mirror of https://github.com/citusdata/citus.git
Remove Postgres 10 support
parent
95633416f7
commit
74cb168205
|
|
@ -2543,7 +2543,7 @@ if test -z "$version_num"; then
|
||||||
as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5
|
as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$version_num" != '10' -a "$version_num" != '11' -a "$version_num" != '12'; then
|
if test "$version_num" != '11' -a "$version_num" != '12'; then
|
||||||
as_fn_error $? "Citus is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5
|
as_fn_error $? "Citus is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5
|
||||||
else
|
else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.])
|
AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$version_num" != '10' -a "$version_num" != '11' -a "$version_num" != '12'; then
|
if test "$version_num" != '11' -a "$version_num" != '12'; then
|
||||||
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
|
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
|
||||||
else
|
else
|
||||||
AC_MSG_NOTICE([building against PostgreSQL $version_num])
|
AC_MSG_NOTICE([building against PostgreSQL $version_num])
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
|
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "distributed/citus_ruleutils.h"
|
#include "distributed/citus_ruleutils.h"
|
||||||
|
|
@ -207,6 +205,3 @@ CallFuncExprRemotely(CallStmt *callStmt, DistObjectCacheEntry *procedure,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* PG_VERSION_NUM >= 110000 */
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/pg_am.h"
|
#include "catalog/pg_am.h"
|
||||||
#include "catalog/pg_attribute.h"
|
#include "catalog/pg_attribute.h"
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
|
||||||
#endif
|
|
||||||
#include "catalog/pg_enum.h"
|
#include "catalog/pg_enum.h"
|
||||||
#include "catalog/pg_extension.h"
|
#include "catalog/pg_extension.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
|
|
@ -1166,7 +1163,7 @@ CreateTruncateTrigger(Oid relationId)
|
||||||
trigger->whenClause = NULL;
|
trigger->whenClause = NULL;
|
||||||
trigger->isconstraint = false;
|
trigger->isconstraint = false;
|
||||||
|
|
||||||
CreateTriggerInternal(trigger, NULL, relationId, InvalidOid, InvalidOid, InvalidOid,
|
CreateTrigger(trigger, NULL, relationId, InvalidOid, InvalidOid, InvalidOid,
|
||||||
InvalidOid, InvalidOid, NULL,
|
InvalidOid, InvalidOid, NULL,
|
||||||
internal, false);
|
internal, false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,6 @@
|
||||||
#if (PG_VERSION_NUM >= 120000)
|
#if (PG_VERSION_NUM >= 120000)
|
||||||
#include "access/genam.h"
|
#include "access/genam.h"
|
||||||
#endif
|
#endif
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
|
||||||
#endif
|
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "distributed/colocation_utils.h"
|
#include "distributed/colocation_utils.h"
|
||||||
#include "distributed/commands.h"
|
#include "distributed/commands.h"
|
||||||
|
|
@ -151,7 +148,8 @@ ErrorIfUnsupportedForeignConstraintExists(Relation relation, char referencingDis
|
||||||
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
||||||
relation->rd_id);
|
relation->rd_id);
|
||||||
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidIndexId, true, NULL,
|
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidTypidNameIndexId,
|
||||||
|
true, NULL,
|
||||||
scanKeyCount, scanKey);
|
scanKeyCount, scanKey);
|
||||||
|
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
heapTuple = systable_getnext(scanDescriptor);
|
||||||
|
|
@ -515,7 +513,8 @@ GetTableForeignConstraintCommands(Oid relationId)
|
||||||
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
||||||
relationId);
|
relationId);
|
||||||
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidIndexId, true, NULL,
|
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidTypidNameIndexId,
|
||||||
|
true, NULL,
|
||||||
scanKeyCount, scanKey);
|
scanKeyCount, scanKey);
|
||||||
|
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
heapTuple = systable_getnext(scanDescriptor);
|
||||||
|
|
@ -523,11 +522,7 @@ GetTableForeignConstraintCommands(Oid relationId)
|
||||||
{
|
{
|
||||||
Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
|
Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
bool inheritedConstraint = OidIsValid(constraintForm->conparentid);
|
bool inheritedConstraint = OidIsValid(constraintForm->conparentid);
|
||||||
#else
|
|
||||||
bool inheritedConstraint = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!inheritedConstraint && constraintForm->contype == CONSTRAINT_FOREIGN)
|
if (!inheritedConstraint && constraintForm->contype == CONSTRAINT_FOREIGN)
|
||||||
{
|
{
|
||||||
|
|
@ -571,7 +566,8 @@ HasForeignKeyToReferenceTable(Oid relationId)
|
||||||
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
|
||||||
relationId);
|
relationId);
|
||||||
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidIndexId, true, NULL,
|
scanDescriptor = systable_beginscan(pgConstraint, ConstraintRelidTypidNameIndexId,
|
||||||
|
true, NULL,
|
||||||
scanKeyCount, scanKey);
|
scanKeyCount, scanKey);
|
||||||
|
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
heapTuple = systable_getnext(scanDescriptor);
|
||||||
|
|
@ -679,7 +675,7 @@ HeapTupleOfForeignConstraintIncludesColumn(HeapTuple heapTuple, Oid relationId,
|
||||||
{
|
{
|
||||||
AttrNumber attrNo = DatumGetInt16(columnArray[attrIdx]);
|
AttrNumber attrNo = DatumGetInt16(columnArray[attrIdx]);
|
||||||
|
|
||||||
char *colName = get_attname_internal(relationId, attrNo, false);
|
char *colName = get_attname(relationId, attrNo, false);
|
||||||
if (strncmp(colName, columnName, NAMEDATALEN) == 0)
|
if (strncmp(colName, columnName, NAMEDATALEN) == 0)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,8 @@ static void ErrorIfFunctionDependsOnExtension(const ObjectAddress *functionAddre
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(create_distributed_function);
|
PG_FUNCTION_INFO_V1(create_distributed_function);
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
#define AssertIsFunctionOrProcedure(objtype) \
|
#define AssertIsFunctionOrProcedure(objtype) \
|
||||||
Assert((objtype) == OBJECT_FUNCTION || (objtype) == OBJECT_PROCEDURE)
|
Assert((objtype) == OBJECT_FUNCTION || (objtype) == OBJECT_PROCEDURE)
|
||||||
#else
|
|
||||||
#define AssertIsFunctionOrProcedure(objtype) \
|
|
||||||
Assert(objtype == OBJECT_FUNCTION)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -597,9 +592,7 @@ GetFunctionAlterOwnerCommand(const RegProcedure funcOid)
|
||||||
|
|
||||||
procOwner = procform->proowner;
|
procOwner = procform->proowner;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
isProcedure = procform->prokind == PROKIND_PROCEDURE;
|
isProcedure = procform->prokind == PROKIND_PROCEDURE;
|
||||||
#endif
|
|
||||||
|
|
||||||
ReleaseSysCache(proctup);
|
ReleaseSysCache(proctup);
|
||||||
}
|
}
|
||||||
|
|
@ -878,12 +871,10 @@ CreateFunctionStmtObjectAddress(CreateFunctionStmt *stmt, bool missing_ok)
|
||||||
ObjectWithArgs *objectWithArgs = NULL;
|
ObjectWithArgs *objectWithArgs = NULL;
|
||||||
ListCell *parameterCell = NULL;
|
ListCell *parameterCell = NULL;
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
if (stmt->is_procedure)
|
if (stmt->is_procedure)
|
||||||
{
|
{
|
||||||
objectType = OBJECT_PROCEDURE;
|
objectType = OBJECT_PROCEDURE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
objectWithArgs = makeNode(ObjectWithArgs);
|
objectWithArgs = makeNode(ObjectWithArgs);
|
||||||
objectWithArgs->objname = stmt->funcname;
|
objectWithArgs->objname = stmt->funcname;
|
||||||
|
|
@ -910,10 +901,7 @@ PlanAlterFunctionStmt(AlterFunctionStmt *stmt, const char *queryString)
|
||||||
const ObjectAddress *address = NULL;
|
const ObjectAddress *address = NULL;
|
||||||
List *commands = NIL;
|
List *commands = NIL;
|
||||||
|
|
||||||
/* AlterFunctionStmt->objtype has only been added since pg11 */
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
AssertIsFunctionOrProcedure(stmt->objtype);
|
AssertIsFunctionOrProcedure(stmt->objtype);
|
||||||
#endif
|
|
||||||
|
|
||||||
address = GetObjectAddressFromParseTree((Node *) stmt, false);
|
address = GetObjectAddressFromParseTree((Node *) stmt, false);
|
||||||
if (!ShouldPropagateAlterFunction(address))
|
if (!ShouldPropagateAlterFunction(address))
|
||||||
|
|
@ -1249,13 +1237,7 @@ ProcessAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryStr
|
||||||
const ObjectAddress *
|
const ObjectAddress *
|
||||||
AlterFunctionStmtObjectAddress(AlterFunctionStmt *stmt, bool missing_ok)
|
AlterFunctionStmtObjectAddress(AlterFunctionStmt *stmt, bool missing_ok)
|
||||||
{
|
{
|
||||||
ObjectType objectType = OBJECT_FUNCTION;
|
return FunctionToObjectAddress(stmt->objtype, stmt->func, missing_ok);
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
objectType = stmt->objtype;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return FunctionToObjectAddress(objectType, stmt->func, missing_ok);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1303,7 +1285,7 @@ AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_o
|
||||||
AssertIsFunctionOrProcedure(stmt->objectType);
|
AssertIsFunctionOrProcedure(stmt->objectType);
|
||||||
|
|
||||||
objectWithArgs = castNode(ObjectWithArgs, stmt->object);
|
objectWithArgs = castNode(ObjectWithArgs, stmt->object);
|
||||||
funcOid = LookupFuncWithArgsCompat(stmt->objectType, objectWithArgs, true);
|
funcOid = LookupFuncWithArgs(stmt->objectType, objectWithArgs, true);
|
||||||
names = objectWithArgs->objname;
|
names = objectWithArgs->objname;
|
||||||
|
|
||||||
if (funcOid == InvalidOid)
|
if (funcOid == InvalidOid)
|
||||||
|
|
@ -1322,7 +1304,7 @@ AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_o
|
||||||
* error if the type didn't exist in the first place.
|
* error if the type didn't exist in the first place.
|
||||||
*/
|
*/
|
||||||
objectWithArgs->objname = newNames;
|
objectWithArgs->objname = newNames;
|
||||||
funcOid = LookupFuncWithArgsCompat(stmt->objectType, objectWithArgs, true);
|
funcOid = LookupFuncWithArgs(stmt->objectType, objectWithArgs, true);
|
||||||
objectWithArgs->objname = names; /* restore the original names */
|
objectWithArgs->objname = names; /* restore the original names */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1336,7 +1318,7 @@ AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_o
|
||||||
* has just been created (if possible at all). For safety we assign the
|
* has just been created (if possible at all). For safety we assign the
|
||||||
* funcOid.
|
* funcOid.
|
||||||
*/
|
*/
|
||||||
funcOid = LookupFuncWithArgsCompat(stmt->objectType, objectWithArgs,
|
funcOid = LookupFuncWithArgs(stmt->objectType, objectWithArgs,
|
||||||
missing_ok);
|
missing_ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1363,7 +1345,7 @@ FunctionToObjectAddress(ObjectType objectType, ObjectWithArgs *objectWithArgs,
|
||||||
|
|
||||||
AssertIsFunctionOrProcedure(objectType);
|
AssertIsFunctionOrProcedure(objectType);
|
||||||
|
|
||||||
funcOid = LookupFuncWithArgsCompat(objectType, objectWithArgs, missing_ok);
|
funcOid = LookupFuncWithArgs(objectType, objectWithArgs, missing_ok);
|
||||||
address = palloc0(sizeof(ObjectAddress));
|
address = palloc0(sizeof(ObjectAddress));
|
||||||
ObjectAddressSet(*address, ProcedureRelationId, funcOid);
|
ObjectAddressSet(*address, ProcedureRelationId, funcOid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ PlanReindexStmt(ReindexStmt *reindexStatement, const char *reindexCommand)
|
||||||
#endif
|
#endif
|
||||||
state.locked_table_oid = InvalidOid;
|
state.locked_table_oid = InvalidOid;
|
||||||
|
|
||||||
indOid = RangeVarGetRelidInternal(reindexStatement->relation,
|
indOid = RangeVarGetRelidExtended(reindexStatement->relation,
|
||||||
lockmode, 0,
|
lockmode, 0,
|
||||||
RangeVarCallbackForReindexIndex,
|
RangeVarCallbackForReindexIndex,
|
||||||
&state);
|
&state);
|
||||||
|
|
@ -243,7 +243,7 @@ PlanReindexStmt(ReindexStmt *reindexStatement, const char *reindexCommand)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RangeVarGetRelidInternal(reindexStatement->relation, lockmode, 0,
|
RangeVarGetRelidExtended(reindexStatement->relation, lockmode, 0,
|
||||||
RangeVarCallbackOwnsTable, NULL);
|
RangeVarCallbackOwnsTable, NULL);
|
||||||
|
|
||||||
relation = heap_openrv(reindexStatement->relation, NoLock);
|
relation = heap_openrv(reindexStatement->relation, NoLock);
|
||||||
|
|
@ -349,7 +349,7 @@ PlanDropIndexStmt(DropStmt *dropIndexStatement, const char *dropIndexCommand)
|
||||||
state.heapOid = InvalidOid;
|
state.heapOid = InvalidOid;
|
||||||
state.concurrent = dropIndexStatement->concurrent;
|
state.concurrent = dropIndexStatement->concurrent;
|
||||||
|
|
||||||
indexId = RangeVarGetRelidInternal(rangeVar, lockmode, rvrFlags,
|
indexId = RangeVarGetRelidExtended(rangeVar, lockmode, rvrFlags,
|
||||||
RangeVarCallbackForDropIndex,
|
RangeVarCallbackForDropIndex,
|
||||||
(void *) &state);
|
(void *) &state);
|
||||||
|
|
||||||
|
|
@ -654,10 +654,8 @@ RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, voi
|
||||||
*/
|
*/
|
||||||
expected_relkind = classform->relkind;
|
expected_relkind = classform->relkind;
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
if (expected_relkind == RELKIND_PARTITIONED_INDEX)
|
if (expected_relkind == RELKIND_PARTITIONED_INDEX)
|
||||||
expected_relkind = RELKIND_INDEX;
|
expected_relkind = RELKIND_INDEX;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (expected_relkind != relkind)
|
if (expected_relkind != relkind)
|
||||||
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
|
|
@ -667,7 +665,7 @@ RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, voi
|
||||||
if (!pg_class_ownercheck(relOid, GetUserId()) &&
|
if (!pg_class_ownercheck(relOid, GetUserId()) &&
|
||||||
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
|
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
|
||||||
{
|
{
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACLCHECK_OBJECT_INDEX, rel->relname);
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX, rel->relname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allowSystemTableMods && IsSystemClass(relOid, classform))
|
if (!allowSystemTableMods && IsSystemClass(relOid, classform))
|
||||||
|
|
@ -747,11 +745,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelI
|
||||||
relkind = get_rel_relkind(relId);
|
relkind = get_rel_relkind(relId);
|
||||||
if (!relkind)
|
if (!relkind)
|
||||||
return;
|
return;
|
||||||
if (relkind != RELKIND_INDEX
|
if (relkind != RELKIND_INDEX && relkind != RELKIND_PARTITIONED_INDEX)
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
&& relkind != RELKIND_PARTITIONED_INDEX
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("\"%s\" is not an index", relation->relname)));
|
errmsg("\"%s\" is not an index", relation->relname)));
|
||||||
|
|
|
||||||
|
|
@ -121,9 +121,7 @@ PlanAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString)
|
||||||
return PlanAlterTypeSchemaStmt(stmt, queryString);
|
return PlanAlterTypeSchemaStmt(stmt, queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return PlanAlterFunctionSchemaStmt(stmt, queryString);
|
return PlanAlterFunctionSchemaStmt(stmt, queryString);
|
||||||
|
|
@ -198,9 +196,7 @@ ProcessAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryStrin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
ProcessAlterFunctionSchemaStmt(stmt, queryString);
|
ProcessAlterFunctionSchemaStmt(stmt, queryString);
|
||||||
|
|
|
||||||
|
|
@ -857,7 +857,7 @@ ErrorIfUnsupportedConstraint(Relation relation, char distributionMethod,
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeCount = indexInfo->ii_NumIndexAttrs;
|
attributeCount = indexInfo->ii_NumIndexAttrs;
|
||||||
attributeNumberArray = IndexInfoAttributeNumberArray(indexInfo);
|
attributeNumberArray = indexInfo->ii_IndexAttrNumbers;
|
||||||
|
|
||||||
for (attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++)
|
for (attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
|
||||||
|
|
||||||
parsetree = ProcessCreateSubscriptionStmt(createSubStmt);
|
parsetree = ProcessCreateSubscriptionStmt(createSubStmt);
|
||||||
}
|
}
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
if (IsA(parsetree, CallStmt))
|
if (IsA(parsetree, CallStmt))
|
||||||
{
|
{
|
||||||
CallStmt *callStmt = (CallStmt *) parsetree;
|
CallStmt *callStmt = (CallStmt *) parsetree;
|
||||||
|
|
@ -253,7 +253,6 @@ multi_ProcessUtility(PlannedStmt *pstmt,
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (IsA(parsetree, DoStmt))
|
if (IsA(parsetree, DoStmt))
|
||||||
{
|
{
|
||||||
|
|
@ -426,9 +425,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
ddlJobs = PlanDropFunctionStmt(dropStatement, queryString);
|
ddlJobs = PlanDropFunctionStmt(dropStatement, queryString);
|
||||||
|
|
@ -484,9 +481,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
ddlJobs = PlanRenameFunctionStmt(renameStmt, queryString);
|
ddlJobs = PlanRenameFunctionStmt(renameStmt, queryString);
|
||||||
|
|
@ -843,9 +838,7 @@ PlanAlterOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
|
||||||
return PlanAlterTypeOwnerStmt(stmt, queryString);
|
return PlanAlterTypeOwnerStmt(stmt, queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return PlanAlterFunctionOwnerStmt(stmt, queryString);
|
return PlanAlterFunctionOwnerStmt(stmt, queryString);
|
||||||
|
|
@ -871,9 +864,7 @@ PlanAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, const char *queryString
|
||||||
{
|
{
|
||||||
switch (stmt->objectType)
|
switch (stmt->objectType)
|
||||||
{
|
{
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return PlanAlterFunctionDependsStmt(stmt, queryString);
|
return PlanAlterFunctionDependsStmt(stmt, queryString);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ static List * VacuumTaskList(Oid relationId, CitusVacuumParams vacuumParams,
|
||||||
List *vacuumColumnList);
|
List *vacuumColumnList);
|
||||||
static StringInfo DeparseVacuumStmtPrefix(CitusVacuumParams vacuumParams);
|
static StringInfo DeparseVacuumStmtPrefix(CitusVacuumParams vacuumParams);
|
||||||
static char * DeparseVacuumColumnNames(List *columnNameList);
|
static char * DeparseVacuumColumnNames(List *columnNameList);
|
||||||
|
static List * VacuumColumnList(VacuumStmt *vacuumStmt, int relationIndex);
|
||||||
|
static List * ExtractVacuumTargetRels(VacuumStmt *vacuumStmt);
|
||||||
static CitusVacuumParams VacuumStmtParams(VacuumStmt *vacstmt);
|
static CitusVacuumParams VacuumStmtParams(VacuumStmt *vacstmt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -379,6 +381,40 @@ DeparseVacuumColumnNames(List *columnNameList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VacuumColumnList returns list of columns from relation
|
||||||
|
* in the vacuum statement at specified relationIndex.
|
||||||
|
*/
|
||||||
|
static List *
|
||||||
|
VacuumColumnList(VacuumStmt *vacuumStmt, int relationIndex)
|
||||||
|
{
|
||||||
|
VacuumRelation *vacuumRelation = (VacuumRelation *) list_nth(vacuumStmt->rels,
|
||||||
|
relationIndex);
|
||||||
|
|
||||||
|
return vacuumRelation->va_cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ExtractVacuumTargetRels returns list of target
|
||||||
|
* relations from vacuum statement.
|
||||||
|
*/
|
||||||
|
static List *
|
||||||
|
ExtractVacuumTargetRels(VacuumStmt *vacuumStmt)
|
||||||
|
{
|
||||||
|
List *vacuumList = NIL;
|
||||||
|
|
||||||
|
ListCell *vacuumRelationCell = NULL;
|
||||||
|
foreach(vacuumRelationCell, vacuumStmt->rels)
|
||||||
|
{
|
||||||
|
VacuumRelation *vacuumRelation = (VacuumRelation *) lfirst(vacuumRelationCell);
|
||||||
|
vacuumList = lappend(vacuumList, vacuumRelation->relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vacuumList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VacuumStmtParams returns a CitusVacuumParams based on the supplied VacuumStmt.
|
* VacuumStmtParams returns a CitusVacuumParams based on the supplied VacuumStmt.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,7 @@ DeparseDropStmt(DropStmt *stmt)
|
||||||
return DeparseDropTypeStmt(stmt);
|
return DeparseDropTypeStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return DeparseDropFunctionStmt(stmt);
|
return DeparseDropFunctionStmt(stmt);
|
||||||
|
|
@ -188,9 +186,7 @@ DeparseRenameStmt(RenameStmt *stmt)
|
||||||
return DeparseRenameAttributeStmt(stmt);
|
return DeparseRenameAttributeStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return DeparseRenameFunctionStmt(stmt);
|
return DeparseRenameFunctionStmt(stmt);
|
||||||
|
|
@ -243,9 +239,7 @@ DeparseAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
|
||||||
return DeparseAlterTypeSchemaStmt(stmt);
|
return DeparseAlterTypeSchemaStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return DeparseAlterFunctionSchemaStmt(stmt);
|
return DeparseAlterFunctionSchemaStmt(stmt);
|
||||||
|
|
@ -277,9 +271,7 @@ DeparseAlterOwnerStmt(AlterOwnerStmt *stmt)
|
||||||
return DeparseAlterTypeOwnerStmt(stmt);
|
return DeparseAlterTypeOwnerStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return DeparseAlterFunctionOwnerStmt(stmt);
|
return DeparseAlterFunctionOwnerStmt(stmt);
|
||||||
|
|
@ -306,9 +298,7 @@ DeparseAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
|
||||||
{
|
{
|
||||||
switch (stmt->objectType)
|
switch (stmt->objectType)
|
||||||
{
|
{
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return DeparseAlterFunctionDependsStmt(stmt);
|
return DeparseAlterFunctionDependsStmt(stmt);
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,6 @@ AppendAlterFunctionStmt(StringInfo buf, AlterFunctionStmt *stmt)
|
||||||
{
|
{
|
||||||
ListCell *actionCell = NULL;
|
ListCell *actionCell = NULL;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
|
||||||
|
|
||||||
AppendFunctionName(buf, stmt->func, OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
if (stmt->objtype == OBJECT_FUNCTION)
|
if (stmt->objtype == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
appendStringInfo(buf, "ALTER FUNCTION ");
|
||||||
|
|
@ -101,7 +96,6 @@ AppendAlterFunctionStmt(StringInfo buf, AlterFunctionStmt *stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendFunctionName(buf, stmt->func, stmt->objtype);
|
AppendFunctionName(buf, stmt->func, stmt->objtype);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
foreach(actionCell, stmt->actions)
|
foreach(actionCell, stmt->actions)
|
||||||
|
|
@ -304,11 +298,7 @@ DeparseRenameFunctionStmt(RenameStmt *stmt)
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->renameType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->renameType == OBJECT_FUNCTION || stmt->renameType == OBJECT_PROCEDURE);
|
Assert(stmt->renameType == OBJECT_FUNCTION || stmt->renameType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendRenameFunctionStmt(&str, stmt);
|
AppendRenameFunctionStmt(&str, stmt);
|
||||||
|
|
||||||
|
|
@ -324,9 +314,6 @@ AppendRenameFunctionStmt(StringInfo buf, RenameStmt *stmt)
|
||||||
{
|
{
|
||||||
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
|
||||||
#else
|
|
||||||
if (stmt->renameType == OBJECT_FUNCTION)
|
if (stmt->renameType == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER FUNCTION ");
|
appendStringInfoString(buf, "ALTER FUNCTION ");
|
||||||
|
|
@ -335,7 +322,6 @@ AppendRenameFunctionStmt(StringInfo buf, RenameStmt *stmt)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendFunctionName(buf, func, stmt->renameType);
|
AppendFunctionName(buf, func, stmt->renameType);
|
||||||
|
|
||||||
|
|
@ -352,11 +338,7 @@ DeparseAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt)
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendAlterFunctionSchemaStmt(&str, stmt);
|
AppendAlterFunctionSchemaStmt(&str, stmt);
|
||||||
|
|
||||||
|
|
@ -372,9 +354,6 @@ AppendAlterFunctionSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
|
||||||
{
|
{
|
||||||
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
|
||||||
#else
|
|
||||||
if (stmt->objectType == OBJECT_FUNCTION)
|
if (stmt->objectType == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER FUNCTION ");
|
appendStringInfoString(buf, "ALTER FUNCTION ");
|
||||||
|
|
@ -383,7 +362,6 @@ AppendAlterFunctionSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendFunctionName(buf, func, stmt->objectType);
|
AppendFunctionName(buf, func, stmt->objectType);
|
||||||
appendStringInfo(buf, " SET SCHEMA %s;", quote_identifier(stmt->newschema));
|
appendStringInfo(buf, " SET SCHEMA %s;", quote_identifier(stmt->newschema));
|
||||||
|
|
@ -399,11 +377,7 @@ DeparseAlterFunctionOwnerStmt(AlterOwnerStmt *stmt)
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendAlterFunctionOwnerStmt(&str, stmt);
|
AppendAlterFunctionOwnerStmt(&str, stmt);
|
||||||
|
|
||||||
|
|
@ -419,9 +393,6 @@ AppendAlterFunctionOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
|
||||||
{
|
{
|
||||||
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
|
||||||
#else
|
|
||||||
if (stmt->objectType == OBJECT_FUNCTION)
|
if (stmt->objectType == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER FUNCTION ");
|
appendStringInfoString(buf, "ALTER FUNCTION ");
|
||||||
|
|
@ -430,7 +401,6 @@ AppendAlterFunctionOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendFunctionName(buf, func, stmt->objectType);
|
AppendFunctionName(buf, func, stmt->objectType);
|
||||||
appendStringInfo(buf, " OWNER TO %s;", RoleSpecString(stmt->newowner));
|
appendStringInfo(buf, " OWNER TO %s;", RoleSpecString(stmt->newowner));
|
||||||
|
|
@ -446,11 +416,7 @@ DeparseAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt)
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendAlterFunctionDependsStmt(&str, stmt);
|
AppendAlterFunctionDependsStmt(&str, stmt);
|
||||||
|
|
||||||
|
|
@ -466,9 +432,6 @@ AppendAlterFunctionDependsStmt(StringInfo buf, AlterObjectDependsStmt *stmt)
|
||||||
{
|
{
|
||||||
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
ObjectWithArgs *func = castNode(ObjectWithArgs, stmt->object);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "ALTER FUNCTION ");
|
|
||||||
#else
|
|
||||||
if (stmt->objectType == OBJECT_FUNCTION)
|
if (stmt->objectType == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER FUNCTION ");
|
appendStringInfoString(buf, "ALTER FUNCTION ");
|
||||||
|
|
@ -477,7 +440,6 @@ AppendAlterFunctionDependsStmt(StringInfo buf, AlterObjectDependsStmt *stmt)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
appendStringInfoString(buf, "ALTER PROCEDURE ");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendFunctionName(buf, func, stmt->objectType);
|
AppendFunctionName(buf, func, stmt->objectType);
|
||||||
appendStringInfo(buf, " DEPENDS ON EXTENSION %s;", strVal(stmt->extname));
|
appendStringInfo(buf, " DEPENDS ON EXTENSION %s;", strVal(stmt->extname));
|
||||||
|
|
@ -493,11 +455,7 @@ DeparseDropFunctionStmt(DropStmt *stmt)
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->removeType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->removeType == OBJECT_FUNCTION || stmt->removeType == OBJECT_PROCEDURE);
|
Assert(stmt->removeType == OBJECT_FUNCTION || stmt->removeType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendDropFunctionStmt(&str, stmt);
|
AppendDropFunctionStmt(&str, stmt);
|
||||||
|
|
||||||
|
|
@ -511,9 +469,6 @@ DeparseDropFunctionStmt(DropStmt *stmt)
|
||||||
static void
|
static void
|
||||||
AppendDropFunctionStmt(StringInfo buf, DropStmt *stmt)
|
AppendDropFunctionStmt(StringInfo buf, DropStmt *stmt)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
appendStringInfo(buf, "DROP FUNCTION ");
|
|
||||||
#else
|
|
||||||
if (stmt->removeType == OBJECT_FUNCTION)
|
if (stmt->removeType == OBJECT_FUNCTION)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "DROP FUNCTION ");
|
appendStringInfoString(buf, "DROP FUNCTION ");
|
||||||
|
|
@ -522,7 +477,6 @@ AppendDropFunctionStmt(StringInfo buf, DropStmt *stmt)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, "DROP PROCEDURE ");
|
appendStringInfoString(buf, "DROP PROCEDURE ");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (stmt->missing_ok)
|
if (stmt->missing_ok)
|
||||||
{
|
{
|
||||||
|
|
@ -576,7 +530,7 @@ AppendFunctionName(StringInfo buf, ObjectWithArgs *func, ObjectType objtype)
|
||||||
char *schemaName = NULL;
|
char *schemaName = NULL;
|
||||||
char *qualifiedFunctionName;
|
char *qualifiedFunctionName;
|
||||||
|
|
||||||
funcid = LookupFuncWithArgsCompat(objtype, func, true);
|
funcid = LookupFuncWithArgs(objtype, func, true);
|
||||||
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
|
||||||
|
|
||||||
if (!HeapTupleIsValid(proctup))
|
if (!HeapTupleIsValid(proctup))
|
||||||
|
|
|
||||||
|
|
@ -143,9 +143,7 @@ RenameStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
|
||||||
return RenameAttributeStmtObjectAddress(stmt, missing_ok);
|
return RenameAttributeStmtObjectAddress(stmt, missing_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return RenameFunctionStmtObjectAddress(stmt, missing_ok);
|
return RenameFunctionStmtObjectAddress(stmt, missing_ok);
|
||||||
|
|
@ -170,9 +168,7 @@ AlterObjectSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok)
|
||||||
return AlterTypeSchemaStmtObjectAddress(stmt, missing_ok);
|
return AlterTypeSchemaStmtObjectAddress(stmt, missing_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return AlterFunctionSchemaStmtObjectAddress(stmt, missing_ok);
|
return AlterFunctionSchemaStmtObjectAddress(stmt, missing_ok);
|
||||||
|
|
@ -218,9 +214,7 @@ AlterOwnerStmtObjectAddress(AlterOwnerStmt *stmt, bool missing_ok)
|
||||||
return AlterTypeOwnerObjectAddress(stmt, missing_ok);
|
return AlterTypeOwnerObjectAddress(stmt, missing_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return AlterFunctionOwnerObjectAddress(stmt, missing_ok);
|
return AlterFunctionOwnerObjectAddress(stmt, missing_ok);
|
||||||
|
|
@ -250,9 +244,7 @@ AlterObjectDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, bool missing_o
|
||||||
{
|
{
|
||||||
switch (stmt->objectType)
|
switch (stmt->objectType)
|
||||||
{
|
{
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
{
|
{
|
||||||
return AlterFunctionDependsStmtObjectAddress(stmt, missing_ok);
|
return AlterFunctionDependsStmtObjectAddress(stmt, missing_ok);
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,7 @@ QualifyRenameStmt(RenameStmt *stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
QualifyRenameFunctionStmt(stmt);
|
QualifyRenameFunctionStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
@ -199,9 +197,7 @@ QualifyAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
QualifyAlterFunctionSchemaStmt(stmt);
|
QualifyAlterFunctionSchemaStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
@ -227,9 +223,7 @@ QualifyAlterOwnerStmt(AlterOwnerStmt *stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
QualifyAlterFunctionOwnerStmt(stmt);
|
QualifyAlterFunctionOwnerStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
@ -248,9 +242,7 @@ QualifyAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
|
||||||
switch (stmt->objectType)
|
switch (stmt->objectType)
|
||||||
{
|
{
|
||||||
case OBJECT_FUNCTION:
|
case OBJECT_FUNCTION:
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
case OBJECT_PROCEDURE:
|
case OBJECT_PROCEDURE:
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
QualifyAlterFunctionDependsStmt(stmt);
|
QualifyAlterFunctionDependsStmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,7 @@ void QualifyFunctionSchemaName(ObjectWithArgs *func, ObjectType type);
|
||||||
void
|
void
|
||||||
QualifyAlterFunctionStmt(AlterFunctionStmt *stmt)
|
QualifyAlterFunctionStmt(AlterFunctionStmt *stmt)
|
||||||
{
|
{
|
||||||
ObjectType objtype = OBJECT_FUNCTION;
|
QualifyFunction(stmt->func, stmt->objtype);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
objtype = stmt->objtype;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QualifyFunction(stmt->func, objtype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -61,11 +55,7 @@ QualifyAlterFunctionStmt(AlterFunctionStmt *stmt)
|
||||||
void
|
void
|
||||||
QualifyRenameFunctionStmt(RenameStmt *stmt)
|
QualifyRenameFunctionStmt(RenameStmt *stmt)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->renameType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->renameType == OBJECT_FUNCTION || stmt->renameType == OBJECT_PROCEDURE);
|
Assert(stmt->renameType == OBJECT_FUNCTION || stmt->renameType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->renameType);
|
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->renameType);
|
||||||
}
|
}
|
||||||
|
|
@ -79,11 +69,7 @@ QualifyRenameFunctionStmt(RenameStmt *stmt)
|
||||||
void
|
void
|
||||||
QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt)
|
QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
||||||
}
|
}
|
||||||
|
|
@ -97,11 +83,7 @@ QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt)
|
||||||
void
|
void
|
||||||
QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt)
|
QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
||||||
}
|
}
|
||||||
|
|
@ -115,11 +97,7 @@ QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt)
|
||||||
void
|
void
|
||||||
QualifyAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt)
|
QualifyAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION);
|
|
||||||
#else
|
|
||||||
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
Assert(stmt->objectType == OBJECT_FUNCTION || stmt->objectType == OBJECT_PROCEDURE);
|
||||||
#endif
|
|
||||||
|
|
||||||
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +134,7 @@ QualifyFunctionSchemaName(ObjectWithArgs *func, ObjectType type)
|
||||||
Oid funcid = InvalidOid;
|
Oid funcid = InvalidOid;
|
||||||
HeapTuple proctup;
|
HeapTuple proctup;
|
||||||
|
|
||||||
funcid = LookupFuncWithArgsCompat(type, func, true);
|
funcid = LookupFuncWithArgs(type, func, true);
|
||||||
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -684,15 +684,9 @@ SortTupleStore(CitusScanState *scanState)
|
||||||
sortKeyIndex++;
|
sortKeyIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
tuplesortstate =
|
tuplesortstate =
|
||||||
tuplesort_begin_heap(tupleDescriptor, numberOfSortKeys, sortColIdx, sortOperators,
|
tuplesort_begin_heap(tupleDescriptor, numberOfSortKeys, sortColIdx, sortOperators,
|
||||||
collations, nullsFirst, work_mem, NULL, false);
|
collations, nullsFirst, work_mem, NULL, false);
|
||||||
#else
|
|
||||||
tuplesortstate =
|
|
||||||
tuplesort_begin_heap(tupleDescriptor, numberOfSortKeys, sortColIdx, sortOperators,
|
|
||||||
collations, nullsFirst, work_mem, false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1362,7 +1362,7 @@ EnsureTablePermissions(Oid relationId, AclMode mode)
|
||||||
|
|
||||||
if (aclresult != ACLCHECK_OK)
|
if (aclresult != ACLCHECK_OK)
|
||||||
{
|
{
|
||||||
aclcheck_error(aclresult, ACLCHECK_OBJECT_TABLE, get_rel_name(relationId));
|
aclcheck_error(aclresult, OBJECT_TABLE, get_rel_name(relationId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1376,7 +1376,7 @@ EnsureTableOwner(Oid relationId)
|
||||||
{
|
{
|
||||||
if (!pg_class_ownercheck(relationId, GetUserId()))
|
if (!pg_class_ownercheck(relationId, GetUserId()))
|
||||||
{
|
{
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACLCHECK_OBJECT_TABLE,
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE,
|
||||||
get_rel_name(relationId));
|
get_rel_name(relationId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1391,7 +1391,7 @@ EnsureSchemaOwner(Oid schemaId)
|
||||||
{
|
{
|
||||||
if (!pg_namespace_ownercheck(schemaId, GetUserId()))
|
if (!pg_namespace_ownercheck(schemaId, GetUserId()))
|
||||||
{
|
{
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACLCHECK_OBJECT_SCHEMA,
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
|
||||||
get_namespace_name(schemaId));
|
get_namespace_name(schemaId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1406,7 +1406,7 @@ EnsureSequenceOwner(Oid sequenceOid)
|
||||||
{
|
{
|
||||||
if (!pg_class_ownercheck(sequenceOid, GetUserId()))
|
if (!pg_class_ownercheck(sequenceOid, GetUserId()))
|
||||||
{
|
{
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACLCHECK_OBJECT_SEQUENCE,
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SEQUENCE,
|
||||||
get_rel_name(sequenceOid));
|
get_rel_name(sequenceOid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,6 @@
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_class.h"
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
|
||||||
#endif
|
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
|
|
|
||||||
|
|
@ -1108,8 +1108,7 @@ WorkerShardStats(ShardPlacement *placement, Oid relationId, char *shardName,
|
||||||
|
|
||||||
/* fill in the partition column name and shard name in the query. */
|
/* fill in the partition column name and shard name in the query. */
|
||||||
partitionColumn = PartitionColumn(relationId, unusedTableId);
|
partitionColumn = PartitionColumn(relationId, unusedTableId);
|
||||||
partitionColumnName = get_attname_internal(relationId, partitionColumn->varattno,
|
partitionColumnName = get_attname(relationId, partitionColumn->varattno, false);
|
||||||
false);
|
|
||||||
appendStringInfo(partitionValueQuery, SHARD_RANGE_QUERY,
|
appendStringInfo(partitionValueQuery, SHARD_RANGE_QUERY,
|
||||||
partitionColumnName, partitionColumnName, shardName);
|
partitionColumnName, partitionColumnName, shardName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,9 +276,7 @@ ClusterHasDistributedFunctionWithDistArgument(void)
|
||||||
|
|
||||||
Relation pgDistObjectRel = heap_open(DistObjectRelationId(), AccessShareLock);
|
Relation pgDistObjectRel = heap_open(DistObjectRelationId(), AccessShareLock);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
TupleDesc tupleDescriptor = RelationGetDescr(pgDistObjectRel);
|
TupleDesc tupleDescriptor = RelationGetDescr(pgDistObjectRel);
|
||||||
#endif
|
|
||||||
|
|
||||||
pgDistObjectScan =
|
pgDistObjectScan =
|
||||||
systable_beginscan(pgDistObjectRel, InvalidOid, false, NULL, 0, NULL);
|
systable_beginscan(pgDistObjectRel, InvalidOid, false, NULL, 0, NULL);
|
||||||
|
|
@ -290,16 +288,10 @@ ClusterHasDistributedFunctionWithDistArgument(void)
|
||||||
if (pg_dist_object->classid == ProcedureRelationId)
|
if (pg_dist_object->classid == ProcedureRelationId)
|
||||||
{
|
{
|
||||||
bool distArgumentIsNull = false;
|
bool distArgumentIsNull = false;
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
distArgumentIsNull =
|
distArgumentIsNull =
|
||||||
heap_attisnull(pgDistObjectTup,
|
heap_attisnull(pgDistObjectTup,
|
||||||
Anum_pg_dist_object_distribution_argument_index,
|
Anum_pg_dist_object_distribution_argument_index,
|
||||||
tupleDescriptor);
|
tupleDescriptor);
|
||||||
#else
|
|
||||||
distArgumentIsNull =
|
|
||||||
heap_attisnull(pgDistObjectTup,
|
|
||||||
Anum_pg_dist_object_distribution_argument_index);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* we found one distributed function that has an distribution argument */
|
/* we found one distributed function that has an distribution argument */
|
||||||
if (!distArgumentIsNull)
|
if (!distArgumentIsNull)
|
||||||
|
|
|
||||||
|
|
@ -1740,17 +1740,9 @@ HasUnresolvedExternParamsWalker(Node *expression, ParamListInfo boundParams)
|
||||||
/* give hook a chance in case parameter is dynamic */
|
/* give hook a chance in case parameter is dynamic */
|
||||||
if (boundParams->paramFetch != NULL)
|
if (boundParams->paramFetch != NULL)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
ParamExternData externParamPlaceholder;
|
ParamExternData externParamPlaceholder;
|
||||||
externParam = (*boundParams->paramFetch)(boundParams, paramId, false,
|
externParam = (*boundParams->paramFetch)(boundParams, paramId, false,
|
||||||
&externParamPlaceholder);
|
&externParamPlaceholder);
|
||||||
#else
|
|
||||||
externParam = &boundParams->params[paramId - 1];
|
|
||||||
if (!OidIsValid(externParam->ptype))
|
|
||||||
{
|
|
||||||
(*boundParams->paramFetch)(boundParams, paramId);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -91,15 +91,6 @@ static void ExplainOneQuery(Query *query, int cursorOptions,
|
||||||
IntoClause *into, ExplainState *es,
|
IntoClause *into, ExplainState *es,
|
||||||
const char *queryString, ParamListInfo params,
|
const char *queryString, ParamListInfo params,
|
||||||
QueryEnvironment *queryEnv);
|
QueryEnvironment *queryEnv);
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
static void ExplainOpenGroup(const char *objtype, const char *labelname,
|
|
||||||
bool labeled, ExplainState *es);
|
|
||||||
static void ExplainCloseGroup(const char *objtype, const char *labelname,
|
|
||||||
bool labeled, ExplainState *es);
|
|
||||||
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es);
|
|
||||||
static void ExplainJSONLineEnding(ExplainState *es);
|
|
||||||
static void ExplainYAMLLineStarting(ExplainState *es);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -230,7 +221,7 @@ ExplainJob(Job *job, ExplainState *es)
|
||||||
|
|
||||||
ExplainOpenGroup("Job", "Job", true, es);
|
ExplainOpenGroup("Job", "Job", true, es);
|
||||||
|
|
||||||
ExplainPropertyIntegerInternal("Task Count", NULL, taskCount, es);
|
ExplainPropertyInteger("Task Count", NULL, taskCount, es);
|
||||||
|
|
||||||
if (dependedJobCount > 0)
|
if (dependedJobCount > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -306,8 +297,8 @@ ExplainMapMergeJob(MapMergeJob *mapMergeJob, ExplainState *es)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExplainOpenGroup("MapMergeJob", NULL, true, es);
|
ExplainOpenGroup("MapMergeJob", NULL, true, es);
|
||||||
ExplainPropertyIntegerInternal("Map Task Count", NULL, mapTaskCount, es);
|
ExplainPropertyInteger("Map Task Count", NULL, mapTaskCount, es);
|
||||||
ExplainPropertyIntegerInternal("Merge Task Count", NULL, mergeTaskCount, es);
|
ExplainPropertyInteger("Merge Task Count", NULL, mergeTaskCount, es);
|
||||||
|
|
||||||
if (dependedJobCount > 0)
|
if (dependedJobCount > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -649,13 +640,10 @@ ExplainOneQuery(Query *query, int cursorOptions,
|
||||||
{
|
{
|
||||||
/* if an advisor plugin is present, let it manage things */
|
/* if an advisor plugin is present, let it manage things */
|
||||||
if (ExplainOneQuery_hook)
|
if (ExplainOneQuery_hook)
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
{
|
||||||
(*ExplainOneQuery_hook) (query, cursorOptions, into, es,
|
(*ExplainOneQuery_hook) (query, cursorOptions, into, es,
|
||||||
queryString, params, queryEnv);
|
queryString, params, queryEnv);
|
||||||
#elif (PG_VERSION_NUM >= 100000)
|
}
|
||||||
(*ExplainOneQuery_hook) (query, cursorOptions, into, es,
|
|
||||||
queryString, params);
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlannedStmt *plan;
|
PlannedStmt *plan;
|
||||||
|
|
@ -675,182 +663,3 @@ ExplainOneQuery(Query *query, int cursorOptions,
|
||||||
&planduration);
|
&planduration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
/*
|
|
||||||
* Open a group of related objects.
|
|
||||||
*
|
|
||||||
* objtype is the type of the group object, labelname is its label within
|
|
||||||
* a containing object (if any).
|
|
||||||
*
|
|
||||||
* If labeled is true, the group members will be labeled properties,
|
|
||||||
* while if it's false, they'll be unlabeled objects.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ExplainOpenGroup(const char *objtype, const char *labelname,
|
|
||||||
bool labeled, ExplainState *es)
|
|
||||||
{
|
|
||||||
switch (es->format)
|
|
||||||
{
|
|
||||||
case EXPLAIN_FORMAT_TEXT:
|
|
||||||
/* nothing to do */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_XML:
|
|
||||||
ExplainXMLTag(objtype, X_OPENING, es);
|
|
||||||
es->indent++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_JSON:
|
|
||||||
ExplainJSONLineEnding(es);
|
|
||||||
appendStringInfoSpaces(es->str, 2 * es->indent);
|
|
||||||
if (labelname)
|
|
||||||
{
|
|
||||||
escape_json(es->str, labelname);
|
|
||||||
appendStringInfoString(es->str, ": ");
|
|
||||||
}
|
|
||||||
appendStringInfoChar(es->str, labeled ? '{' : '[');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In JSON format, the grouping_stack is an integer list. 0 means
|
|
||||||
* we've emitted nothing at this grouping level, 1 means we've
|
|
||||||
* emitted something (and so the next item needs a comma). See
|
|
||||||
* ExplainJSONLineEnding().
|
|
||||||
*/
|
|
||||||
es->grouping_stack = lcons_int(0, es->grouping_stack);
|
|
||||||
es->indent++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_YAML:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In YAML format, the grouping stack is an integer list. 0 means
|
|
||||||
* we've emitted nothing at this grouping level AND this grouping
|
|
||||||
* level is unlabelled and must be marked with "- ". See
|
|
||||||
* ExplainYAMLLineStarting().
|
|
||||||
*/
|
|
||||||
ExplainYAMLLineStarting(es);
|
|
||||||
if (labelname)
|
|
||||||
{
|
|
||||||
appendStringInfo(es->str, "%s: ", labelname);
|
|
||||||
es->grouping_stack = lcons_int(1, es->grouping_stack);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendStringInfoString(es->str, "- ");
|
|
||||||
es->grouping_stack = lcons_int(0, es->grouping_stack);
|
|
||||||
}
|
|
||||||
es->indent++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close a group of related objects.
|
|
||||||
* Parameters must match the corresponding ExplainOpenGroup call.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ExplainCloseGroup(const char *objtype, const char *labelname,
|
|
||||||
bool labeled, ExplainState *es)
|
|
||||||
{
|
|
||||||
switch (es->format)
|
|
||||||
{
|
|
||||||
case EXPLAIN_FORMAT_TEXT:
|
|
||||||
/* nothing to do */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_XML:
|
|
||||||
es->indent--;
|
|
||||||
ExplainXMLTag(objtype, X_CLOSING, es);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_JSON:
|
|
||||||
es->indent--;
|
|
||||||
appendStringInfoChar(es->str, '\n');
|
|
||||||
appendStringInfoSpaces(es->str, 2 * es->indent);
|
|
||||||
appendStringInfoChar(es->str, labeled ? '}' : ']');
|
|
||||||
es->grouping_stack = list_delete_first(es->grouping_stack);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPLAIN_FORMAT_YAML:
|
|
||||||
es->indent--;
|
|
||||||
es->grouping_stack = list_delete_first(es->grouping_stack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Emit opening or closing XML tag.
|
|
||||||
*
|
|
||||||
* "flags" must contain X_OPENING, X_CLOSING, or X_CLOSE_IMMEDIATE.
|
|
||||||
* Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally
|
|
||||||
* add.
|
|
||||||
*
|
|
||||||
* XML tag names can't contain white space, so we replace any spaces in
|
|
||||||
* "tagname" with dashes.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if ((flags & X_NOWHITESPACE) == 0)
|
|
||||||
appendStringInfoSpaces(es->str, 2 * es->indent);
|
|
||||||
appendStringInfoCharMacro(es->str, '<');
|
|
||||||
if ((flags & X_CLOSING) != 0)
|
|
||||||
appendStringInfoCharMacro(es->str, '/');
|
|
||||||
for (s = tagname; *s; s++)
|
|
||||||
appendStringInfoCharMacro(es->str, (*s == ' ') ? '-' : *s);
|
|
||||||
if ((flags & X_CLOSE_IMMEDIATE) != 0)
|
|
||||||
appendStringInfoString(es->str, " /");
|
|
||||||
appendStringInfoCharMacro(es->str, '>');
|
|
||||||
if ((flags & X_NOWHITESPACE) == 0)
|
|
||||||
appendStringInfoCharMacro(es->str, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Emit a JSON line ending.
|
|
||||||
*
|
|
||||||
* JSON requires a comma after each property but the last. To facilitate this,
|
|
||||||
* in JSON format, the text emitted for each property begins just prior to the
|
|
||||||
* preceding line-break (and comma, if applicable).
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ExplainJSONLineEnding(ExplainState *es)
|
|
||||||
{
|
|
||||||
Assert(es->format == EXPLAIN_FORMAT_JSON);
|
|
||||||
if (linitial_int(es->grouping_stack) != 0)
|
|
||||||
appendStringInfoChar(es->str, ',');
|
|
||||||
else
|
|
||||||
linitial_int(es->grouping_stack) = 1;
|
|
||||||
appendStringInfoChar(es->str, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indent a YAML line.
|
|
||||||
*
|
|
||||||
* YAML lines are ordinarily indented by two spaces per indentation level.
|
|
||||||
* The text emitted for each property begins just prior to the preceding
|
|
||||||
* line-break, except for the first property in an unlabelled group, for which
|
|
||||||
* it begins immediately after the "- " that introduces the group. The first
|
|
||||||
* property of the group appears on the same line as the opening "- ".
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
ExplainYAMLLineStarting(ExplainState *es)
|
|
||||||
{
|
|
||||||
Assert(es->format == EXPLAIN_FORMAT_YAML);
|
|
||||||
if (linitial_int(es->grouping_stack) == 0)
|
|
||||||
{
|
|
||||||
linitial_int(es->grouping_stack) = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendStringInfoChar(es->str, '\n');
|
|
||||||
appendStringInfoSpaces(es->str, es->indent * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1358,8 +1358,7 @@ ExtractFromExpressionWalker(Node *node, QualifierWalkerContext *walkerContext)
|
||||||
{
|
{
|
||||||
/* this part of code only run for subqueries */
|
/* this part of code only run for subqueries */
|
||||||
Node *joinClause = eval_const_expressions(NULL, joinQualifiersNode);
|
Node *joinClause = eval_const_expressions(NULL, joinQualifiersNode);
|
||||||
joinClause = (Node *) canonicalize_qual_compat((Expr *) joinClause,
|
joinClause = (Node *) canonicalize_qual((Expr *) joinClause, false);
|
||||||
false);
|
|
||||||
joinQualifierList = make_ands_implicit((Expr *) joinClause);
|
joinQualifierList = make_ands_implicit((Expr *) joinClause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1392,8 +1391,7 @@ ExtractFromExpressionWalker(Node *node, QualifierWalkerContext *walkerContext)
|
||||||
{
|
{
|
||||||
/* this part of code only run for subqueries */
|
/* this part of code only run for subqueries */
|
||||||
Node *fromClause = eval_const_expressions(NULL, fromQualifiersNode);
|
Node *fromClause = eval_const_expressions(NULL, fromQualifiersNode);
|
||||||
fromClause = (Node *) canonicalize_qual_compat((Expr *) fromClause,
|
fromClause = (Node *) canonicalize_qual((Expr *) fromClause, false);
|
||||||
false);
|
|
||||||
fromQualifierList = make_ands_implicit((Expr *) fromClause);
|
fromQualifierList = make_ands_implicit((Expr *) fromClause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4375,7 +4375,7 @@ ColumnName(Var *column, List *rangeTableList)
|
||||||
else if (rangeTableKind == CITUS_RTE_RELATION)
|
else if (rangeTableKind == CITUS_RTE_RELATION)
|
||||||
{
|
{
|
||||||
Oid relationId = rangeTableEntry->relid;
|
Oid relationId = rangeTableEntry->relid;
|
||||||
columnName = get_attname_internal(relationId, columnNumber, false);
|
columnName = get_attname(relationId, columnNumber, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(columnName != NULL);
|
Assert(columnName != NULL);
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,6 @@
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_class.h"
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
|
||||||
#endif
|
|
||||||
#include "distributed/commands.h"
|
#include "distributed/commands.h"
|
||||||
#include "distributed/metadata_cache.h"
|
#include "distributed/metadata_cache.h"
|
||||||
#include "distributed/relay_utility.h"
|
#include "distributed/relay_utility.h"
|
||||||
|
|
@ -318,7 +315,7 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
{
|
{
|
||||||
GrantStmt *grantStmt = (GrantStmt *) parseTree;
|
GrantStmt *grantStmt = (GrantStmt *) parseTree;
|
||||||
if (grantStmt->targtype == ACL_TARGET_OBJECT &&
|
if (grantStmt->targtype == ACL_TARGET_OBJECT &&
|
||||||
grantStmt->objtype == RELATION_OBJECT_TYPE)
|
grantStmt->objtype == OBJECT_TABLE)
|
||||||
{
|
{
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,7 @@ StartLockAcquireHelperBackgroundWorker(int backendToHelp, int32 lock_cooldown)
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN,
|
snprintf(worker.bgw_name, BGW_MAXLEN,
|
||||||
"Citus Lock Acquire Helper: %d/%u",
|
"Citus Lock Acquire Helper: %d/%u",
|
||||||
backendToHelp, MyDatabaseId);
|
backendToHelp, MyDatabaseId);
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
snprintf(worker.bgw_type, BGW_MAXLEN, "citus_lock_aqcuire");
|
snprintf(worker.bgw_type, BGW_MAXLEN, "citus_lock_aqcuire");
|
||||||
#endif
|
|
||||||
|
|
||||||
worker.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
|
worker.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
|
||||||
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
||||||
|
|
|
||||||
|
|
@ -694,8 +694,6 @@ deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, int64 shardid,
|
||||||
deparse_index_columns(buffer, indexStmt->indexParams, deparseContext);
|
deparse_index_columns(buffer, indexStmt->indexParams, deparseContext);
|
||||||
appendStringInfoString(buffer, ") ");
|
appendStringInfoString(buffer, ") ");
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
|
|
||||||
/* column/expressions for INCLUDE list */
|
/* column/expressions for INCLUDE list */
|
||||||
if (indexStmt->indexIncludingParams != NIL)
|
if (indexStmt->indexIncludingParams != NIL)
|
||||||
{
|
{
|
||||||
|
|
@ -703,7 +701,6 @@ deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, int64 shardid,
|
||||||
deparse_index_columns(buffer, indexStmt->indexIncludingParams, deparseContext);
|
deparse_index_columns(buffer, indexStmt->indexIncludingParams, deparseContext);
|
||||||
appendStringInfoChar(buffer, ')');
|
appendStringInfoChar(buffer, ')');
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
AppendStorageParametersToString(buffer, indexStmt->options);
|
AppendStorageParametersToString(buffer, indexStmt->options);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ ColumnNameToColumn(Oid relationId, char *columnNodeString)
|
||||||
columnNumber, relationName)));
|
columnNumber, relationName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
columnName = get_attname_internal(relationId, column->varattno, false);
|
columnName = get_attname(relationId, column->varattno, false);
|
||||||
if (columnName == NULL)
|
if (columnName == NULL)
|
||||||
{
|
{
|
||||||
char *relationName = get_rel_name(relationId);
|
char *relationName = get_rel_name(relationId);
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@
|
||||||
#include "catalog/partition.h"
|
#include "catalog/partition.h"
|
||||||
#include "catalog/pg_class.h"
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_inherits.h"
|
#include "catalog/pg_inherits.h"
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
|
||||||
#endif
|
|
||||||
#include "distributed/citus_ruleutils.h"
|
#include "distributed/citus_ruleutils.h"
|
||||||
#include "distributed/colocation_utils.h"
|
#include "distributed/colocation_utils.h"
|
||||||
#include "distributed/master_metadata_utility.h"
|
#include "distributed/master_metadata_utility.h"
|
||||||
|
|
|
||||||
|
|
@ -839,7 +839,7 @@ lock_relation_if_exists(PG_FUNCTION_ARGS)
|
||||||
relation = makeRangeVarFromNameList(relationNameList);
|
relation = makeRangeVarFromNameList(relationNameList);
|
||||||
|
|
||||||
/* lock the relation with the lock mode */
|
/* lock the relation with the lock mode */
|
||||||
relationId = RangeVarGetRelidInternal(relation, lockMode, RVR_MISSING_OK,
|
relationId = RangeVarGetRelidExtended(relation, lockMode, RVR_MISSING_OK,
|
||||||
CitusRangeVarCallbackForLockTable,
|
CitusRangeVarCallbackForLockTable,
|
||||||
(void *) &lockMode);
|
(void *) &lockMode);
|
||||||
relationExists = OidIsValid(relationId);
|
relationExists = OidIsValid(relationId);
|
||||||
|
|
@ -879,13 +879,8 @@ CitusRangeVarCallbackForLockTable(const RangeVar *rangeVar, Oid relationId,
|
||||||
aclResult = CitusLockTableAclCheck(relationId, lockmode, GetUserId());
|
aclResult = CitusLockTableAclCheck(relationId, lockmode, GetUserId());
|
||||||
if (aclResult != ACLCHECK_OK)
|
if (aclResult != ACLCHECK_OK)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
aclcheck_error(aclResult, get_relkind_objtype(get_rel_relkind(relationId)),
|
aclcheck_error(aclResult, get_relkind_objtype(get_rel_relkind(relationId)),
|
||||||
rangeVar->relname);
|
rangeVar->relname);
|
||||||
#else
|
|
||||||
|
|
||||||
aclcheck_error(aclResult, ACL_KIND_CLASS, rangeVar->relname);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -382,7 +382,7 @@ RemoveJobSchema(StringInfo schemaName)
|
||||||
bool permissionsOK = pg_namespace_ownercheck(schemaId, GetUserId());
|
bool permissionsOK = pg_namespace_ownercheck(schemaId, GetUserId());
|
||||||
if (!permissionsOK)
|
if (!permissionsOK)
|
||||||
{
|
{
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACLCHECK_OBJECT_SCHEMA, schemaName->data);
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA, schemaName->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
schemaObject.classId = NamespaceRelationId;
|
schemaObject.classId = NamespaceRelationId;
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,8 @@
|
||||||
/* cluster.c - forward declarations */
|
/* cluster.c - forward declarations */
|
||||||
extern List * PlanClusterStmt(ClusterStmt *clusterStmt, const char *clusterCommand);
|
extern List * PlanClusterStmt(ClusterStmt *clusterStmt, const char *clusterCommand);
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 110000
|
|
||||||
|
|
||||||
/* call.c */
|
/* call.c */
|
||||||
extern bool CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *dest);
|
extern bool CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *dest);
|
||||||
#endif /* PG_VERSION_NUM >= 110000 */
|
|
||||||
|
|
||||||
/* extension.c - forward declarations */
|
/* extension.c - forward declarations */
|
||||||
extern bool IsCitusExtensionStmt(Node *parsetree);
|
extern bool IsCitusExtensionStmt(Node *parsetree);
|
||||||
|
|
|
||||||
|
|
@ -16,260 +16,10 @@
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 120000)
|
#if (PG_VERSION_NUM >= 120000)
|
||||||
#include "optimizer/optimizer.h"
|
#include "optimizer/optimizer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 110000)
|
|
||||||
|
|
||||||
#include "access/hash.h"
|
|
||||||
#include "storage/fd.h"
|
|
||||||
#include "optimizer/prep.h"
|
|
||||||
#include "postmaster/bgworker.h"
|
|
||||||
#include "utils/memutils.h"
|
|
||||||
#include "funcapi.h"
|
|
||||||
|
|
||||||
/* PostgreSQL 11 splits hash procs into "standard" and "extended" */
|
|
||||||
#define HASHSTANDARD_PROC HASHPROC
|
|
||||||
|
|
||||||
/* following functions are renamed in PG11 */
|
|
||||||
#define PreventInTransactionBlock PreventTransactionChain
|
|
||||||
#define DatumGetJsonbP(d) DatumGetJsonb(d)
|
|
||||||
#define RequireTransactionBlock RequireTransactionChain
|
|
||||||
|
|
||||||
/* following defines also exist for PG11 */
|
|
||||||
#define RELATION_OBJECT_TYPE ACL_OBJECT_RELATION
|
|
||||||
#define IndexInfoAttributeNumberArray(indexinfo) (indexinfo->ii_KeyAttrNumbers)
|
|
||||||
|
|
||||||
/* CreateTrigger api is changed in PG11 */
|
|
||||||
#define CreateTriggerInternal(stmt, queryString, relOid, refRelOid, constraintOid, \
|
|
||||||
indexOid, funcoid, parentTriggerOid, whenClause, isInternal, \
|
|
||||||
in_partition) \
|
|
||||||
CreateTrigger(stmt, queryString, relOid, refRelOid, constraintOid, indexOid, \
|
|
||||||
isInternal)
|
|
||||||
|
|
||||||
#define get_attname_internal(relationId, columnNumber, false) \
|
|
||||||
get_attname(relationId, columnNumber)
|
|
||||||
|
|
||||||
#define BackgroundWorkerInitializeConnectionByOid(dboid, useroid, flags) \
|
|
||||||
BackgroundWorkerInitializeConnectionByOid(dboid, useroid)
|
|
||||||
|
|
||||||
#define AtEOXact_Files(isCommit) \
|
|
||||||
AtEOXact_Files()
|
|
||||||
|
|
||||||
#define ACLCHECK_OBJECT_TABLE ACL_KIND_CLASS
|
|
||||||
#define ACLCHECK_OBJECT_SCHEMA ACL_KIND_NAMESPACE
|
|
||||||
#define ACLCHECK_OBJECT_INDEX ACL_KIND_CLASS
|
|
||||||
#define ACLCHECK_OBJECT_SEQUENCE ACL_KIND_CLASS
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
BasicOpenFilePerm(FileName fileName, int fileFlags, int fileMode)
|
|
||||||
{
|
|
||||||
return BasicOpenFile(fileName, fileFlags, fileMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline File
|
|
||||||
PathNameOpenFilePerm(FileName fileName, int fileFlags, int fileMode)
|
|
||||||
{
|
|
||||||
return PathNameOpenFile(fileName, fileFlags, fileMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline MemoryContext
|
|
||||||
AllocSetContextCreateExtended(MemoryContext parent, const char *name, Size minContextSize,
|
|
||||||
Size initBlockSize, Size maxBlockSize)
|
|
||||||
{
|
|
||||||
return AllocSetContextCreate(parent, name, minContextSize, initBlockSize,
|
|
||||||
maxBlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
ExplainPropertyIntegerInternal(const char *qlabel, const char *unit, int64 value,
|
|
||||||
ExplainState *es)
|
|
||||||
{
|
|
||||||
return ExplainPropertyInteger(qlabel, value, es);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline List *
|
|
||||||
ExtractVacuumTargetRels(VacuumStmt *vacuumStmt)
|
|
||||||
{
|
|
||||||
List *vacuumList = NIL;
|
|
||||||
|
|
||||||
if (vacuumStmt->relation != NULL)
|
|
||||||
{
|
|
||||||
vacuumList = list_make1(vacuumStmt->relation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vacuumList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline List *
|
|
||||||
VacuumColumnList(VacuumStmt *vacuumStmt, int relationIndex)
|
|
||||||
{
|
|
||||||
Assert(relationIndex == 0);
|
|
||||||
|
|
||||||
return vacuumStmt->va_cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define RVR_MISSING_OK 1
|
|
||||||
#define RVR_NOWAIT 2
|
|
||||||
|
|
||||||
static inline Oid
|
|
||||||
RangeVarGetRelidInternal(const RangeVar *relation, LOCKMODE lockmode, uint32 flags,
|
|
||||||
RangeVarGetRelidCallback callback, void *callback_arg)
|
|
||||||
{
|
|
||||||
bool missingOK = ((flags & RVR_MISSING_OK) != 0);
|
|
||||||
bool noWait = ((flags & RVR_NOWAIT) != 0);
|
|
||||||
|
|
||||||
return RangeVarGetRelidExtended(relation, lockmode, missingOK, noWait,
|
|
||||||
callback, callback_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline Expr *
|
|
||||||
canonicalize_qual_compat(Expr *qual, bool is_check)
|
|
||||||
{
|
|
||||||
return canonicalize_qual(qual);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A convenient wrapper around get_expr_result_type() that is added on PG11
|
|
||||||
*
|
|
||||||
* Note that this function ignores the second parameter and behaves
|
|
||||||
* slightly differently than the PG11 version.
|
|
||||||
*
|
|
||||||
* 1. The original function throws errors if noError flag is not set, we ignore
|
|
||||||
* this flag here and return NULL in that case
|
|
||||||
* 2. TYPEFUNC_COMPOSITE_DOMAIN is introduced in PG11, and references to this
|
|
||||||
* macro is removed
|
|
||||||
* */
|
|
||||||
static inline TupleDesc
|
|
||||||
get_expr_result_tupdesc(Node *expr, bool noError)
|
|
||||||
{
|
|
||||||
TupleDesc tupleDesc;
|
|
||||||
TypeFuncClass functypclass;
|
|
||||||
|
|
||||||
functypclass = get_expr_result_type(expr, NULL, &tupleDesc);
|
|
||||||
|
|
||||||
if (functypclass == TYPEFUNC_COMPOSITE)
|
|
||||||
{
|
|
||||||
return tupleDesc;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* following compat function and macro should be removed when we drop support for PG10 */
|
|
||||||
static inline Oid
|
|
||||||
LookupFuncWithArgsCompat(ObjectType objtype, ObjectWithArgs *func, bool noError)
|
|
||||||
{
|
|
||||||
if (objtype == OBJECT_FUNCTION)
|
|
||||||
{
|
|
||||||
return LookupFuncWithArgs(func, noError);
|
|
||||||
}
|
|
||||||
else if (objtype == OBJECT_AGGREGATE)
|
|
||||||
{
|
|
||||||
return LookupAggWithArgs(func, noError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return InvalidOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 110000)
|
|
||||||
#include "optimizer/prep.h"
|
|
||||||
|
|
||||||
/* following macros should be removed when we drop support for PG10 and below */
|
|
||||||
#define RELATION_OBJECT_TYPE OBJECT_TABLE
|
|
||||||
#define IndexInfoAttributeNumberArray(indexinfo) (indexinfo->ii_IndexAttrNumbers)
|
|
||||||
#define CreateTriggerInternal CreateTrigger
|
|
||||||
#define get_attname_internal get_attname
|
|
||||||
|
|
||||||
#define ACLCHECK_OBJECT_TABLE OBJECT_TABLE
|
|
||||||
#define ACLCHECK_OBJECT_SCHEMA OBJECT_SCHEMA
|
|
||||||
#define ACLCHECK_OBJECT_INDEX OBJECT_INDEX
|
|
||||||
#define ACLCHECK_OBJECT_SEQUENCE OBJECT_SEQUENCE
|
|
||||||
|
|
||||||
|
|
||||||
#define ConstraintRelidIndexId ConstraintRelidTypidNameIndexId
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
ExplainPropertyIntegerInternal(const char *qlabel, const char *unit, int64 value,
|
|
||||||
ExplainState *es)
|
|
||||||
{
|
|
||||||
return ExplainPropertyInteger(qlabel, unit, value, es);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline Expr *
|
|
||||||
canonicalize_qual_compat(Expr *qual, bool is_check)
|
|
||||||
{
|
|
||||||
return canonicalize_qual(qual, is_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ExtractVacuumTargetRels returns list of target
|
|
||||||
* relations from vacuum statement.
|
|
||||||
*/
|
|
||||||
static inline List *
|
|
||||||
ExtractVacuumTargetRels(VacuumStmt *vacuumStmt)
|
|
||||||
{
|
|
||||||
List *vacuumList = NIL;
|
|
||||||
|
|
||||||
ListCell *vacuumRelationCell = NULL;
|
|
||||||
foreach(vacuumRelationCell, vacuumStmt->rels)
|
|
||||||
{
|
|
||||||
VacuumRelation *vacuumRelation = (VacuumRelation *) lfirst(vacuumRelationCell);
|
|
||||||
vacuumList = lappend(vacuumList, vacuumRelation->relation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vacuumList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VacuumColumnList returns list of columns from relation
|
|
||||||
* in the vacuum statement at specified relationIndex.
|
|
||||||
*/
|
|
||||||
static inline List *
|
|
||||||
VacuumColumnList(VacuumStmt *vacuumStmt, int relationIndex)
|
|
||||||
{
|
|
||||||
VacuumRelation *vacuumRelation = (VacuumRelation *) list_nth(vacuumStmt->rels,
|
|
||||||
relationIndex);
|
|
||||||
|
|
||||||
return vacuumRelation->va_cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline Oid
|
|
||||||
RangeVarGetRelidInternal(const RangeVar *relation, LOCKMODE lockmode, uint32 flags,
|
|
||||||
RangeVarGetRelidCallback callback, void *callback_arg)
|
|
||||||
{
|
|
||||||
return RangeVarGetRelidExtended(relation, lockmode, flags, callback, callback_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* following compat function and macro should be removed when we drop support for PG10 */
|
|
||||||
static inline Oid
|
|
||||||
LookupFuncWithArgsCompat(ObjectType objtype, ObjectWithArgs *func, bool noError)
|
|
||||||
{
|
|
||||||
return LookupFuncWithArgs(objtype, func, noError);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 120000
|
#if PG_VERSION_NUM >= 120000
|
||||||
|
|
||||||
#define MakeSingleTupleTableSlotCompat MakeSingleTupleTableSlot
|
#define MakeSingleTupleTableSlotCompat MakeSingleTupleTableSlot
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,3 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
\endif
|
|
||||||
SET citus.next_shard_id TO 20030000;
|
SET citus.next_shard_id TO 20030000;
|
||||||
CREATE USER procedureuser;
|
CREATE USER procedureuser;
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
|
|
@ -1,392 +0,0 @@
|
||||||
SET citus.next_shard_id TO 20010000;
|
|
||||||
CREATE USER typeuser;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
SELECT run_command_on_workers($$CREATE USER typeuser;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
-----------------------------------
|
|
||||||
(localhost,57637,t,"CREATE ROLE")
|
|
||||||
(localhost,57638,t,"CREATE ROLE")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
CREATE SCHEMA type_tests AUTHORIZATION typeuser;
|
|
||||||
CREATE SCHEMA type_tests2 AUTHORIZATION typeuser; -- to test creation in a specific schema and moving to schema
|
|
||||||
SET search_path TO type_tests;
|
|
||||||
SET citus.shard_count TO 4;
|
|
||||||
-- single statement transactions with a simple type used in a table
|
|
||||||
CREATE TYPE tc1 AS (a int, b int);
|
|
||||||
CREATE TABLE t1 (a int PRIMARY KEY, b tc1);
|
|
||||||
SELECT create_distributed_table('t1','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO t1 VALUES (1, (2,3)::tc1);
|
|
||||||
SELECT * FROM t1;
|
|
||||||
a | b
|
|
||||||
---+-------
|
|
||||||
1 | (2,3)
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ALTER TYPE tc1 RENAME TO tc1_newname;
|
|
||||||
INSERT INTO t1 VALUES (3, (4,5)::tc1_newname); -- insert with a cast would fail if the rename didn't propagate
|
|
||||||
ALTER TYPE tc1_newname SET SCHEMA type_tests2;
|
|
||||||
INSERT INTO t1 VALUES (6, (7,8)::type_tests2.tc1_newname); -- insert with a cast would fail if the rename didn't propagate
|
|
||||||
-- single statement transactions with a an enum used in a table
|
|
||||||
CREATE TYPE te1 AS ENUM ('one', 'two', 'three');
|
|
||||||
CREATE TABLE t2 (a int PRIMARY KEY, b te1);
|
|
||||||
SELECT create_distributed_table('t2','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO t2 VALUES (1, 'two');
|
|
||||||
SELECT * FROM t2;
|
|
||||||
a | b
|
|
||||||
---+-----
|
|
||||||
1 | two
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- rename enum, subsequent operations on the type would fail if the rename was not propagated
|
|
||||||
ALTER TYPE te1 RENAME TO te1_newname;
|
|
||||||
-- add an extra value to the enum and use in table
|
|
||||||
ALTER TYPE te1_newname ADD VALUE 'four';
|
|
||||||
UPDATE t2 SET b = 'four';
|
|
||||||
SELECT * FROM t2;
|
|
||||||
a | b
|
|
||||||
---+------
|
|
||||||
1 | four
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- change the schema of the type and use the new fully qualified name in an insert
|
|
||||||
ALTER TYPE te1_newname SET SCHEMA type_tests2;
|
|
||||||
INSERT INTO t2 VALUES (3, 'three'::type_tests2.te1_newname);
|
|
||||||
-- transaction block with simple type
|
|
||||||
BEGIN;
|
|
||||||
CREATE TYPE tc2 AS (a int, b int);
|
|
||||||
CREATE TABLE t3 (a int PRIMARY KEY, b tc2);
|
|
||||||
SELECT create_distributed_table('t3','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO t3 VALUES (4, (5,6)::tc2);
|
|
||||||
SELECT * FROM t3;
|
|
||||||
a | b
|
|
||||||
---+-------
|
|
||||||
4 | (5,6)
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
-- transaction block with simple type
|
|
||||||
BEGIN;
|
|
||||||
CREATE TYPE te2 AS ENUM ('yes', 'no');
|
|
||||||
CREATE TABLE t4 (a int PRIMARY KEY, b te2);
|
|
||||||
SELECT create_distributed_table('t4','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO t4 VALUES (1, 'yes');
|
|
||||||
SELECT * FROM t4;
|
|
||||||
a | b
|
|
||||||
---+-----
|
|
||||||
1 | yes
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ALTER TYPE ... ADD VALUE does not work in transactions
|
|
||||||
COMMIT;
|
|
||||||
-- verify order of enum labels
|
|
||||||
SELECT string_agg(enumlabel, ',' ORDER BY enumsortorder ASC) FROM pg_enum WHERE enumtypid = 'type_tests.te2'::regtype;
|
|
||||||
string_agg
|
|
||||||
------------
|
|
||||||
yes,no
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT string_agg(enumlabel, ',' ORDER BY enumsortorder ASC) FROM pg_enum WHERE enumtypid = 'type_tests.te2'::regtype;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------------
|
|
||||||
(localhost,57637,t,"yes,no")
|
|
||||||
(localhost,57638,t,"yes,no")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- test some combination of types without ddl propagation, this will prevent the workers
|
|
||||||
-- from having those types created. They are created just-in-time on table distribution
|
|
||||||
SET citus.enable_ddl_propagation TO off;
|
|
||||||
CREATE TYPE tc3 AS (a int, b int);
|
|
||||||
CREATE TYPE tc4 AS (a int, b tc3[]);
|
|
||||||
CREATE TYPE tc5 AS (a int, b tc4);
|
|
||||||
CREATE TYPE te3 AS ENUM ('a','b');
|
|
||||||
RESET citus.enable_ddl_propagation;
|
|
||||||
CREATE TABLE t5 (a int PRIMARY KEY, b tc5[], c te3);
|
|
||||||
SELECT create_distributed_table('t5','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test adding an attribute to a type and a column to a table both for a non-distributed type
|
|
||||||
SET citus.enable_ddl_propagation TO off;
|
|
||||||
CREATE TYPE te4 AS ENUM ('c','d');
|
|
||||||
CREATE TYPE tc6 AS (a int, b int);
|
|
||||||
CREATE TYPE tc6c AS (a int, b int);
|
|
||||||
RESET citus.enable_ddl_propagation;
|
|
||||||
-- types need to be fully qualified because of the search_path which is not supported by ALTER TYPE ... ADD COLUMN
|
|
||||||
ALTER TABLE t5 ADD COLUMN d type_tests.te4;
|
|
||||||
ALTER TABLE t5 ADD COLUMN e type_tests.tc6;
|
|
||||||
ALTER TYPE tc6 ADD ATTRIBUTE c tc6c;
|
|
||||||
-- last two values are only there if above commands succeeded
|
|
||||||
INSERT INTO t5 VALUES (1, NULL, 'a', 'd', (1,2,(4,5)::tc6c)::tc6);
|
|
||||||
-- test renaming an attribute of a distrbuted type and read it by its new name to verify propagation
|
|
||||||
ALTER TYPE tc6 RENAME ATTRIBUTE b TO d;
|
|
||||||
SELECT (e::tc6).d FROM t5 ORDER BY 1;
|
|
||||||
d
|
|
||||||
---
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- change owner of supported types and check ownership on remote server
|
|
||||||
ALTER TYPE te4 OWNER TO typeuser;
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'te4' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
te4 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'te4' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(te4,typeuser)")
|
|
||||||
(localhost,57638,t,"(te4,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
ALTER TYPE tc6 OWNER TO typeuser;
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'tc6' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
tc6 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'tc6' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(tc6,typeuser)")
|
|
||||||
(localhost,57638,t,"(tc6,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- create a type as a different user
|
|
||||||
SET ROLE typeuser;
|
|
||||||
-- create directly on the worker
|
|
||||||
CREATE TYPE tc7 AS (a int, b int);
|
|
||||||
CREATE TYPE te5 AS ENUM ('a','b','c');
|
|
||||||
-- cascade to the worker when table gets created
|
|
||||||
SET citus.enable_ddl_propagation TO off;
|
|
||||||
CREATE TYPE tc8 AS (a int, b int);
|
|
||||||
CREATE TYPE te6 AS ENUM ('a','b','c');
|
|
||||||
RESET citus.enable_ddl_propagation;
|
|
||||||
CREATE TABLE t6 (a int, b tc8, c te6);
|
|
||||||
SELECT create_distributed_table('t6', 'a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- test ownership of all types
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'tc7' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
tc7 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'tc7' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(tc7,typeuser)")
|
|
||||||
(localhost,57638,t,"(tc7,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'te5' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
te5 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'te5' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(te5,typeuser)")
|
|
||||||
(localhost,57638,t,"(te5,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'tc8' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
tc8 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'tc8' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(tc8,typeuser)")
|
|
||||||
(localhost,57638,t,"(tc8,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT typname, usename FROM pg_type, pg_user where typname = 'te6' and typowner = usesysid;
|
|
||||||
typname | usename
|
|
||||||
---------+----------
|
|
||||||
te6 | typeuser
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT row(typname, usename) FROM pg_type, pg_user where typname = 'te6' and typowner = usesysid;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
--------------------------------------
|
|
||||||
(localhost,57637,t,"(te6,typeuser)")
|
|
||||||
(localhost,57638,t,"(te6,typeuser)")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- deleting the enum cascade will remove the type from the table and the workers
|
|
||||||
DROP TYPE te3 CASCADE;
|
|
||||||
NOTICE: drop cascades to table t5 column c
|
|
||||||
-- DELETE multiple types at once
|
|
||||||
DROP TYPE tc3, tc4, tc5 CASCADE;
|
|
||||||
NOTICE: drop cascades to table t5 column b
|
|
||||||
-- test if the types are deleted
|
|
||||||
SELECT typname FROM pg_type, pg_user where typname IN ('te3','tc3','tc4','tc5') and typowner = usesysid ORDER BY typname;
|
|
||||||
typname
|
|
||||||
---------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT typname FROM pg_type, pg_user where typname IN ('te3','tc3','tc4','tc5') and typowner = usesysid ORDER BY typname;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- make sure attribute names are quoted correctly, no errors indicates types are propagated correctly
|
|
||||||
CREATE TYPE tc9 AS ("field-with-dashes" text COLLATE "POSIX");
|
|
||||||
ALTER TYPE tc9 ADD ATTRIBUTE "some-more" int, ADD ATTRIBUTE normal int;
|
|
||||||
ALTER TYPE tc9 RENAME ATTRIBUTE normal TO "not-so-normal";
|
|
||||||
-- test alter statements for non-distributed types, if they would be propagated they would
|
|
||||||
-- error, preventing from changing them
|
|
||||||
SET citus.enable_ddl_propagation TO off;
|
|
||||||
CREATE TYPE non_distributed_composite_type AS (a int, b int);
|
|
||||||
CREATE TYPE non_distributed_enum_type AS ENUM ('a', 'c');
|
|
||||||
SET citus.enable_ddl_propagation TO on;
|
|
||||||
ALTER TYPE non_distributed_composite_type ADD ATTRIBUTE c int;
|
|
||||||
ALTER TYPE non_distributed_composite_type RENAME ATTRIBUTE c TO d;
|
|
||||||
ALTER TYPE non_distributed_composite_type ALTER ATTRIBUTE d SET DATA TYPE text COLLATE "POSIX" CASCADE;
|
|
||||||
ALTER TYPE non_distributed_composite_type DROP ATTRIBUTE d;
|
|
||||||
ALTER TYPE non_distributed_composite_type OWNER TO typeuser;
|
|
||||||
ALTER TYPE non_distributed_composite_type RENAME TO non_distributed_composite_type_renamed;
|
|
||||||
ALTER TYPE non_distributed_composite_type_renamed RENAME TO non_distributed_composite_type;
|
|
||||||
ALTER TYPE non_distributed_composite_type SET SCHEMA type_tests2;
|
|
||||||
ALTER TYPE type_tests2.non_distributed_composite_type SET SCHEMA type_tests;
|
|
||||||
ALTER TYPE non_distributed_enum_type OWNER TO typeuser;
|
|
||||||
ALTER TYPE non_distributed_enum_type RENAME TO non_distributed_enum_type_renamed;
|
|
||||||
ALTER TYPE non_distributed_enum_type_renamed RENAME TO non_distributed_enum_type;
|
|
||||||
ALTER TYPE non_distributed_enum_type SET SCHEMA type_tests2;
|
|
||||||
ALTER TYPE type_tests2.non_distributed_enum_type SET SCHEMA type_tests;
|
|
||||||
ALTER TYPE non_distributed_enum_type ADD VALUE 'b' BEFORE 'c';
|
|
||||||
ALTER TYPE non_distributed_enum_type ADD VALUE 'd' AFTER 'c';
|
|
||||||
ALTER TYPE non_distributed_enum_type RENAME VALUE 'd' TO 'something-with-quotes''andstuff';
|
|
||||||
-- test all forms of alter statements on distributed types
|
|
||||||
CREATE TYPE distributed_composite_type AS (a int, b int);
|
|
||||||
CREATE TYPE distributed_enum_type AS ENUM ('a', 'c');
|
|
||||||
-- enforce distribution of types in every case
|
|
||||||
CREATE TABLE type_proc (a int, b distributed_composite_type, c distributed_enum_type);
|
|
||||||
SELECT create_distributed_table('type_proc','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE type_proc;
|
|
||||||
ALTER TYPE distributed_composite_type ADD ATTRIBUTE c int;
|
|
||||||
ALTER TYPE distributed_composite_type RENAME ATTRIBUTE c TO d;
|
|
||||||
ALTER TYPE distributed_composite_type ALTER ATTRIBUTE d SET DATA TYPE text COLLATE "POSIX" CASCADE;
|
|
||||||
ALTER TYPE distributed_composite_type DROP ATTRIBUTE d;
|
|
||||||
ALTER TYPE distributed_composite_type OWNER TO typeuser;
|
|
||||||
ALTER TYPE distributed_composite_type RENAME TO distributed_composite_type_renamed;
|
|
||||||
ALTER TYPE distributed_composite_type_renamed RENAME TO distributed_composite_type;
|
|
||||||
ALTER TYPE distributed_composite_type SET SCHEMA type_tests2;
|
|
||||||
ALTER TYPE type_tests2.distributed_composite_type SET SCHEMA type_tests;
|
|
||||||
ALTER TYPE distributed_enum_type OWNER TO typeuser;
|
|
||||||
ALTER TYPE distributed_enum_type RENAME TO distributed_enum_type_renamed;
|
|
||||||
ALTER TYPE distributed_enum_type_renamed RENAME TO distributed_enum_type;
|
|
||||||
ALTER TYPE distributed_enum_type SET SCHEMA type_tests2;
|
|
||||||
ALTER TYPE type_tests2.distributed_enum_type SET SCHEMA type_tests;
|
|
||||||
ALTER TYPE distributed_enum_type ADD VALUE 'b' BEFORE 'c';
|
|
||||||
ALTER TYPE distributed_enum_type ADD VALUE 'd' AFTER 'c';
|
|
||||||
ALTER TYPE distributed_enum_type RENAME VALUE 'd' TO 'something-with-quotes''andstuff';
|
|
||||||
-- make sure types are not distributed by default when feature flag is turned off
|
|
||||||
SET citus.enable_create_type_propagation TO off;
|
|
||||||
CREATE TYPE feature_flag_composite_type AS (a int, b int);
|
|
||||||
CREATE TYPE feature_flag_enum_type AS ENUM ('a', 'b');
|
|
||||||
-- verify types do not exist on workers
|
|
||||||
SELECT count(*) FROM pg_type where typname IN ('feature_flag_composite_type', 'feature_flag_enum_type');
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN ('feature_flag_composite_type', 'feature_flag_enum_type');$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- verify they are still distributed when required
|
|
||||||
CREATE TABLE feature_flag_table (a int PRIMARY KEY, b feature_flag_composite_type, c feature_flag_enum_type);
|
|
||||||
SELECT create_distributed_table('feature_flag_table','a');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_type where typname IN ('feature_flag_composite_type', 'feature_flag_enum_type');
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname IN ('feature_flag_composite_type', 'feature_flag_enum_type');$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,2)
|
|
||||||
(localhost,57638,t,2)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
RESET citus.enable_create_type_propagation;
|
|
||||||
-- clear objects
|
|
||||||
SET client_min_messages TO error; -- suppress cascading objects dropping
|
|
||||||
DROP SCHEMA type_tests CASCADE;
|
|
||||||
SELECT run_command_on_workers($$DROP SCHEMA type_tests CASCADE;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
-----------------------------------
|
|
||||||
(localhost,57637,t,"DROP SCHEMA")
|
|
||||||
(localhost,57638,t,"DROP SCHEMA")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
DROP SCHEMA type_tests2 CASCADE;
|
|
||||||
SELECT run_command_on_workers($$DROP SCHEMA type_tests2 CASCADE;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
-----------------------------------
|
|
||||||
(localhost,57637,t,"DROP SCHEMA")
|
|
||||||
(localhost,57638,t,"DROP SCHEMA")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
DROP USER typeuser;
|
|
||||||
SELECT run_command_on_workers($$DROP USER typeuser;$$);
|
|
||||||
run_command_on_workers
|
|
||||||
---------------------------------
|
|
||||||
(localhost,57637,t,"DROP ROLE")
|
|
||||||
(localhost,57638,t,"DROP ROLE")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
|
|
@ -1,14 +1,6 @@
|
||||||
-- We have different output files for the executor. This is because
|
-- We have different output files for the executor. This is because
|
||||||
-- we don't mark transactions with ANALYZE as critical anymore, and
|
-- we don't mark transactions with ANALYZE as critical anymore, and
|
||||||
-- get WARNINGs instead of ERRORs.
|
-- get WARNINGs instead of ERRORs.
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 12000000;
|
SET citus.next_shard_id TO 12000000;
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
SELECT citus.mitmproxy('conn.allow()');
|
||||||
mitmproxy
|
mitmproxy
|
||||||
|
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
-- We have different output files for the executor. The executor
|
|
||||||
-- with PG10 behaves like non-executor PG11, and with PG11 it
|
|
||||||
-- behaves like non-executor PG10.
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.shard_count = 1;
|
|
||||||
SET citus.shard_replication_factor = 2; -- one shard per worker
|
|
||||||
SET citus.multi_shard_commit_protocol TO '1pc';
|
|
||||||
CREATE TABLE vacuum_test (key int, value int);
|
|
||||||
SELECT create_distributed_table('vacuum_test', 'key');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT citus.clear_network_traffic();
|
|
||||||
clear_network_traffic
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^VACUUM").kill()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
VACUUM vacuum_test;
|
|
||||||
ERROR: server closed the connection unexpectedly
|
|
||||||
This probably means the server terminated abnormally
|
|
||||||
before or while processing the request.
|
|
||||||
CONTEXT: while executing command on localhost:9060
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^ANALYZE").kill()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ANALYZE vacuum_test;
|
|
||||||
ERROR: server closed the connection unexpectedly
|
|
||||||
This probably means the server terminated abnormally
|
|
||||||
before or while processing the request.
|
|
||||||
CONTEXT: while executing command on localhost:9060
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^COMMIT").kill()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ANALYZE vacuum_test;
|
|
||||||
WARNING: connection not open
|
|
||||||
CONTEXT: while executing command on localhost:9060
|
|
||||||
WARNING: failed to commit transaction on localhost:9060
|
|
||||||
WARNING: connection not open
|
|
||||||
CONTEXT: while executing command on localhost:9060
|
|
||||||
-- ANALYZE transactions being critical is an open question, see #2430
|
|
||||||
UPDATE pg_dist_shard_placement SET shardstate = 1
|
|
||||||
WHERE shardid IN (
|
|
||||||
SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'vacuum_test'::regclass
|
|
||||||
);
|
|
||||||
-- the same tests with cancel
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^VACUUM").cancel(' || pg_backend_pid() || ')');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
VACUUM vacuum_test;
|
|
||||||
ERROR: canceling statement due to user request
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^ANALYZE").cancel(' || pg_backend_pid() || ')');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ANALYZE vacuum_test;
|
|
||||||
ERROR: canceling statement due to user request
|
|
||||||
-- cancel during COMMIT should be ignored
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^COMMIT").cancel(' || pg_backend_pid() || ')');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ANALYZE vacuum_test;
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE other_vacuum_test (key int, value int);
|
|
||||||
SELECT create_distributed_table('other_vacuum_test', 'key');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^VACUUM.*other").kill()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
VACUUM vacuum_test, other_vacuum_test;
|
|
||||||
ERROR: syntax error at or near ","
|
|
||||||
LINE 1: VACUUM vacuum_test, other_vacuum_test;
|
|
||||||
^
|
|
||||||
SELECT citus.mitmproxy('conn.onQuery(query="^VACUUM.*other").cancel(' || pg_backend_pid() || ')');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
VACUUM vacuum_test, other_vacuum_test;
|
|
||||||
ERROR: syntax error at or near ","
|
|
||||||
LINE 1: VACUUM vacuum_test, other_vacuum_test;
|
|
||||||
^
|
|
||||||
-- ==== Clean up, we're done here ====
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
|
||||||
mitmproxy
|
|
||||||
-----------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE vacuum_test, other_vacuum_test;
|
|
||||||
|
|
@ -1,14 +1,6 @@
|
||||||
-- We have different output files for the executor. This is because
|
-- We have different output files for the executor. This is because
|
||||||
-- we don't mark transactions with ANALYZE as critical anymore, and
|
-- we don't mark transactions with ANALYZE as critical anymore, and
|
||||||
-- get WARNINGs instead of ERRORs.
|
-- get WARNINGs instead of ERRORs.
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 12000000;
|
SET citus.next_shard_id TO 12000000;
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
SELECT citus.mitmproxy('conn.allow()');
|
||||||
mitmproxy
|
mitmproxy
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,6 @@
|
||||||
-- We have different output files for the executor. This is because
|
-- We have different output files for the executor. This is because
|
||||||
-- we don't mark transactions with ANALYZE as critical anymore, and
|
-- we don't mark transactions with ANALYZE as critical anymore, and
|
||||||
-- get WARNINGs instead of ERRORs.
|
-- get WARNINGs instead of ERRORs.
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 12000000;
|
SET citus.next_shard_id TO 12000000;
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
SELECT citus.mitmproxy('conn.allow()');
|
||||||
mitmproxy
|
mitmproxy
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,6 @@
|
||||||
-- there is foreign key relation between reference
|
-- there is foreign key relation between reference
|
||||||
-- tables and distributed tables
|
-- tables and distributed tables
|
||||||
--
|
--
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE SCHEMA test_fkey_to_ref_in_tx;
|
CREATE SCHEMA test_fkey_to_ref_in_tx;
|
||||||
SET search_path TO 'test_fkey_to_ref_in_tx';
|
SET search_path TO 'test_fkey_to_ref_in_tx';
|
||||||
SET citus.next_shard_id TO 2380000;
|
SET citus.next_shard_id TO 2380000;
|
||||||
|
|
@ -1117,7 +1110,6 @@ ROLLBACK;
|
||||||
-- parallel connection via create_distributed_table(), later
|
-- parallel connection via create_distributed_table(), later
|
||||||
-- adding foreign key to reference table fails
|
-- adding foreign key to reference table fails
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
SELECT create_reference_table('test_table_1');
|
SELECT create_reference_table('test_table_1');
|
||||||
create_reference_table
|
create_reference_table
|
||||||
|
|
@ -1144,7 +1136,6 @@ ERROR: current transaction is aborted, commands ignored until end of transactio
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- same test with the above on sequential mode should work fine
|
-- same test with the above on sequential mode should work fine
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
SELECT create_reference_table('test_table_1');
|
SELECT create_reference_table('test_table_1');
|
||||||
|
|
@ -1246,7 +1237,6 @@ ROLLBACK;
|
||||||
-- make sure that we cannot create hash distributed tables with
|
-- make sure that we cannot create hash distributed tables with
|
||||||
-- foreign keys to reference tables when they have data in it
|
-- foreign keys to reference tables when they have data in it
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
||||||
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
||||||
|
|
@ -1270,7 +1260,6 @@ COMMIT;
|
||||||
-- the same test with above in sequential mode would still not work
|
-- the same test with above in sequential mode would still not work
|
||||||
-- since COPY cannot be executed in sequential mode
|
-- since COPY cannot be executed in sequential mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
||||||
|
|
@ -1286,7 +1275,6 @@ NOTICE: Copying data from local table...
|
||||||
SELECT create_distributed_table('test_table_2', 'id');
|
SELECT create_distributed_table('test_table_2', 'id');
|
||||||
ERROR: cannot distribute "test_table_2" in sequential mode because it is not empty
|
ERROR: cannot distribute "test_table_2" in sequential mode because it is not empty
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
||||||
|
|
||||||
-- make sure that the output isn't too verbose
|
-- make sure that the output isn't too verbose
|
||||||
SET LOCAL client_min_messages TO ERROR;
|
SET LOCAL client_min_messages TO ERROR;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||||
|
|
@ -1296,7 +1284,6 @@ COMMIT;
|
||||||
-- we should be able to execute and DML/DDL/SELECT after we've
|
-- we should be able to execute and DML/DDL/SELECT after we've
|
||||||
-- switched to sequential via create_distributed_table
|
-- switched to sequential via create_distributed_table
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
||||||
SELECT create_reference_table('test_table_1');
|
SELECT create_reference_table('test_table_1');
|
||||||
|
|
@ -1423,7 +1410,6 @@ HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_m
|
||||||
-- finally, make sure that we can execute the same queries
|
-- finally, make sure that we can execute the same queries
|
||||||
-- in the sequential mode
|
-- in the sequential mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
|
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
|
||||||
t2 AS (DELETE FROM reference_table RETURNING id)
|
t2 AS (DELETE FROM reference_table RETURNING id)
|
||||||
|
|
@ -1438,7 +1424,6 @@ DEBUG: Plan 181 query after replacing subqueries and CTEs: SELECT count(*) AS c
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
|
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
|
||||||
DELETE FROM reference_table RETURNING id;
|
DELETE FROM reference_table RETURNING id;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +1,6 @@
|
||||||
--
|
--
|
||||||
-- FOREIGN_KEY_TO_REFERENCE_TABLE
|
-- FOREIGN_KEY_TO_REFERENCE_TABLE
|
||||||
--
|
--
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
version_above_nine
|
|
||||||
--------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE SCHEMA fkey_reference_table;
|
CREATE SCHEMA fkey_reference_table;
|
||||||
SET search_path TO 'fkey_reference_table';
|
SET search_path TO 'fkey_reference_table';
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
|
@ -653,8 +646,8 @@ INSERT INTO referenced_table SELECT x,x FROM generate_series(1,1000) AS f(x);
|
||||||
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
|
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
|
||||||
-- Fails for non existing value inserts (serial is already incremented)
|
-- Fails for non existing value inserts (serial is already incremented)
|
||||||
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
|
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000195" violates foreign key constraint "fkey_ref_7000195"
|
ERROR: insert or update on table "referencing_table_7000190" violates foreign key constraint "fkey_ref_7000190"
|
||||||
DETAIL: Key (ref_id)=(1009) is not present in table "referenced_table_7000187".
|
DETAIL: Key (ref_id)=(1004) is not present in table "referenced_table_7000187".
|
||||||
DROP TABLE referenced_table CASCADE;
|
DROP TABLE referenced_table CASCADE;
|
||||||
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
|
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
|
||||||
DROP TABLE referencing_table CASCADE;
|
DROP TABLE referencing_table CASCADE;
|
||||||
|
|
@ -684,8 +677,8 @@ INSERT INTO referenced_table(test_column2) SELECT x FROM generate_series(1,1000)
|
||||||
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
|
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
|
||||||
-- Fails for non existing value inserts (serial is already incremented)
|
-- Fails for non existing value inserts (serial is already incremented)
|
||||||
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
|
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000200" violates foreign key constraint "fkey_ref_7000200"
|
ERROR: insert or update on table "referencing_table_7000199" violates foreign key constraint "fkey_ref_7000199"
|
||||||
DETAIL: Key (ref_id)=(1003) is not present in table "referenced_table_7000196".
|
DETAIL: Key (ref_id)=(1004) is not present in table "referenced_table_7000196".
|
||||||
DROP TABLE referenced_table CASCADE;
|
DROP TABLE referenced_table CASCADE;
|
||||||
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
|
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
|
||||||
DROP TABLE referencing_table CASCADE;
|
DROP TABLE referencing_table CASCADE;
|
||||||
|
|
@ -826,16 +819,16 @@ INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
|
||||||
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
|
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000229" violates foreign key constraint "foreign_key_2_7000229"
|
ERROR: insert or update on table "referencing_table_7000230" violates foreign key constraint "foreign_key_2_7000230"
|
||||||
DETAIL: Key (id)=(0) is not present in table "referenced_table2_7000225".
|
DETAIL: Key (id)=(28) is not present in table "referenced_table2_7000225".
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000229" violates foreign key constraint "foreign_key_2_7000229"
|
ERROR: insert or update on table "referencing_table_7000226" violates foreign key constraint "foreign_key_2_7000226"
|
||||||
DETAIL: Key (id)=(0) is not present in table "referenced_table2_7000225".
|
DETAIL: Key (id)=(1) is not present in table "referenced_table2_7000225".
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000231" violates foreign key constraint "fkey_ref_7000231"
|
ERROR: insert or update on table "referencing_table_7000228" violates foreign key constraint "fkey_ref_7000228"
|
||||||
DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000224".
|
DETAIL: Key (id)=(1015) is not present in table "referenced_table_7000224".
|
||||||
-- should succeed
|
-- should succeed
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x);
|
||||||
SELECT count(*) FROM referencing_table;
|
SELECT count(*) FROM referencing_table;
|
||||||
|
|
@ -954,13 +947,13 @@ INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
|
||||||
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
|
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000249" violates foreign key constraint "foreign_key_2_7000249"
|
ERROR: insert or update on table "referencing_table_7000246" violates foreign key constraint "foreign_key_2_7000246"
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000249" violates foreign key constraint "foreign_key_2_7000249"
|
ERROR: insert or update on table "referencing_table_7000246" violates foreign key constraint "foreign_key_2_7000246"
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "fkey_ref_7000251"
|
ERROR: insert or update on table "referencing_table_7000248" violates foreign key constraint "fkey_ref_7000248"
|
||||||
-- should succeed
|
-- should succeed
|
||||||
INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x);
|
||||||
SELECT count(*) FROM referencing_table;
|
SELECT count(*) FROM referencing_table;
|
||||||
|
|
@ -1092,14 +1085,14 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A
|
||||||
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
|
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x);
|
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table2_7000276" violates foreign key constraint "fkey_ref_to_dist_7000276"
|
ERROR: insert or update on table "referencing_table2_7000273" violates foreign key constraint "fkey_ref_to_dist_7000273"
|
||||||
DETAIL: Key (id)=(0) is not present in table "referencing_table_7000268".
|
DETAIL: Key (id)=(1) is not present in table "referencing_table_7000265".
|
||||||
-- should succeed
|
-- should succeed
|
||||||
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
|
||||||
-- should fail
|
-- should fail
|
||||||
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x);
|
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x);
|
||||||
ERROR: insert or update on table "referencing_table2_7000274" violates foreign key constraint "fkey_ref_to_dist_7000274"
|
ERROR: insert or update on table "referencing_table2_7000273" violates foreign key constraint "fkey_ref_to_dist_7000273"
|
||||||
DETAIL: Key (id)=(403) is not present in table "referencing_table_7000266".
|
DETAIL: Key (id)=(401) is not present in table "referencing_table_7000265".
|
||||||
-- should succeed
|
-- should succeed
|
||||||
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x);
|
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x);
|
||||||
DELETE FROM referenced_table WHERE test_column < 200;
|
DELETE FROM referenced_table WHERE test_column < 200;
|
||||||
|
|
@ -1308,7 +1301,6 @@ ERROR: current transaction is aborted, commands ignored until end of transactio
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- make sure that we fail if we need parallel data load
|
-- make sure that we fail if we need parallel data load
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
||||||
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id));
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,400 +0,0 @@
|
||||||
Parsed test spec with 2 sessions
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-drop s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
error in steps s1-commit s2-drop: ERROR: table "drop_hash" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-ddl-create-index s1-commit s2-commit s1-select-count s1-show-indexes
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-create-index: CREATE INDEX drop_hash_index ON drop_hash(id); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-create-index: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-create-index: ERROR: relation "drop_hash" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''drop_hash%''');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-create-index s1-begin s2-begin s1-drop s2-ddl-drop-index s1-commit s2-commit s1-select-count s1-show-indexes
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-ddl-create-index: CREATE INDEX drop_hash_index ON drop_hash(id);
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-drop-index: DROP INDEX drop_hash_index; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-drop-index: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-drop-index: ERROR: index "drop_hash_index" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''drop_hash%''');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-drop s2-ddl-create-index-concurrently s1-commit s1-select-count s1-show-indexes
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-create-index-concurrently: CREATE INDEX CONCURRENTLY drop_hash_index ON drop_hash(id); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-create-index-concurrently: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-create-index-concurrently: ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''drop_hash%''');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-ddl-add-column s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-add-column: ALTER TABLE drop_hash ADD new_column int DEFAULT 0; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-add-column: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-add-column: ERROR: relation "drop_hash" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-add-column s1-begin s2-begin s1-drop s2-ddl-drop-column s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE drop_hash ADD new_column int DEFAULT 0;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-drop-column: ALTER TABLE drop_hash DROP new_column; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-drop-column: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-drop-column: ERROR: relation "drop_hash" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-ddl-rename-column s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-ddl-rename-column: ALTER TABLE drop_hash RENAME data TO new_column; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-rename-column: <... completed>
|
|
||||||
error in steps s1-commit s2-ddl-rename-column: ERROR: relation "drop_hash" does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-table-size s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-table-size: SELECT citus_total_relation_size('drop_hash'); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-table-size: <... completed>
|
|
||||||
error in steps s1-commit s2-table-size: ERROR: could not compute table size: relation does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-master-modify-multiple-shards s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-master-modify-multiple-shards: SELECT master_modify_multiple_shards('DROP FROM drop_hash;');
|
|
||||||
ERROR: syntax error at or near "FROM"
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-drop s1-create-non-distributed-table s1-initialize s1-begin s2-begin s1-drop s2-distribute-table s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s1-create-non-distributed-table: CREATE TABLE drop_hash(id integer, data text); COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s2-distribute-table: SELECT create_distributed_table('drop_hash', 'id'); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-distribute-table: <... completed>
|
|
||||||
error in steps s1-commit s2-distribute-table: ERROR: could not create distributed table: relation does not exist
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-create-index s2-drop s1-commit s2-commit s1-select-count s1-show-indexes
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-ddl-create-index: CREATE INDEX drop_hash_index ON drop_hash(id);
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''drop_hash%''');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-create-index s1-begin s2-begin s1-ddl-drop-index s2-drop s1-commit s2-commit s1-select-count s1-show-indexes
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-ddl-create-index: CREATE INDEX drop_hash_index ON drop_hash(id);
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-ddl-drop-index: DROP INDEX drop_hash_index;
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''drop_hash%''');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,0)
|
|
||||||
(localhost,57638,t,0)
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-add-column s2-drop s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE drop_hash ADD new_column int DEFAULT 0;
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-add-column s1-begin s2-begin s1-ddl-drop-column s2-drop s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE drop_hash ADD new_column int DEFAULT 0;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-ddl-drop-column: ALTER TABLE drop_hash DROP new_column;
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-rename-column s2-drop s1-commit s2-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-ddl-rename-column: ALTER TABLE drop_hash RENAME data TO new_column;
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''ddl_hash%'' AND column_name = ''drop_hash'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-table-size s2-drop s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-table-size: SELECT citus_total_relation_size('drop_hash');
|
|
||||||
citus_total_relation_size
|
|
||||||
|
|
||||||
57344
|
|
||||||
step s2-drop: DROP TABLE drop_hash;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s2-begin s1-master-modify-multiple-shards s2-drop s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-master-modify-multiple-shards: SELECT master_modify_multiple_shards('DROP FROM drop_hash;');
|
|
||||||
ERROR: syntax error at or near "FROM"
|
|
||||||
step s2-drop: DROP TABLE drop_hash;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1-drop s1-create-non-distributed-table s1-initialize s1-begin s2-begin s1-distribute-table s2-drop s1-commit s2-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-drop: DROP TABLE drop_hash;
|
|
||||||
step s1-create-non-distributed-table: CREATE TABLE drop_hash(id integer, data text); COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-initialize: COPY drop_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s2-begin: BEGIN;
|
|
||||||
step s1-distribute-table: SELECT create_distributed_table('drop_hash', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s2-drop: DROP TABLE drop_hash; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s2-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM drop_hash;
|
|
||||||
ERROR: relation "drop_hash" does not exist
|
|
||||||
restore_isolation_tester_func
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,570 +0,0 @@
|
||||||
Parsed test spec with 2 sessions
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
15
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-router-select s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-router-select: SELECT * FROM partitioned_copy WHERE id = 1;
|
|
||||||
id data int_data
|
|
||||||
|
|
||||||
1 b 1
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-real-time-select s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-real-time-select: SELECT * FROM partitioned_copy ORDER BY 1, 2;
|
|
||||||
id data int_data
|
|
||||||
|
|
||||||
0 a 0
|
|
||||||
1 b 1
|
|
||||||
2 c 2
|
|
||||||
3 d 3
|
|
||||||
4 e 4
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-task-tracker-select s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-task-tracker-select:
|
|
||||||
SET citus.task_executor_type TO "task-tracker";
|
|
||||||
SELECT * FROM partitioned_copy AS t1 JOIN partitioned_copy AS t2 ON t1.id = t2.int_data ORDER BY 1, 2, 3, 4;
|
|
||||||
|
|
||||||
id data int_data id data int_data
|
|
||||||
|
|
||||||
0 a 0 0 a 0
|
|
||||||
1 b 1 1 b 1
|
|
||||||
2 c 2 2 c 2
|
|
||||||
3 d 3 3 d 3
|
|
||||||
4 e 4 4 e 4
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-insert s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-insert: INSERT INTO partitioned_copy VALUES(0, 'k', 0);
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
11
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-insert-select s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-insert-select: INSERT INTO partitioned_copy SELECT * FROM partitioned_copy;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
15
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-update s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-update: UPDATE partitioned_copy SET data = 'l' WHERE id = 0;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-delete s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-delete: DELETE FROM partitioned_copy WHERE id = 1;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
9
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-truncate s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-truncate: TRUNCATE partitioned_copy; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-truncate: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-drop s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-drop: DROP TABLE partitioned_copy; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-drop: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
ERROR: relation "partitioned_copy" does not exist
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-ddl-add-column s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-ddl-add-column: ALTER TABLE partitioned_copy ADD new_column int DEFAULT 0; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-add-column: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,new_column)
|
|
||||||
(localhost,57638,t,new_column)
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-add-column s1-begin s1-copy-additional-column s2-ddl-drop-column s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE partitioned_copy ADD new_column int DEFAULT 0;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy-additional-column: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5, 5 && echo 6, g, 6, 6 && echo 7, h, 7, 7 && echo 8, i, 8, 8 && echo 9, j, 9, 9' WITH CSV;
|
|
||||||
step s2-ddl-drop-column: ALTER TABLE partitioned_copy DROP new_column; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-drop-column: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-ddl-rename-column s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-ddl-rename-column: ALTER TABLE partitioned_copy RENAME data TO new_column; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-ddl-rename-column: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,new_column)
|
|
||||||
(localhost,57638,t,new_column)
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-table-size s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-table-size: SELECT citus_total_relation_size('partitioned_copy');
|
|
||||||
citus_total_relation_size
|
|
||||||
|
|
||||||
32768
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-master-modify-multiple-shards s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-master-modify-multiple-shards: DELETE FROM partitioned_copy;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
5
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-copy s2-master-drop-all-shards s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-master-drop-all-shards: SELECT master_drop_all_shards('partitioned_copy'::regclass, 'public', 'partitioned_copy'); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-master-drop-all-shards: <... completed>
|
|
||||||
master_drop_all_shards
|
|
||||||
|
|
||||||
4
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
starting permutation: s1-drop s1-create-non-distributed-table s1-initialize s1-begin s1-copy s2-distribute-table s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-drop: DROP TABLE partitioned_copy;
|
|
||||||
step s1-create-non-distributed-table: CREATE TABLE partitioned_copy(id integer, data text, int_data int); COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s2-distribute-table: SELECT create_distributed_table('partitioned_copy', 'id'); <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-distribute-table: <... completed>
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
15
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-router-select s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-router-select: SELECT * FROM partitioned_copy WHERE id = 1;
|
|
||||||
id data int_data
|
|
||||||
|
|
||||||
1 b 1
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-real-time-select s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-real-time-select: SELECT * FROM partitioned_copy ORDER BY 1, 2;
|
|
||||||
id data int_data
|
|
||||||
|
|
||||||
0 a 0
|
|
||||||
1 b 1
|
|
||||||
2 c 2
|
|
||||||
3 d 3
|
|
||||||
4 e 4
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-task-tracker-select s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-task-tracker-select:
|
|
||||||
SET citus.task_executor_type TO "task-tracker";
|
|
||||||
SELECT * FROM partitioned_copy AS t1 JOIN partitioned_copy AS t2 ON t1.id = t2.int_data ORDER BY 1, 2, 3, 4;
|
|
||||||
|
|
||||||
id data int_data id data int_data
|
|
||||||
|
|
||||||
0 a 0 0 a 0
|
|
||||||
1 b 1 1 b 1
|
|
||||||
2 c 2 2 c 2
|
|
||||||
3 d 3 3 d 3
|
|
||||||
4 e 4 4 e 4
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-insert s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-insert: INSERT INTO partitioned_copy VALUES(0, 'k', 0);
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
11
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-insert-select s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-insert-select: INSERT INTO partitioned_copy SELECT * FROM partitioned_copy;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
15
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-update s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-update: UPDATE partitioned_copy SET data = 'l' WHERE id = 0;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-delete s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-delete: DELETE FROM partitioned_copy WHERE id = 1;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
9
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-truncate s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-truncate: TRUNCATE partitioned_copy;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
5
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-drop s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-drop: DROP TABLE partitioned_copy;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
error in steps s1-commit s2-copy: ERROR: relation "partitioned_copy" does not exist
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
ERROR: relation "partitioned_copy" does not exist
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-ddl-add-column s2-copy s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE partitioned_copy ADD new_column int DEFAULT 0;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
error in steps s1-commit s2-copy: ERROR: missing data for column "new_column"
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
5
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,new_column)
|
|
||||||
(localhost,57638,t,new_column)
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-ddl-add-column s1-begin s1-ddl-drop-column s2-copy s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-ddl-add-column: ALTER TABLE partitioned_copy ADD new_column int DEFAULT 0;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-ddl-drop-column: ALTER TABLE partitioned_copy DROP new_column;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-ddl-rename-column s2-copy s1-commit s1-select-count s1-show-columns
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-ddl-rename-column: ALTER TABLE partitioned_copy RENAME data TO new_column;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''partitioned_copy%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
|
|
||||||
run_command_on_workers
|
|
||||||
|
|
||||||
(localhost,57637,t,new_column)
|
|
||||||
(localhost,57638,t,new_column)
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-table-size s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-table-size: SELECT citus_total_relation_size('partitioned_copy');
|
|
||||||
citus_total_relation_size
|
|
||||||
|
|
||||||
32768
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-master-modify-multiple-shards s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-master-modify-multiple-shards: DELETE FROM partitioned_copy;
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV;
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
5
|
|
||||||
|
|
||||||
starting permutation: s1-initialize s1-begin s1-master-drop-all-shards s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-master-drop-all-shards: SELECT master_drop_all_shards('partitioned_copy'::regclass, 'public', 'partitioned_copy');
|
|
||||||
master_drop_all_shards
|
|
||||||
|
|
||||||
4
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
error in steps s1-commit s2-copy: ERROR: could not find any shards into which to copy
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
starting permutation: s1-drop s1-create-non-distributed-table s1-initialize s1-begin s1-distribute-table s2-copy s1-commit s1-select-count
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s1-drop: DROP TABLE partitioned_copy;
|
|
||||||
step s1-create-non-distributed-table: CREATE TABLE partitioned_copy(id integer, data text, int_data int); COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-initialize: COPY partitioned_copy FROM PROGRAM 'echo 0, a, 0 && echo 1, b, 1 && echo 2, c, 2 && echo 3, d, 3 && echo 4, e, 4' WITH CSV;
|
|
||||||
step s1-begin: BEGIN;
|
|
||||||
step s1-distribute-table: SELECT create_distributed_table('partitioned_copy', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
|
|
||||||
|
|
||||||
step s2-copy: COPY partitioned_copy FROM PROGRAM 'echo 5, f, 5 && echo 6, g, 6 && echo 7, h, 7 && echo 8, i, 8 && echo 9, j, 9' WITH CSV; <waiting ...>
|
|
||||||
step s1-commit: COMMIT;
|
|
||||||
step s2-copy: <... completed>
|
|
||||||
step s1-select-count: SELECT COUNT(*) FROM partitioned_copy;
|
|
||||||
count
|
|
||||||
|
|
||||||
15
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,14 +1,6 @@
|
||||||
--
|
--
|
||||||
-- MULTI_CREATE_TABLE_NEW_FEATURES
|
-- MULTI_CREATE_TABLE_NEW_FEATURES
|
||||||
--
|
--
|
||||||
-- print major version to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+') AS major_version;
|
|
||||||
major_version
|
|
||||||
---------------
|
|
||||||
10
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Verify that the GENERATED ... AS IDENTITY feature in PostgreSQL 10
|
-- Verify that the GENERATED ... AS IDENTITY feature in PostgreSQL 10
|
||||||
-- is forbidden in distributed tables.
|
-- is forbidden in distributed tables.
|
||||||
CREATE TABLE table_identity_col (
|
CREATE TABLE table_identity_col (
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,3 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
\endif
|
|
||||||
--
|
--
|
||||||
-- Regression tests for deparsing ALTER/DROP PROCEDURE Queries
|
-- Regression tests for deparsing ALTER/DROP PROCEDURE Queries
|
||||||
--
|
--
|
||||||
|
|
@ -38,14 +31,6 @@ CREATE SCHEMA procedure_tests;
|
||||||
SET search_path TO procedure_tests;
|
SET search_path TO procedure_tests;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET client_min_messages TO INFO;
|
SET client_min_messages TO INFO;
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE FUNCTION deparse_test(text)
|
CREATE FUNCTION deparse_test(text)
|
||||||
RETURNS text
|
RETURNS text
|
||||||
AS 'citus'
|
AS 'citus'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
|
|
@ -2,14 +2,6 @@
|
||||||
-- MULTI_EXPLAIN
|
-- MULTI_EXPLAIN
|
||||||
--
|
--
|
||||||
SET citus.next_shard_id TO 570000;
|
SET citus.next_shard_id TO 570000;
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
version_above_nine
|
|
||||||
--------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\a\t
|
\a\t
|
||||||
RESET citus.task_executor_type;
|
RESET citus.task_executor_type;
|
||||||
SET citus.explain_distributed_queries TO on;
|
SET citus.explain_distributed_queries TO on;
|
||||||
|
|
@ -786,7 +778,6 @@ t
|
||||||
SELECT true AS valid FROM explain_json($$
|
SELECT true AS valid FROM explain_json($$
|
||||||
SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030$$);
|
SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030$$);
|
||||||
t
|
t
|
||||||
|
|
||||||
-- Test multi shard update
|
-- Test multi shard update
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
UPDATE lineitem_hash_part
|
UPDATE lineitem_hash_part
|
||||||
|
|
@ -810,7 +801,6 @@ Custom Scan (Citus Adaptive)
|
||||||
Node: host=localhost port=57638 dbname=regression
|
Node: host=localhost port=57638 dbname=regression
|
||||||
-> Update on lineitem_hash_part_360044 lineitem_hash_part
|
-> Update on lineitem_hash_part_360044 lineitem_hash_part
|
||||||
-> Seq Scan on lineitem_hash_part_360044 lineitem_hash_part
|
-> Seq Scan on lineitem_hash_part_360044 lineitem_hash_part
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
UPDATE lineitem_hash_part
|
UPDATE lineitem_hash_part
|
||||||
SET l_suppkey = 12
|
SET l_suppkey = 12
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,6 @@
|
||||||
--
|
--
|
||||||
-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed
|
-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed
|
||||||
-- tables.
|
-- tables.
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
server_version_above_ten
|
|
||||||
--------------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- CREATE TEST TABLES
|
-- CREATE TEST TABLES
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -1,312 +0,0 @@
|
||||||
--
|
|
||||||
-- MULTI_INDEX_STATEMENTS
|
|
||||||
--
|
|
||||||
-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed
|
|
||||||
-- tables.
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
server_version_above_ten
|
|
||||||
--------------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
--
|
|
||||||
-- CREATE TEST TABLES
|
|
||||||
--
|
|
||||||
SET citus.next_shard_id TO 102080;
|
|
||||||
CREATE TABLE index_test_range(a int, b int, c int);
|
|
||||||
SELECT create_distributed_table('index_test_range', 'a', 'range');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('index_test_range');
|
|
||||||
master_create_empty_shard
|
|
||||||
---------------------------
|
|
||||||
102080
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('index_test_range');
|
|
||||||
master_create_empty_shard
|
|
||||||
---------------------------
|
|
||||||
102081
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.shard_count TO 8;
|
|
||||||
SET citus.shard_replication_factor TO 2;
|
|
||||||
CREATE TABLE index_test_hash(a int, b int, c int);
|
|
||||||
SELECT create_distributed_table('index_test_hash', 'a', 'hash');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE index_test_append(a int, b int, c int);
|
|
||||||
SELECT create_distributed_table('index_test_append', 'a', 'append');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('index_test_append');
|
|
||||||
master_create_empty_shard
|
|
||||||
---------------------------
|
|
||||||
102090
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('index_test_append');
|
|
||||||
master_create_empty_shard
|
|
||||||
---------------------------
|
|
||||||
102091
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
--
|
|
||||||
-- CREATE INDEX
|
|
||||||
--
|
|
||||||
-- Verify that we can create different types of indexes
|
|
||||||
CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey);
|
|
||||||
CREATE INDEX lineitem_partkey_desc_index ON lineitem (l_partkey DESC);
|
|
||||||
CREATE INDEX lineitem_partial_index ON lineitem (l_shipdate)
|
|
||||||
WHERE l_shipdate < '1995-01-01';
|
|
||||||
CREATE INDEX lineitem_colref_index ON lineitem (record_ne(lineitem.*, NULL));
|
|
||||||
SET client_min_messages = ERROR; -- avoid version dependant warning about WAL
|
|
||||||
CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey);
|
|
||||||
CREATE UNIQUE INDEX index_test_range_index_a ON index_test_range(a);
|
|
||||||
CREATE UNIQUE INDEX index_test_range_index_a_b ON index_test_range(a,b);
|
|
||||||
CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash(a);
|
|
||||||
CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash(a,b);
|
|
||||||
CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash(a,b) WHERE c IS NOT NULL;
|
|
||||||
CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range(a,b) WHERE c IS NOT NULL;
|
|
||||||
CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b,c);
|
|
||||||
ERROR: syntax error at or near "INCLUDE"
|
|
||||||
LINE 1: ...index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b...
|
|
||||||
^
|
|
||||||
RESET client_min_messages;
|
|
||||||
-- Verify that we handle if not exists statements correctly
|
|
||||||
CREATE INDEX lineitem_orderkey_index on lineitem(l_orderkey);
|
|
||||||
ERROR: relation "lineitem_orderkey_index" already exists
|
|
||||||
CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on lineitem(l_orderkey);
|
|
||||||
NOTICE: relation "lineitem_orderkey_index" already exists, skipping
|
|
||||||
CREATE INDEX IF NOT EXISTS lineitem_orderkey_index_new on lineitem(l_orderkey);
|
|
||||||
-- Verify if not exists behavior with an index with same name on a different table
|
|
||||||
CREATE INDEX lineitem_orderkey_index on index_test_hash(a);
|
|
||||||
ERROR: relation "lineitem_orderkey_index" already exists
|
|
||||||
CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on index_test_hash(a);
|
|
||||||
NOTICE: relation "lineitem_orderkey_index" already exists, skipping
|
|
||||||
-- Verify that we can create indexes concurrently
|
|
||||||
CREATE INDEX CONCURRENTLY lineitem_concurrently_index ON lineitem (l_orderkey);
|
|
||||||
-- Verify that we warn out on CLUSTER command for distributed tables and no parameter
|
|
||||||
CLUSTER index_test_hash USING index_test_hash_index_a;
|
|
||||||
WARNING: not propagating CLUSTER command to worker nodes
|
|
||||||
CLUSTER;
|
|
||||||
WARNING: not propagating CLUSTER command to worker nodes
|
|
||||||
-- Verify that no-name local CREATE INDEX CONCURRENTLY works
|
|
||||||
CREATE TABLE local_table (id integer, name text);
|
|
||||||
CREATE INDEX CONCURRENTLY local_table_index ON local_table(id);
|
|
||||||
-- Vefify we don't warn out on CLUSTER command for local tables
|
|
||||||
CLUSTER local_table USING local_table_index;
|
|
||||||
DROP TABLE local_table;
|
|
||||||
-- Verify that all indexes got created on the master node and one of the workers
|
|
||||||
SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname;
|
|
||||||
schemaname | tablename | indexname | tablespace | indexdef
|
|
||||||
------------+------------------+------------------------------------+------------+----------------------------------------------------------------------------------------------------------------------------
|
|
||||||
public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a)
|
|
||||||
public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b)
|
|
||||||
public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL)
|
|
||||||
public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a)
|
|
||||||
public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b)
|
|
||||||
public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL)
|
|
||||||
public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record))
|
|
||||||
public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey)
|
|
||||||
public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date)
|
|
||||||
public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC)
|
|
||||||
public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber)
|
|
||||||
public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate)
|
|
||||||
(15 rows)
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT count(*) FROM pg_indexes WHERE tablename = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
9
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_hash%';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
24
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_range%';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
6
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_append%';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
-- Verify that we error out on unsupported statement types
|
|
||||||
CREATE UNIQUE INDEX try_index ON lineitem (l_orderkey);
|
|
||||||
ERROR: creating unique indexes on append-partitioned tables is currently unsupported
|
|
||||||
CREATE INDEX try_index ON lineitem (l_orderkey) TABLESPACE newtablespace;
|
|
||||||
ERROR: specifying tablespaces with CREATE INDEX statements is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_range_index ON index_test_range(b);
|
|
||||||
ERROR: creating unique indexes on non-partition columns is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_range_index_partial ON index_test_range(b) WHERE c IS NOT NULL;
|
|
||||||
ERROR: creating unique indexes on non-partition columns is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_hash_index ON index_test_hash(b);
|
|
||||||
ERROR: creating unique indexes on non-partition columns is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_hash_index_partial ON index_test_hash(b) WHERE c IS NOT NULL;
|
|
||||||
ERROR: creating unique indexes on non-partition columns is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_append_index ON index_test_append(b);
|
|
||||||
ERROR: creating unique indexes on append-partitioned tables is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_append_index ON index_test_append(a);
|
|
||||||
ERROR: creating unique indexes on append-partitioned tables is currently unsupported
|
|
||||||
CREATE UNIQUE INDEX try_unique_append_index_a_b ON index_test_append(a,b);
|
|
||||||
ERROR: creating unique indexes on append-partitioned tables is currently unsupported
|
|
||||||
-- Verify that we error out in case of postgres errors on supported statement
|
|
||||||
-- types.
|
|
||||||
CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey);
|
|
||||||
ERROR: relation "lineitem_orderkey_index" already exists
|
|
||||||
CREATE INDEX try_index ON lineitem USING gist (l_orderkey);
|
|
||||||
ERROR: data type bigint has no default operator class for access method "gist"
|
|
||||||
HINT: You must specify an operator class for the index or define a default operator class for the data type.
|
|
||||||
CREATE INDEX try_index ON lineitem (non_existent_column);
|
|
||||||
ERROR: column "non_existent_column" does not exist
|
|
||||||
CREATE INDEX ON lineitem (l_orderkey);
|
|
||||||
ERROR: creating index without a name on a distributed table is currently unsupported
|
|
||||||
-- Verify that none of failed indexes got created on the master node
|
|
||||||
SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname;
|
|
||||||
schemaname | tablename | indexname | tablespace | indexdef
|
|
||||||
------------+------------------+------------------------------------+------------+----------------------------------------------------------------------------------------------------------------------------
|
|
||||||
public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a)
|
|
||||||
public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b)
|
|
||||||
public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL)
|
|
||||||
public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a)
|
|
||||||
public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b)
|
|
||||||
public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL)
|
|
||||||
public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record))
|
|
||||||
public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey)
|
|
||||||
public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey)
|
|
||||||
public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date)
|
|
||||||
public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC)
|
|
||||||
public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber)
|
|
||||||
public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate)
|
|
||||||
(15 rows)
|
|
||||||
|
|
||||||
--
|
|
||||||
-- REINDEX
|
|
||||||
--
|
|
||||||
REINDEX INDEX lineitem_orderkey_index;
|
|
||||||
REINDEX TABLE lineitem;
|
|
||||||
REINDEX SCHEMA public;
|
|
||||||
REINDEX DATABASE regression;
|
|
||||||
REINDEX SYSTEM regression;
|
|
||||||
--
|
|
||||||
-- DROP INDEX
|
|
||||||
--
|
|
||||||
-- Verify that we can't drop multiple indexes in a single command
|
|
||||||
DROP INDEX lineitem_orderkey_index, lineitem_partial_index;
|
|
||||||
ERROR: cannot drop multiple distributed objects in a single command
|
|
||||||
HINT: Try dropping each object in a separate DROP command.
|
|
||||||
-- Verify that we can succesfully drop indexes
|
|
||||||
DROP INDEX lineitem_orderkey_index;
|
|
||||||
DROP INDEX lineitem_orderkey_index_new;
|
|
||||||
DROP INDEX lineitem_partkey_desc_index;
|
|
||||||
DROP INDEX lineitem_partial_index;
|
|
||||||
DROP INDEX lineitem_colref_index;
|
|
||||||
-- Verify that we handle if exists statements correctly
|
|
||||||
DROP INDEX non_existent_index;
|
|
||||||
ERROR: index "non_existent_index" does not exist
|
|
||||||
DROP INDEX IF EXISTS non_existent_index;
|
|
||||||
NOTICE: index "non_existent_index" does not exist, skipping
|
|
||||||
DROP INDEX IF EXISTS lineitem_orderkey_hash_index;
|
|
||||||
DROP INDEX lineitem_orderkey_hash_index;
|
|
||||||
ERROR: index "lineitem_orderkey_hash_index" does not exist
|
|
||||||
DROP INDEX index_test_range_index_a;
|
|
||||||
DROP INDEX index_test_range_index_a_b;
|
|
||||||
DROP INDEX index_test_range_index_a_b_partial;
|
|
||||||
DROP INDEX index_test_hash_index_a;
|
|
||||||
DROP INDEX index_test_hash_index_a_b;
|
|
||||||
DROP INDEX index_test_hash_index_a_b_partial;
|
|
||||||
-- Verify that we can drop indexes concurrently
|
|
||||||
DROP INDEX CONCURRENTLY lineitem_concurrently_index;
|
|
||||||
-- Verify that all the indexes are dropped from the master and one worker node.
|
|
||||||
-- As there's a primary key, so exclude those from this check.
|
|
||||||
SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1)::regclass AND NOT indisprimary AND indexrelid::regclass::text NOT LIKE 'lineitem_time_index%';
|
|
||||||
indrelid | indexrelid
|
|
||||||
----------+------------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname;
|
|
||||||
schemaname | tablename | indexname | tablespace | indexdef
|
|
||||||
------------+-----------+-----------+------------+----------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1)::regclass AND NOT indisprimary AND indexrelid::regclass::text NOT LIKE 'lineitem_time_index%';
|
|
||||||
indrelid | indexrelid
|
|
||||||
----------+------------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname;
|
|
||||||
schemaname | tablename | indexname | tablespace | indexdef
|
|
||||||
------------+-----------+-----------+------------+----------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
-- create index that will conflict with master operations
|
|
||||||
CREATE INDEX CONCURRENTLY ith_b_idx_102089 ON index_test_hash_102089(b);
|
|
||||||
\c - - - :master_port
|
|
||||||
-- should fail because worker index already exists
|
|
||||||
CREATE INDEX CONCURRENTLY ith_b_idx ON index_test_hash(b);
|
|
||||||
ERROR: CONCURRENTLY-enabled index command failed
|
|
||||||
DETAIL: CONCURRENTLY-enabled index commands can fail partially, leaving behind an INVALID index.
|
|
||||||
HINT: Use DROP INDEX CONCURRENTLY IF EXISTS to remove the invalid index, then retry the original command.
|
|
||||||
-- the failure results in an INVALID index
|
|
||||||
SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass;
|
|
||||||
Index Valid?
|
|
||||||
--------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- we can clean it up and recreate with an DROP IF EXISTS
|
|
||||||
DROP INDEX CONCURRENTLY IF EXISTS ith_b_idx;
|
|
||||||
CREATE INDEX CONCURRENTLY ith_b_idx ON index_test_hash(b);
|
|
||||||
SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass;
|
|
||||||
Index Valid?
|
|
||||||
--------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
-- now drop shard index to test partial master DROP failure
|
|
||||||
DROP INDEX CONCURRENTLY ith_b_idx_102089;
|
|
||||||
\c - - - :master_port
|
|
||||||
DROP INDEX CONCURRENTLY ith_b_idx;
|
|
||||||
ERROR: CONCURRENTLY-enabled index command failed
|
|
||||||
DETAIL: CONCURRENTLY-enabled index commands can fail partially, leaving behind an INVALID index.
|
|
||||||
HINT: Use DROP INDEX CONCURRENTLY IF EXISTS to remove the invalid index, then retry the original command.
|
|
||||||
-- the failure results in an INVALID index
|
|
||||||
SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass;
|
|
||||||
Index Valid?
|
|
||||||
--------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- final clean up
|
|
||||||
DROP INDEX CONCURRENTLY IF EXISTS ith_b_idx;
|
|
||||||
-- Drop created tables
|
|
||||||
DROP TABLE index_test_range;
|
|
||||||
DROP TABLE index_test_hash;
|
|
||||||
DROP TABLE index_test_append;
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
-- if the output of following query changes, we might need to change
|
-- if the output of following query changes, we might need to change
|
||||||
-- some heap_getattr() calls to heap_deform_tuple(). This errors out in
|
-- some heap_getattr() calls to heap_deform_tuple().
|
||||||
-- postgres versions before 11.
|
|
||||||
SELECT attrelid::regclass, attname, atthasmissing, attmissingval
|
SELECT attrelid::regclass, attname, atthasmissing, attmissingval
|
||||||
FROM pg_attribute
|
FROM pg_attribute
|
||||||
WHERE atthasmissing
|
WHERE atthasmissing
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
-- if the output of following query changes, we might need to change
|
|
||||||
-- some heap_getattr() calls to heap_deform_tuple(). This errors out in
|
|
||||||
-- postgres versions before 11.
|
|
||||||
SELECT attrelid::regclass, attname, atthasmissing, attmissingval
|
|
||||||
FROM pg_attribute
|
|
||||||
WHERE atthasmissing
|
|
||||||
ORDER BY attrelid, attname;
|
|
||||||
ERROR: column "atthasmissing" does not exist
|
|
||||||
LINE 1: SELECT attrelid::regclass, attname, atthasmissing, attmissin...
|
|
||||||
^
|
|
||||||
|
|
@ -3,14 +3,6 @@
|
||||||
--
|
--
|
||||||
-- Test user permissions.
|
-- Test user permissions.
|
||||||
--
|
--
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 1420000;
|
SET citus.next_shard_id TO 1420000;
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
ALTER SYSTEM SET citus.metadata_sync_interval TO 3000;
|
ALTER SYSTEM SET citus.metadata_sync_interval TO 3000;
|
||||||
|
|
|
||||||
|
|
@ -1,693 +0,0 @@
|
||||||
--
|
|
||||||
-- MULTI_MULTIUSERS
|
|
||||||
--
|
|
||||||
-- Test user permissions.
|
|
||||||
--
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 1420000;
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
CREATE TABLE test (id integer, val integer);
|
|
||||||
SELECT create_distributed_table('test', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE test_coloc (id integer, val integer);
|
|
||||||
SELECT create_distributed_table('test_coloc', 'id', colocate_with := 'none');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.shard_count TO 1;
|
|
||||||
CREATE TABLE singleshard (id integer, val integer);
|
|
||||||
SELECT create_distributed_table('singleshard', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- turn off propagation to avoid Enterprise processing the following section
|
|
||||||
SET citus.enable_ddl_propagation TO off;
|
|
||||||
CREATE USER full_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER usage_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER read_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER no_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE ROLE some_role;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
GRANT some_role TO full_access;
|
|
||||||
GRANT some_role TO read_access;
|
|
||||||
GRANT ALL ON TABLE test TO full_access;
|
|
||||||
GRANT SELECT ON TABLE test TO read_access;
|
|
||||||
CREATE SCHEMA full_access_user_schema;
|
|
||||||
REVOKE ALL ON SCHEMA full_access_user_schema FROM PUBLIC;
|
|
||||||
GRANT ALL ON SCHEMA full_access_user_schema TO full_access;
|
|
||||||
GRANT USAGE ON SCHEMA full_access_user_schema TO usage_access;
|
|
||||||
SET citus.enable_ddl_propagation TO DEFAULT;
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
CREATE USER full_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER usage_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER read_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER no_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE ROLE some_role;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
GRANT some_role TO full_access;
|
|
||||||
GRANT some_role TO read_access;
|
|
||||||
GRANT ALL ON TABLE test_1420000 TO full_access;
|
|
||||||
GRANT SELECT ON TABLE test_1420000 TO read_access;
|
|
||||||
GRANT ALL ON TABLE test_1420002 TO full_access;
|
|
||||||
GRANT SELECT ON TABLE test_1420002 TO read_access;
|
|
||||||
CREATE SCHEMA full_access_user_schema;
|
|
||||||
REVOKE ALL ON SCHEMA full_access_user_schema FROM PUBLIC;
|
|
||||||
GRANT USAGE ON SCHEMA full_access_user_schema TO full_access;
|
|
||||||
GRANT ALL ON SCHEMA full_access_user_schema TO full_access;
|
|
||||||
GRANT USAGE ON SCHEMA full_access_user_schema TO usage_access;
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
CREATE USER full_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER usage_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER read_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE USER no_access;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
CREATE ROLE some_role;
|
|
||||||
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
|
|
||||||
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
|
|
||||||
GRANT some_role TO full_access;
|
|
||||||
GRANT some_role TO read_access;
|
|
||||||
GRANT ALL ON TABLE test_1420001 TO full_access;
|
|
||||||
GRANT SELECT ON TABLE test_1420001 TO read_access;
|
|
||||||
GRANT ALL ON TABLE test_1420003 TO full_access;
|
|
||||||
GRANT SELECT ON TABLE test_1420003 TO read_access;
|
|
||||||
CREATE SCHEMA full_access_user_schema;
|
|
||||||
REVOKE ALL ON SCHEMA full_access_user_schema FROM PUBLIC;
|
|
||||||
GRANT USAGE ON SCHEMA full_access_user_schema TO full_access;
|
|
||||||
GRANT ALL ON SCHEMA full_access_user_schema TO full_access;
|
|
||||||
GRANT USAGE ON SCHEMA full_access_user_schema TO usage_access;
|
|
||||||
\c - - - :master_port
|
|
||||||
-- create prepare tests
|
|
||||||
PREPARE prepare_insert AS INSERT INTO test VALUES ($1);
|
|
||||||
PREPARE prepare_select AS SELECT count(*) FROM test;
|
|
||||||
-- not allowed to read absolute paths, even as superuser
|
|
||||||
COPY "/etc/passwd" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: absolute path not allowed
|
|
||||||
-- not allowed to read paths outside pgsql_job_cache, even as superuser
|
|
||||||
COPY "postgresql.conf" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: path must be in the pgsql_job_cache directory
|
|
||||||
-- check full permission
|
|
||||||
SET ROLE full_access;
|
|
||||||
EXECUTE prepare_insert(1);
|
|
||||||
EXECUTE prepare_select;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO test VALUES (2);
|
|
||||||
SELECT count(*) FROM test;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM test WHERE id = 1;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
|
||||||
SELECT count(*), min(current_user) FROM test;
|
|
||||||
count | min
|
|
||||||
-------+-------------
|
|
||||||
2 | full_access
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test re-partition query (needs to transmit intermediate results)
|
|
||||||
SELECT count(*) FROM test a JOIN test b ON (a.val = b.val) WHERE a.id = 1 AND b.id = 2;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- should not be able to transmit directly
|
|
||||||
COPY "postgresql.conf" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: operation is not allowed
|
|
||||||
HINT: Run the command with a superuser.
|
|
||||||
RESET citus.task_executor_type;
|
|
||||||
-- should not be able to transmit directly
|
|
||||||
COPY "postgresql.conf" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: operation is not allowed
|
|
||||||
HINT: Run the command with a superuser.
|
|
||||||
-- create a task that other users should not be able to inspect
|
|
||||||
SELECT task_tracker_assign_task(1, 1, 'SELECT 1');
|
|
||||||
task_tracker_assign_task
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- check read permission
|
|
||||||
SET ROLE read_access;
|
|
||||||
EXECUTE prepare_insert(1);
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
EXECUTE prepare_select;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO test VALUES (2);
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
SELECT count(*) FROM test;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM test WHERE id = 1;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
|
||||||
SELECT count(*), min(current_user) FROM test;
|
|
||||||
count | min
|
|
||||||
-------+-------------
|
|
||||||
2 | read_access
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test re-partition query (needs to transmit intermediate results)
|
|
||||||
SELECT count(*) FROM test a JOIN test b ON (a.val = b.val) WHERE a.id = 1 AND b.id = 2;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- should not be able to transmit directly
|
|
||||||
COPY "postgresql.conf" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: operation is not allowed
|
|
||||||
HINT: Run the command with a superuser.
|
|
||||||
-- should not be able to access tasks or jobs belonging to a different user
|
|
||||||
SELECT task_tracker_task_status(1, 1);
|
|
||||||
ERROR: could not find the worker task
|
|
||||||
DETAIL: Task jobId: 1 and taskId: 1
|
|
||||||
SELECT task_tracker_assign_task(1, 2, 'SELECT 1');
|
|
||||||
ERROR: must be owner of schema pg_merge_job_0001
|
|
||||||
SELECT task_tracker_cleanup_job(1);
|
|
||||||
ERROR: must be owner of schema pg_merge_job_0001
|
|
||||||
-- should not be allowed to take aggressive locks on table
|
|
||||||
BEGIN;
|
|
||||||
SELECT lock_relation_if_exists('test', 'ACCESS SHARE');
|
|
||||||
lock_relation_if_exists
|
|
||||||
-------------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT lock_relation_if_exists('test', 'EXCLUSIVE');
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
ABORT;
|
|
||||||
RESET citus.task_executor_type;
|
|
||||||
-- check no permission
|
|
||||||
SET ROLE no_access;
|
|
||||||
EXECUTE prepare_insert(1);
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
EXECUTE prepare_select;
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
INSERT INTO test VALUES (2);
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
SELECT count(*) FROM test;
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
SELECT count(*) FROM test WHERE id = 1;
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
|
||||||
SELECT count(*), min(current_user) FROM test;
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
-- test re-partition query
|
|
||||||
SELECT count(*) FROM test a JOIN test b ON (a.val = b.val) WHERE a.id = 1 AND b.id = 2;
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
-- should not be able to transmit directly
|
|
||||||
COPY "postgresql.conf" TO STDOUT WITH (format transmit);
|
|
||||||
ERROR: operation is not allowed
|
|
||||||
HINT: Run the command with a superuser.
|
|
||||||
RESET citus.task_executor_type;
|
|
||||||
-- should be able to use intermediate results as any user
|
|
||||||
BEGIN;
|
|
||||||
SELECT create_intermediate_result('topten', 'SELECT s FROM generate_series(1,10) s');
|
|
||||||
create_intermediate_result
|
|
||||||
----------------------------
|
|
||||||
10
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT * FROM read_intermediate_result('topten', 'binary'::citus_copy_format) AS res (s int) ORDER BY s;
|
|
||||||
s
|
|
||||||
----
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
6
|
|
||||||
7
|
|
||||||
8
|
|
||||||
9
|
|
||||||
10
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
END;
|
|
||||||
-- as long as we don't read from a table
|
|
||||||
BEGIN;
|
|
||||||
SELECT create_intermediate_result('topten', 'SELECT count(*) FROM test');
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
ABORT;
|
|
||||||
SELECT * FROM citus_stat_statements_reset();
|
|
||||||
ERROR: permission denied for function citus_stat_statements_reset
|
|
||||||
-- should not be allowed to upgrade to reference table
|
|
||||||
SELECT upgrade_to_reference_table('singleshard');
|
|
||||||
ERROR: must be owner of relation singleshard
|
|
||||||
-- should not be allowed to co-located tables
|
|
||||||
SELECT mark_tables_colocated('test', ARRAY['test_coloc'::regclass]);
|
|
||||||
ERROR: must be owner of relation test
|
|
||||||
-- should not be allowed to take any locks
|
|
||||||
BEGIN;
|
|
||||||
SELECT lock_relation_if_exists('test', 'ACCESS SHARE');
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
ABORT;
|
|
||||||
BEGIN;
|
|
||||||
SELECT lock_relation_if_exists('test', 'EXCLUSIVE');
|
|
||||||
ERROR: permission denied for relation test
|
|
||||||
ABORT;
|
|
||||||
-- table owner should be the same on the shards, even when distributing the table as superuser
|
|
||||||
SET ROLE full_access;
|
|
||||||
CREATE TABLE my_table (id integer, val integer);
|
|
||||||
RESET ROLE;
|
|
||||||
SELECT create_distributed_table('my_table', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT result FROM run_command_on_workers($$SELECT tableowner FROM pg_tables WHERE tablename LIKE 'my_table_%' LIMIT 1$$);
|
|
||||||
result
|
|
||||||
-------------
|
|
||||||
full_access
|
|
||||||
full_access
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT task_tracker_cleanup_job(1);
|
|
||||||
task_tracker_cleanup_job
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- table should be distributable by super user when it has data in there
|
|
||||||
SET ROLE full_access;
|
|
||||||
CREATE TABLE my_table_with_data (id integer, val integer);
|
|
||||||
INSERT INTO my_table_with_data VALUES (1,2);
|
|
||||||
RESET ROLE;
|
|
||||||
SELECT create_distributed_table('my_table_with_data', 'id');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM my_table_with_data;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- table that is owned by a role should be distributable by a user that has that role granted
|
|
||||||
-- while it should not be if the user has the role not granted
|
|
||||||
SET ROLE full_access;
|
|
||||||
CREATE TABLE my_role_table_with_data (id integer, val integer);
|
|
||||||
ALTER TABLE my_role_table_with_data OWNER TO some_role;
|
|
||||||
INSERT INTO my_role_table_with_data VALUES (1,2);
|
|
||||||
RESET ROLE;
|
|
||||||
-- we first try to distribute it with a user that does not have the role so we can reuse the table
|
|
||||||
SET ROLE no_access;
|
|
||||||
SELECT create_distributed_table('my_role_table_with_data', 'id');
|
|
||||||
ERROR: must be owner of relation my_role_table_with_data
|
|
||||||
RESET ROLE;
|
|
||||||
-- then we try to distribute it with a user that has the role but different then the one creating
|
|
||||||
SET ROLE read_access;
|
|
||||||
SELECT create_distributed_table('my_role_table_with_data', 'id');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- lastly we want to verify the table owner is set to the role, not the user that distributed
|
|
||||||
SELECT result FROM run_command_on_workers($cmd$
|
|
||||||
SELECT tableowner FROM pg_tables WHERE tablename LIKE 'my_role_table_with_data%' LIMIT 1;
|
|
||||||
$cmd$);
|
|
||||||
result
|
|
||||||
-----------
|
|
||||||
some_role
|
|
||||||
some_role
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- we want to verify a user without CREATE access cannot distribute its table, but can get
|
|
||||||
-- its table distributed by the super user
|
|
||||||
-- we want to make sure the schema and user are setup in such a way they can't create a
|
|
||||||
-- table
|
|
||||||
SET ROLE usage_access;
|
|
||||||
CREATE TABLE full_access_user_schema.t1 (id int);
|
|
||||||
ERROR: permission denied for schema full_access_user_schema
|
|
||||||
LINE 1: CREATE TABLE full_access_user_schema.t1 (id int);
|
|
||||||
^
|
|
||||||
RESET ROLE;
|
|
||||||
-- now we create the table for the user
|
|
||||||
CREATE TABLE full_access_user_schema.t1 (id int);
|
|
||||||
ALTER TABLE full_access_user_schema.t1 OWNER TO usage_access;
|
|
||||||
-- make sure we can insert data
|
|
||||||
SET ROLE usage_access;
|
|
||||||
INSERT INTO full_access_user_schema.t1 VALUES (1),(2),(3);
|
|
||||||
-- creating the table should fail with a failure on the worker machine since the user is
|
|
||||||
-- not allowed to create a table
|
|
||||||
SELECT create_distributed_table('full_access_user_schema.t1', 'id');
|
|
||||||
ERROR: permission denied for schema full_access_user_schema
|
|
||||||
CONTEXT: while executing command on localhost:57638
|
|
||||||
RESET ROLE;
|
|
||||||
-- now we distribute the table as super user
|
|
||||||
SELECT create_distributed_table('full_access_user_schema.t1', 'id');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- verify the owner of the shards for the distributed tables
|
|
||||||
SELECT result FROM run_command_on_workers($cmd$
|
|
||||||
SELECT tableowner FROM pg_tables WHERE
|
|
||||||
true
|
|
||||||
AND schemaname = 'full_access_user_schema'
|
|
||||||
AND tablename LIKE 't1_%'
|
|
||||||
LIMIT 1;
|
|
||||||
$cmd$);
|
|
||||||
result
|
|
||||||
--------------
|
|
||||||
usage_access
|
|
||||||
usage_access
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- a user with all privileges on a schema should be able to distribute tables
|
|
||||||
SET ROLE full_access;
|
|
||||||
CREATE TABLE full_access_user_schema.t2(id int);
|
|
||||||
SELECT create_distributed_table('full_access_user_schema.t2', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- a user with all privileges on a schema should be able to upgrade a distributed table to
|
|
||||||
-- a reference table
|
|
||||||
SET ROLE full_access;
|
|
||||||
BEGIN;
|
|
||||||
CREATE TABLE full_access_user_schema.r1(id int);
|
|
||||||
SET LOCAL citus.shard_count TO 1;
|
|
||||||
SELECT create_distributed_table('full_access_user_schema.r1', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT upgrade_to_reference_table('full_access_user_schema.r1');
|
|
||||||
upgrade_to_reference_table
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
RESET ROLE;
|
|
||||||
-- the super user should be able to upgrade a distributed table to a reference table, even
|
|
||||||
-- if it is owned by another user
|
|
||||||
SET ROLE full_access;
|
|
||||||
BEGIN;
|
|
||||||
CREATE TABLE full_access_user_schema.r2(id int);
|
|
||||||
SET LOCAL citus.shard_count TO 1;
|
|
||||||
SELECT create_distributed_table('full_access_user_schema.r2', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
RESET ROLE;
|
|
||||||
-- the usage_access should not be able to upgrade the table
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT upgrade_to_reference_table('full_access_user_schema.r2');
|
|
||||||
ERROR: must be owner of relation r2
|
|
||||||
RESET ROLE;
|
|
||||||
-- the super user should be able
|
|
||||||
SELECT upgrade_to_reference_table('full_access_user_schema.r2');
|
|
||||||
upgrade_to_reference_table
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- verify the owner of the shards for the reference table
|
|
||||||
SELECT result FROM run_command_on_workers($cmd$
|
|
||||||
SELECT tableowner FROM pg_tables WHERE
|
|
||||||
true
|
|
||||||
AND schemaname = 'full_access_user_schema'
|
|
||||||
AND tablename LIKE 'r2_%'
|
|
||||||
LIMIT 1;
|
|
||||||
$cmd$);
|
|
||||||
result
|
|
||||||
-------------
|
|
||||||
full_access
|
|
||||||
full_access
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- super user should be the only one being able to call worker_cleanup_job_schema_cache
|
|
||||||
SELECT worker_cleanup_job_schema_cache();
|
|
||||||
worker_cleanup_job_schema_cache
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET ROLE full_access;
|
|
||||||
SELECT worker_cleanup_job_schema_cache();
|
|
||||||
ERROR: permission denied for function worker_cleanup_job_schema_cache
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT worker_cleanup_job_schema_cache();
|
|
||||||
ERROR: permission denied for function worker_cleanup_job_schema_cache
|
|
||||||
SET ROLE read_access;
|
|
||||||
SELECT worker_cleanup_job_schema_cache();
|
|
||||||
ERROR: permission denied for function worker_cleanup_job_schema_cache
|
|
||||||
SET ROLE no_access;
|
|
||||||
SELECT worker_cleanup_job_schema_cache();
|
|
||||||
ERROR: permission denied for function worker_cleanup_job_schema_cache
|
|
||||||
RESET ROLE;
|
|
||||||
-- to test access to files created during repartition we will create some on worker 1
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SET ROLE full_access;
|
|
||||||
SELECT worker_hash_partition_table(42,1,'SELECT a FROM generate_series(1,100) AS a', 'a', 23, ARRAY[-2147483648, -1073741824, 0, 1073741824]::int4[]);
|
|
||||||
worker_hash_partition_table
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- all attempts for transfer are initiated from other workers
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
-- super user should not be able to copy files created by a user
|
|
||||||
SELECT worker_fetch_partition_file(42, 1, 1, 1, 'localhost', :worker_1_port);
|
|
||||||
WARNING: could not open file "base/pgsql_job_cache/job_0042/task_000001/p_00001.10": No such file or directory
|
|
||||||
CONTEXT: while executing command on localhost:57637
|
|
||||||
ERROR: could not receive file "base/pgsql_job_cache/job_0042/task_000001/p_00001" from localhost:57637
|
|
||||||
-- different user should not be able to fetch partition file
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT worker_fetch_partition_file(42, 1, 1, 1, 'localhost', :worker_1_port);
|
|
||||||
WARNING: could not open file "base/pgsql_job_cache/job_0042/task_000001/p_00001.18007": No such file or directory
|
|
||||||
CONTEXT: while executing command on localhost:57637
|
|
||||||
ERROR: could not receive file "base/pgsql_job_cache/job_0042/task_000001/p_00001" from localhost:57637
|
|
||||||
-- only the user whom created the files should be able to fetch
|
|
||||||
SET ROLE full_access;
|
|
||||||
SELECT worker_fetch_partition_file(42, 1, 1, 1, 'localhost', :worker_1_port);
|
|
||||||
worker_fetch_partition_file
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- now we will test that only the user who owns the fetched file is able to merge it into
|
|
||||||
-- a table
|
|
||||||
-- test that no other user can merge the downloaded file before the task is being tracked
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT worker_merge_files_into_table(42, 1, ARRAY['a'], ARRAY['integer']);
|
|
||||||
ERROR: job schema does not exist
|
|
||||||
DETAIL: must be superuser to use public schema
|
|
||||||
RESET ROLE;
|
|
||||||
SET ROLE full_access;
|
|
||||||
-- use the side effect of this function to have a schema to use, otherwise only the super
|
|
||||||
-- user could call worker_merge_files_into_table and store the results in public, which is
|
|
||||||
-- not what we want
|
|
||||||
SELECT task_tracker_assign_task(42, 1, 'SELECT 1');
|
|
||||||
task_tracker_assign_task
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
RESET ROLE;
|
|
||||||
-- test that no other user can merge the downloaded file after the task is being tracked
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT worker_merge_files_into_table(42, 1, ARRAY['a'], ARRAY['integer']);
|
|
||||||
ERROR: must be owner of schema pg_merge_job_0042
|
|
||||||
RESET ROLE;
|
|
||||||
-- test that the super user is unable to read the contents of the intermediate file,
|
|
||||||
-- although it does create the table
|
|
||||||
SELECT worker_merge_files_into_table(42, 1, ARRAY['a'], ARRAY['integer']);
|
|
||||||
WARNING: Task file "task_000001.18003" does not have expected suffix ".10"
|
|
||||||
worker_merge_files_into_table
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE pg_merge_job_0042.task_000001; -- drop table so we can reuse the same files for more tests
|
|
||||||
SET ROLE full_access;
|
|
||||||
SELECT worker_merge_files_into_table(42, 1, ARRAY['a'], ARRAY['integer']);
|
|
||||||
worker_merge_files_into_table
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
25
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE pg_merge_job_0042.task_000001; -- drop table so we can reuse the same files for more tests
|
|
||||||
RESET ROLE;
|
|
||||||
-- test that no other user can merge files and run query on the already fetched files
|
|
||||||
SET ROLE usage_access;
|
|
||||||
SELECT worker_merge_files_and_run_query(42, 1,
|
|
||||||
'CREATE TABLE task_000001_merge(merge_column_0 int)',
|
|
||||||
'CREATE TABLE task_000001 (a) AS SELECT sum(merge_column_0) FROM task_000001_merge'
|
|
||||||
);
|
|
||||||
ERROR: must be owner of schema pg_merge_job_0042
|
|
||||||
RESET ROLE;
|
|
||||||
-- test that the super user is unable to read the contents of the partitioned files after
|
|
||||||
-- trying to merge with run query
|
|
||||||
SELECT worker_merge_files_and_run_query(42, 1,
|
|
||||||
'CREATE TABLE task_000001_merge(merge_column_0 int)',
|
|
||||||
'CREATE TABLE task_000001 (a) AS SELECT sum(merge_column_0) FROM task_000001_merge'
|
|
||||||
);
|
|
||||||
WARNING: Task file "task_000001.18003" does not have expected suffix ".10"
|
|
||||||
worker_merge_files_and_run_query
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001_merge;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE pg_merge_job_0042.task_000001, pg_merge_job_0042.task_000001_merge; -- drop table so we can reuse the same files for more tests
|
|
||||||
-- test that the owner of the task can merge files and run query correctly
|
|
||||||
SET ROLE full_access;
|
|
||||||
SELECT worker_merge_files_and_run_query(42, 1,
|
|
||||||
'CREATE TABLE task_000001_merge(merge_column_0 int)',
|
|
||||||
'CREATE TABLE task_000001 (a) AS SELECT sum(merge_column_0) FROM task_000001_merge'
|
|
||||||
);
|
|
||||||
worker_merge_files_and_run_query
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test that owner of task cannot execute arbitrary sql
|
|
||||||
SELECT worker_merge_files_and_run_query(42, 1,
|
|
||||||
'CREATE TABLE task_000002_merge(merge_column_0 int)',
|
|
||||||
'DROP USER usage_access'
|
|
||||||
);
|
|
||||||
ERROR: permission denied to drop role
|
|
||||||
CONTEXT: SQL statement "DROP USER usage_access"
|
|
||||||
SELECT worker_merge_files_and_run_query(42, 1,
|
|
||||||
'DROP USER usage_access',
|
|
||||||
'CREATE TABLE task_000002 (a) AS SELECT sum(merge_column_0) FROM task_000002_merge'
|
|
||||||
);
|
|
||||||
ERROR: permission denied to drop role
|
|
||||||
CONTEXT: SQL statement "DROP USER usage_access"
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001_merge;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
25
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM pg_merge_job_0042.task_000001;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE pg_merge_job_0042.task_000001, pg_merge_job_0042.task_000001_merge; -- drop table so we can reuse the same files for more tests
|
|
||||||
RESET ROLE;
|
|
||||||
\c - - - :master_port
|
|
||||||
DROP SCHEMA full_access_user_schema CASCADE;
|
|
||||||
NOTICE: drop cascades to 4 other objects
|
|
||||||
DETAIL: drop cascades to table full_access_user_schema.t1
|
|
||||||
drop cascades to table full_access_user_schema.t2
|
|
||||||
drop cascades to table full_access_user_schema.r1
|
|
||||||
drop cascades to table full_access_user_schema.r2
|
|
||||||
DROP TABLE
|
|
||||||
my_table,
|
|
||||||
my_table_with_data,
|
|
||||||
my_role_table_with_data,
|
|
||||||
singleshard,
|
|
||||||
test,
|
|
||||||
test_coloc;
|
|
||||||
DROP USER full_access;
|
|
||||||
DROP USER read_access;
|
|
||||||
DROP USER no_access;
|
|
||||||
DROP ROLE some_role;
|
|
||||||
|
|
@ -1,372 +0,0 @@
|
||||||
-- 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;
|
|
||||||
set citus.replication_model to 'statement';
|
|
||||||
-- 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;
|
|
||||||
set citus.replication_model to 'streaming';
|
|
||||||
--
|
|
||||||
-- 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');
|
|
||||||
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;$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE mx_call_proc(x int, INOUT y int)
|
|
||||||
^
|
|
||||||
CREATE PROCEDURE mx_call_proc_bigint(x bigint, INOUT y bigint)
|
|
||||||
LANGUAGE plpgsql AS $$
|
|
||||||
BEGIN
|
|
||||||
y := x + y * 2;
|
|
||||||
END;$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE mx_call_proc_bigint(x bigint, INOUT y bigin...
|
|
||||||
^
|
|
||||||
-- 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;$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE mx_call_proc_custom_types(INOUT x mx_call_e...
|
|
||||||
^
|
|
||||||
-- Test that undistributed procedures have no issue executing
|
|
||||||
call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
-- Same for unqualified names
|
|
||||||
call mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
call mx_call_proc_custom_types('S', 'A');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
-- Mark both procedures as distributed ...
|
|
||||||
select create_distributed_function('mx_call_proc(int,int)');
|
|
||||||
ERROR: function "mx_call_proc(int,int)" does not exist
|
|
||||||
LINE 1: select create_distributed_function('mx_call_proc(int,int)');
|
|
||||||
^
|
|
||||||
select create_distributed_function('mx_call_proc_bigint(bigint,bigint)');
|
|
||||||
ERROR: function "mx_call_proc_bigint(bigint,bigint)" does not exist
|
|
||||||
LINE 1: select create_distributed_function('mx_call_proc_bigint(bigi...
|
|
||||||
^
|
|
||||||
select create_distributed_function('mx_call_proc_custom_types(mx_call_enum,mx_call_enum)');
|
|
||||||
ERROR: function "mx_call_proc_custom_types(mx_call_enum,mx_call_enum)" does not exist
|
|
||||||
LINE 1: select create_distributed_function('mx_call_proc_custom_type...
|
|
||||||
^
|
|
||||||
-- 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);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
call mx_call_proc_bigint(4, 2);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc_bigint(4, 2);
|
|
||||||
^
|
|
||||||
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
-- 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);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
call mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
call mx_call_proc_custom_types('S', 'A');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
-- Test implicit cast of int to bigint
|
|
||||||
call mx_call_proc_bigint(4, 2);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call mx_call_proc_bigint(4, 2);
|
|
||||||
^
|
|
||||||
-- We don't allow distributing calls inside transactions
|
|
||||||
begin;
|
|
||||||
call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
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');
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc_custom_types('S', 'A');
|
|
||||||
^
|
|
||||||
-- 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);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
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);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
-- We don't currently support colocating with reference tables
|
|
||||||
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_ref'::regclass, 1);
|
|
||||||
colocate_proc_with_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
-- 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);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
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;$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE mx_call_proc_tx(x int) LANGUAGE plpgsql AS ...
|
|
||||||
^
|
|
||||||
-- before distribution ...
|
|
||||||
CALL multi_mx_call.mx_call_proc_tx(10);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: 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');
|
|
||||||
ERROR: function "mx_call_proc_tx(int)" does not exist
|
|
||||||
LINE 1: select create_distributed_function('mx_call_proc_tx(int)', '...
|
|
||||||
^
|
|
||||||
CALL multi_mx_call.mx_call_proc_tx(20);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL multi_mx_call.mx_call_proc_tx(20);
|
|
||||||
^
|
|
||||||
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
|
|
||||||
(5 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;$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE mx_call_proc_raise(x int) LANGUAGE plpgsql ...
|
|
||||||
^
|
|
||||||
select create_distributed_function('mx_call_proc_raise(int)', '$1', 'mx_call_dist_table_1');
|
|
||||||
ERROR: function "mx_call_proc_raise(int)" does not exist
|
|
||||||
LINE 1: select create_distributed_function('mx_call_proc_raise(int)'...
|
|
||||||
^
|
|
||||||
\set VERBOSITY terse
|
|
||||||
call multi_mx_call.mx_call_proc_raise(2);
|
|
||||||
ERROR: syntax error at or near "call" at character 1
|
|
||||||
\set VERBOSITY default
|
|
||||||
-- Test that we don't propagate to non-metadata worker nodes
|
|
||||||
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)
|
|
||||||
|
|
||||||
call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, 0);
|
|
||||||
^
|
|
||||||
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));
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(2, mx_call_add(3, 4));
|
|
||||||
^
|
|
||||||
-- non-const parameter can be pushed down
|
|
||||||
call multi_mx_call.mx_call_proc(multi_mx_call.mx_call_add(3, 4), 2);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(multi_mx_call.mx_call_add(3,...
|
|
||||||
^
|
|
||||||
-- volatile parameter cannot be pushed down
|
|
||||||
call multi_mx_call.mx_call_proc(floor(random())::int, 2);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call multi_mx_call.mx_call_proc(floor(random())::int, 2);
|
|
||||||
^
|
|
||||||
reset client_min_messages;
|
|
||||||
\set VERBOSITY terse
|
|
||||||
drop schema multi_mx_call cascade;
|
|
||||||
NOTICE: drop cascades to 6 other objects
|
|
||||||
|
|
@ -1,869 +0,0 @@
|
||||||
--
|
|
||||||
-- MULTI_MX_EXPLAIN
|
|
||||||
--
|
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1320000;
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
\c - - - :master_port
|
|
||||||
\a\t
|
|
||||||
SET citus.task_executor_type TO 'real-time';
|
|
||||||
SET citus.explain_distributed_queries TO on;
|
|
||||||
VACUUM ANALYZE lineitem_mx;
|
|
||||||
VACUUM ANALYZE orders_mx;
|
|
||||||
VACUUM ANALYZE customer_mx;
|
|
||||||
VACUUM ANALYZE supplier_mx;
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
-- Function that parses explain output as JSON
|
|
||||||
CREATE FUNCTION explain_json(query text)
|
|
||||||
RETURNS jsonb
|
|
||||||
AS $BODY$
|
|
||||||
DECLARE
|
|
||||||
result jsonb;
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('EXPLAIN (FORMAT JSON) %s', query) INTO result;
|
|
||||||
RETURN result;
|
|
||||||
END;
|
|
||||||
$BODY$ LANGUAGE plpgsql;
|
|
||||||
-- Function that parses explain output as XML
|
|
||||||
CREATE FUNCTION explain_xml(query text)
|
|
||||||
RETURNS xml
|
|
||||||
AS $BODY$
|
|
||||||
DECLARE
|
|
||||||
result xml;
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('EXPLAIN (FORMAT XML) %s', query) INTO result;
|
|
||||||
RETURN result;
|
|
||||||
END;
|
|
||||||
$BODY$ LANGUAGE plpgsql;
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
-- Function that parses explain output as JSON
|
|
||||||
CREATE FUNCTION explain_json(query text)
|
|
||||||
RETURNS jsonb
|
|
||||||
AS $BODY$
|
|
||||||
DECLARE
|
|
||||||
result jsonb;
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('EXPLAIN (FORMAT JSON) %s', query) INTO result;
|
|
||||||
RETURN result;
|
|
||||||
END;
|
|
||||||
$BODY$ LANGUAGE plpgsql;
|
|
||||||
-- Function that parses explain output as XML
|
|
||||||
CREATE FUNCTION explain_xml(query text)
|
|
||||||
RETURNS xml
|
|
||||||
AS $BODY$
|
|
||||||
DECLARE
|
|
||||||
result xml;
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('EXPLAIN (FORMAT XML) %s', query) INTO result;
|
|
||||||
RETURN result;
|
|
||||||
END;
|
|
||||||
$BODY$ LANGUAGE plpgsql;
|
|
||||||
-- Test Text format
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT TEXT)
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
|
||||||
Sort
|
|
||||||
Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.l_quantity
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: l_quantity
|
|
||||||
-> Seq Scan on lineitem_mx_1220052 lineitem_mx
|
|
||||||
-- Test JSON format
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT JSON)
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"Plan": {
|
|
||||||
"Node Type": "Sort",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Sort Key": ["COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "remote_scan.l_quantity"],
|
|
||||||
"Plans": [
|
|
||||||
{
|
|
||||||
"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 Real-Time",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Distributed Query": {
|
|
||||||
"Job": {
|
|
||||||
"Task Count": 16,
|
|
||||||
"Tasks Shown": "One of 16",
|
|
||||||
"Tasks": [
|
|
||||||
{
|
|
||||||
"Node": "host=localhost port=57637 dbname=regression",
|
|
||||||
"Remote Plan": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"Plan": {
|
|
||||||
"Node Type": "Aggregate",
|
|
||||||
"Strategy": "Hashed",
|
|
||||||
"Partial Mode": "Simple",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Group Key": ["l_quantity"],
|
|
||||||
"Plans": [
|
|
||||||
{
|
|
||||||
"Node Type": "Seq Scan",
|
|
||||||
"Parent Relationship": "Outer",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Relation Name": "lineitem_mx_1220052",
|
|
||||||
"Alias": "lineitem_mx"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
-- Validate JSON format
|
|
||||||
SELECT true AS valid FROM explain_json($$
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity$$);
|
|
||||||
t
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
-- Test XML format
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT XML)
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
|
||||||
<explain xmlns="http://www.postgresql.org/2009/explain">
|
|
||||||
<Query>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Sort</Node-Type>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Sort-Key>
|
|
||||||
<Item>COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)</Item>
|
|
||||||
<Item>remote_scan.l_quantity</Item>
|
|
||||||
</Sort-Key>
|
|
||||||
<Plans>
|
|
||||||
<Plan>
|
|
||||||
<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>
|
|
||||||
</Group-Key>
|
|
||||||
<Plans>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Custom Scan</Node-Type>
|
|
||||||
<Parent-Relationship>Outer</Parent-Relationship>
|
|
||||||
<Custom-Plan-Provider>Citus Real-Time</Custom-Plan-Provider>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Distributed-Query>
|
|
||||||
<Job>
|
|
||||||
<Task-Count>16</Task-Count>
|
|
||||||
<Tasks-Shown>One of 16</Tasks-Shown>
|
|
||||||
<Tasks>
|
|
||||||
<Task>
|
|
||||||
<Node>host=localhost port=57637 dbname=regression</Node>
|
|
||||||
<Remote-Plan>
|
|
||||||
<explain xmlns="http://www.postgresql.org/2009/explain">
|
|
||||||
<Query>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Aggregate</Node-Type>
|
|
||||||
<Strategy>Hashed</Strategy>
|
|
||||||
<Partial-Mode>Simple</Partial-Mode>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Group-Key>
|
|
||||||
<Item>l_quantity</Item>
|
|
||||||
</Group-Key>
|
|
||||||
<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>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Query>
|
|
||||||
</explain>
|
|
||||||
</Remote-Plan>
|
|
||||||
</Task>
|
|
||||||
</Tasks>
|
|
||||||
</Job>
|
|
||||||
</Distributed-Query>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Query>
|
|
||||||
</explain>
|
|
||||||
-- Validate XML format
|
|
||||||
SELECT true AS valid FROM explain_xml($$
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity$$);
|
|
||||||
t
|
|
||||||
-- Test YAML format
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT YAML)
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
|
||||||
- Plan:
|
|
||||||
Node Type: "Sort"
|
|
||||||
Parallel Aware: false
|
|
||||||
Sort Key:
|
|
||||||
- "COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
|
|
||||||
- "remote_scan.l_quantity"
|
|
||||||
Plans:
|
|
||||||
- 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 Real-Time"
|
|
||||||
Parallel Aware: false
|
|
||||||
Distributed Query:
|
|
||||||
Job:
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: "One of 16"
|
|
||||||
Tasks:
|
|
||||||
- Node: "host=localhost port=57637 dbname=regression"
|
|
||||||
Remote Plan:
|
|
||||||
- Plan:
|
|
||||||
Node Type: "Aggregate"
|
|
||||||
Strategy: "Hashed"
|
|
||||||
Partial Mode: "Simple"
|
|
||||||
Parallel Aware: false
|
|
||||||
Group Key:
|
|
||||||
- "l_quantity"
|
|
||||||
Plans:
|
|
||||||
- Node Type: "Seq Scan"
|
|
||||||
Parent Relationship: "Outer"
|
|
||||||
Parallel Aware: false
|
|
||||||
Relation Name: "lineitem_mx_1220052"
|
|
||||||
Alias: "lineitem_mx"
|
|
||||||
|
|
||||||
-- Test Text format
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT TEXT)
|
|
||||||
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
|
|
||||||
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
|
||||||
Sort
|
|
||||||
Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.l_quantity
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: l_quantity
|
|
||||||
-> Seq Scan on lineitem_mx_1220052 lineitem_mx
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
-- Test verbose
|
|
||||||
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
|
|
||||||
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem_mx;
|
|
||||||
Aggregate
|
|
||||||
Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2")))
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2"
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
Output: sum(l_quantity), sum(l_quantity), count(l_quantity)
|
|
||||||
-> Seq Scan on public.lineitem_mx_1220052 lineitem_mx
|
|
||||||
Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment
|
|
||||||
-- Test join
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT * FROM lineitem_mx
|
|
||||||
JOIN orders_mx ON l_orderkey = o_orderkey AND l_quantity < 5.0
|
|
||||||
ORDER BY l_quantity LIMIT 10;
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan.l_quantity
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: lineitem_mx.l_quantity
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (lineitem_mx.l_orderkey = orders_mx.o_orderkey)
|
|
||||||
-> Seq Scan on lineitem_mx_1220052 lineitem_mx
|
|
||||||
Filter: (l_quantity < 5.0)
|
|
||||||
-> Hash
|
|
||||||
-> Seq Scan on orders_mx_1220068 orders_mx
|
|
||||||
-- Test insert
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
INSERT INTO lineitem_mx VALUES(1,0);
|
|
||||||
Custom Scan (Citus Router)
|
|
||||||
Task Count: 1
|
|
||||||
Tasks Shown: All
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Insert on lineitem_mx_1220052
|
|
||||||
-> Result
|
|
||||||
-- Test update
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
UPDATE lineitem_mx
|
|
||||||
SET l_suppkey = 12
|
|
||||||
WHERE l_orderkey = 1 AND l_partkey = 0;
|
|
||||||
Custom Scan (Citus Router)
|
|
||||||
Task Count: 1
|
|
||||||
Tasks Shown: All
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Update on lineitem_mx_1220052 lineitem_mx
|
|
||||||
-> Index Scan using lineitem_mx_pkey_1220052 on lineitem_mx_1220052 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey = 1)
|
|
||||||
Filter: (l_partkey = 0)
|
|
||||||
-- Test delete
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
DELETE FROM lineitem_mx
|
|
||||||
WHERE l_orderkey = 1 AND l_partkey = 0;
|
|
||||||
Custom Scan (Citus Router)
|
|
||||||
Task Count: 1
|
|
||||||
Tasks Shown: All
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Delete on lineitem_mx_1220052 lineitem_mx
|
|
||||||
-> Index Scan using lineitem_mx_pkey_1220052 on lineitem_mx_1220052 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey = 1)
|
|
||||||
Filter: (l_partkey = 0)
|
|
||||||
-- make the outputs more consistent
|
|
||||||
VACUUM ANALYZE lineitem_mx;
|
|
||||||
VACUUM ANALYZE orders_mx;
|
|
||||||
VACUUM ANALYZE customer_mx;
|
|
||||||
VACUUM ANALYZE supplier_mx;
|
|
||||||
-- Test single-shard SELECT
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT l_quantity FROM lineitem_mx WHERE l_orderkey = 5;
|
|
||||||
Custom Scan (Citus Router)
|
|
||||||
Task Count: 1
|
|
||||||
Tasks Shown: All
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Index Scan using lineitem_mx_pkey_1220055 on lineitem_mx_1220055 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey = 5)
|
|
||||||
SELECT true AS valid FROM explain_xml($$
|
|
||||||
SELECT l_quantity FROM lineitem_mx WHERE l_orderkey = 5$$);
|
|
||||||
t
|
|
||||||
SELECT true AS valid FROM explain_json($$
|
|
||||||
SELECT l_quantity FROM lineitem_mx WHERE l_orderkey = 5$$);
|
|
||||||
t
|
|
||||||
-- Test CREATE TABLE ... AS
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
CREATE TABLE explain_result AS
|
|
||||||
SELECT * FROM lineitem_mx;
|
|
||||||
Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Seq Scan on lineitem_mx_1220052 lineitem_mx
|
|
||||||
-- Test all tasks output
|
|
||||||
SET citus.explain_all_tasks TO on;
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT avg(l_linenumber) FROM lineitem_mx WHERE l_orderkey > 9030;
|
|
||||||
Aggregate
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: All
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220052 on lineitem_mx_1220052 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220053 on lineitem_mx_1220053 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220054 on lineitem_mx_1220054 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220055 on lineitem_mx_1220055 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220056 on lineitem_mx_1220056 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220057 on lineitem_mx_1220057 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220058 on lineitem_mx_1220058 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220059 on lineitem_mx_1220059 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220060 on lineitem_mx_1220060 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220061 on lineitem_mx_1220061 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220062 on lineitem_mx_1220062 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220063 on lineitem_mx_1220063 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220064 on lineitem_mx_1220064 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Seq Scan on lineitem_mx_1220065 lineitem_mx
|
|
||||||
Filter: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220066 on lineitem_mx_1220066 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57638 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220067 on lineitem_mx_1220067 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
SELECT true AS valid FROM explain_xml($$
|
|
||||||
SELECT avg(l_linenumber) FROM lineitem_mx WHERE l_orderkey > 9030$$);
|
|
||||||
t
|
|
||||||
SELECT true AS valid FROM explain_json($$
|
|
||||||
SELECT avg(l_linenumber) FROM lineitem_mx WHERE l_orderkey > 9030$$);
|
|
||||||
t
|
|
||||||
-- Test track tracker
|
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
|
||||||
SET citus.explain_all_tasks TO off;
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT avg(l_linenumber) FROM lineitem_mx WHERE l_orderkey > 9030;
|
|
||||||
Aggregate
|
|
||||||
-> Custom Scan (Citus Task-Tracker)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Index Only Scan using lineitem_mx_pkey_1220052 on lineitem_mx_1220052 lineitem_mx
|
|
||||||
Index Cond: (l_orderkey > 9030)
|
|
||||||
-- Test re-partition join
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey;
|
|
||||||
Aggregate
|
|
||||||
-> Custom Scan (Citus Task-Tracker)
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: One of 16
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Aggregate
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (lineitem_mx.l_orderkey = orders_mx.o_orderkey)
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (supplier_mx.s_suppkey = lineitem_mx.l_suppkey)
|
|
||||||
-> Seq Scan on supplier_mx_1220087 supplier_mx
|
|
||||||
-> Hash
|
|
||||||
-> Seq Scan on lineitem_mx_1220052 lineitem_mx
|
|
||||||
-> Hash
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (customer_mx.c_custkey = orders_mx.o_custkey)
|
|
||||||
-> Seq Scan on customer_mx_1220084 customer_mx
|
|
||||||
-> Hash
|
|
||||||
-> Seq Scan on orders_mx_1220068 orders_mx
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT JSON)
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey;
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"Plan": {
|
|
||||||
"Node Type": "Aggregate",
|
|
||||||
"Strategy": "Plain",
|
|
||||||
"Partial Mode": "Simple",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Plans": [
|
|
||||||
{
|
|
||||||
"Node Type": "Custom Scan",
|
|
||||||
"Parent Relationship": "Outer",
|
|
||||||
"Custom Plan Provider": "Citus Task-Tracker",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Distributed Query": {
|
|
||||||
"Job": {
|
|
||||||
"Task Count": 16,
|
|
||||||
"Tasks Shown": "One of 16",
|
|
||||||
"Tasks": [
|
|
||||||
{
|
|
||||||
"Node": "host=localhost port=57637 dbname=regression",
|
|
||||||
"Remote Plan": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"Plan": {
|
|
||||||
"Node Type": "Aggregate",
|
|
||||||
"Strategy": "Plain",
|
|
||||||
"Partial Mode": "Simple",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Plans": [
|
|
||||||
{
|
|
||||||
"Node Type": "Hash Join",
|
|
||||||
"Parent Relationship": "Outer",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Join Type": "Inner",
|
|
||||||
"Hash Cond": "(lineitem_mx.l_orderkey = orders_mx.o_orderkey)",
|
|
||||||
"Plans": [
|
|
||||||
{
|
|
||||||
"Node Type": "Hash Join",
|
|
||||||
"Parent Relationship": "Outer",
|
|
||||||
"Parallel Aware": false,
|
|
||||||
"Join Type": "Inner",
|
|
||||||
"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",
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
SELECT true AS valid FROM explain_json($$
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey$$);
|
|
||||||
t
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT XML)
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey;
|
|
||||||
<explain xmlns="http://www.postgresql.org/2009/explain">
|
|
||||||
<Query>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Aggregate</Node-Type>
|
|
||||||
<Strategy>Plain</Strategy>
|
|
||||||
<Partial-Mode>Simple</Partial-Mode>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Plans>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Custom Scan</Node-Type>
|
|
||||||
<Parent-Relationship>Outer</Parent-Relationship>
|
|
||||||
<Custom-Plan-Provider>Citus Task-Tracker</Custom-Plan-Provider>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Distributed-Query>
|
|
||||||
<Job>
|
|
||||||
<Task-Count>16</Task-Count>
|
|
||||||
<Tasks-Shown>One of 16</Tasks-Shown>
|
|
||||||
<Tasks>
|
|
||||||
<Task>
|
|
||||||
<Node>host=localhost port=57637 dbname=regression</Node>
|
|
||||||
<Remote-Plan>
|
|
||||||
<explain xmlns="http://www.postgresql.org/2009/explain">
|
|
||||||
<Query>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Aggregate</Node-Type>
|
|
||||||
<Strategy>Plain</Strategy>
|
|
||||||
<Partial-Mode>Simple</Partial-Mode>
|
|
||||||
<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>
|
|
||||||
<Hash-Cond>(lineitem_mx.l_orderkey = orders_mx.o_orderkey)</Hash-Cond>
|
|
||||||
<Plans>
|
|
||||||
<Plan>
|
|
||||||
<Node-Type>Hash Join</Node-Type>
|
|
||||||
<Parent-Relationship>Outer</Parent-Relationship>
|
|
||||||
<Parallel-Aware>false</Parallel-Aware>
|
|
||||||
<Join-Type>Inner</Join-Type>
|
|
||||||
<Hash-Cond>(supplier_mx.s_suppkey = lineitem_mx.l_suppkey)</Hash-Cond>
|
|
||||||
<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>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</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>
|
|
||||||
<Hash-Cond>(customer_mx.c_custkey = orders_mx.o_custkey)</Hash-Cond>
|
|
||||||
<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>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Query>
|
|
||||||
</explain>
|
|
||||||
</Remote-Plan>
|
|
||||||
</Task>
|
|
||||||
</Tasks>
|
|
||||||
</Job>
|
|
||||||
</Distributed-Query>
|
|
||||||
</Plan>
|
|
||||||
</Plans>
|
|
||||||
</Plan>
|
|
||||||
</Query>
|
|
||||||
</explain>
|
|
||||||
SELECT true AS valid FROM explain_xml($$
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey$$);
|
|
||||||
t
|
|
||||||
EXPLAIN (COSTS FALSE, FORMAT YAML)
|
|
||||||
SELECT count(*)
|
|
||||||
FROM lineitem_mx, orders_mx, customer_mx, supplier_mx
|
|
||||||
WHERE l_orderkey = o_orderkey
|
|
||||||
AND o_custkey = c_custkey
|
|
||||||
AND l_suppkey = s_suppkey;
|
|
||||||
- Plan:
|
|
||||||
Node Type: "Aggregate"
|
|
||||||
Strategy: "Plain"
|
|
||||||
Partial Mode: "Simple"
|
|
||||||
Parallel Aware: false
|
|
||||||
Plans:
|
|
||||||
- Node Type: "Custom Scan"
|
|
||||||
Parent Relationship: "Outer"
|
|
||||||
Custom Plan Provider: "Citus Task-Tracker"
|
|
||||||
Parallel Aware: false
|
|
||||||
Distributed Query:
|
|
||||||
Job:
|
|
||||||
Task Count: 16
|
|
||||||
Tasks Shown: "One of 16"
|
|
||||||
Tasks:
|
|
||||||
- Node: "host=localhost port=57637 dbname=regression"
|
|
||||||
Remote Plan:
|
|
||||||
- Plan:
|
|
||||||
Node Type: "Aggregate"
|
|
||||||
Strategy: "Plain"
|
|
||||||
Partial Mode: "Simple"
|
|
||||||
Parallel Aware: false
|
|
||||||
Plans:
|
|
||||||
- Node Type: "Hash Join"
|
|
||||||
Parent Relationship: "Outer"
|
|
||||||
Parallel Aware: false
|
|
||||||
Join Type: "Inner"
|
|
||||||
Hash Cond: "(lineitem_mx.l_orderkey = orders_mx.o_orderkey)"
|
|
||||||
Plans:
|
|
||||||
- Node Type: "Hash Join"
|
|
||||||
Parent Relationship: "Outer"
|
|
||||||
Parallel Aware: false
|
|
||||||
Join Type: "Inner"
|
|
||||||
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"
|
|
||||||
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"
|
|
||||||
|
|
||||||
|
|
@ -1,270 +0,0 @@
|
||||||
--
|
|
||||||
-- Distributed Partitioned Table MX Tests
|
|
||||||
--
|
|
||||||
SET citus.next_shard_id TO 1700000;
|
|
||||||
SET citus.shard_count TO 4;
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
-- make sure wen can create partitioning tables in MX
|
|
||||||
SET citus.replication_model TO 'streaming';
|
|
||||||
SELECT start_metadata_sync_to_node('localhost', :worker_1_port);
|
|
||||||
start_metadata_sync_to_node
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- 1-) Distributing partitioned table
|
|
||||||
-- create partitioned table
|
|
||||||
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partitioning_test(id int, time date) PARTITION ...
|
|
||||||
^
|
|
||||||
|
|
||||||
-- create its partitions
|
|
||||||
CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partitioning_test_2009 PARTITION OF partitionin...
|
|
||||||
^
|
|
||||||
CREATE TABLE partitioning_test_2010 PARTITION OF partitioning_test FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partitioning_test_2010 PARTITION OF partitionin...
|
|
||||||
^
|
|
||||||
-- load some data and distribute tables
|
|
||||||
INSERT INTO partitioning_test VALUES (1, '2009-06-06');
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: INSERT INTO partitioning_test VALUES (1, '2009-06-06');
|
|
||||||
^
|
|
||||||
INSERT INTO partitioning_test VALUES (2, '2010-07-07');
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: INSERT INTO partitioning_test VALUES (2, '2010-07-07');
|
|
||||||
^
|
|
||||||
INSERT INTO partitioning_test_2009 VALUES (3, '2009-09-09');
|
|
||||||
ERROR: relation "partitioning_test_2009" does not exist
|
|
||||||
LINE 1: INSERT INTO partitioning_test_2009 VALUES (3, '2009-09-09');
|
|
||||||
^
|
|
||||||
INSERT INTO partitioning_test_2010 VALUES (4, '2010-03-03');
|
|
||||||
ERROR: relation "partitioning_test_2010" does not exist
|
|
||||||
LINE 1: INSERT INTO partitioning_test_2010 VALUES (4, '2010-03-03');
|
|
||||||
^
|
|
||||||
-- distribute partitioned table
|
|
||||||
SELECT create_distributed_table('partitioning_test', 'id');
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: SELECT create_distributed_table('partitioning_test', 'id');
|
|
||||||
^
|
|
||||||
-- see from MX node, the data is loaded to shards
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioned table and its partitions are distributed
|
|
||||||
SELECT
|
|
||||||
logicalrelid
|
|
||||||
FROM
|
|
||||||
pg_dist_partition
|
|
||||||
WHERE
|
|
||||||
logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010')
|
|
||||||
ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 6: logicalrelid IN ('partitioning_test', 'partitioning_test_20...
|
|
||||||
^
|
|
||||||
SELECT
|
|
||||||
logicalrelid, count(*)
|
|
||||||
FROM pg_dist_shard
|
|
||||||
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010')
|
|
||||||
GROUP BY
|
|
||||||
logicalrelid
|
|
||||||
ORDER BY
|
|
||||||
1,2;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 4: WHERE logicalrelid IN ('partitioning_test', 'partitioning_t...
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioning hierarchy is built
|
|
||||||
SELECT inhrelid::regclass FROM pg_inherits WHERE inhparent = 'partitioning_test'::regclass ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: ...elid::regclass FROM pg_inherits WHERE inhparent = 'partition...
|
|
||||||
^
|
|
||||||
\c - - - :master_port
|
|
||||||
SET citus.replication_model TO 'streaming';
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
-- 2-) Creating partition of a distributed table
|
|
||||||
CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partitioning_test_2011 PARTITION OF partitionin...
|
|
||||||
^
|
|
||||||
-- see from MX node, new partition is automatically distributed as well
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT
|
|
||||||
logicalrelid
|
|
||||||
FROM
|
|
||||||
pg_dist_partition
|
|
||||||
WHERE
|
|
||||||
logicalrelid IN ('partitioning_test', 'partitioning_test_2011')
|
|
||||||
ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 6: logicalrelid IN ('partitioning_test', 'partitioning_test_20...
|
|
||||||
^
|
|
||||||
SELECT
|
|
||||||
logicalrelid, count(*)
|
|
||||||
FROM pg_dist_shard
|
|
||||||
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2011')
|
|
||||||
GROUP BY
|
|
||||||
logicalrelid
|
|
||||||
ORDER BY
|
|
||||||
1,2;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 4: WHERE logicalrelid IN ('partitioning_test', 'partitioning_t...
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioning hierarchy is built
|
|
||||||
SELECT inhrelid::regclass FROM pg_inherits WHERE inhparent = 'partitioning_test'::regclass ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: ...elid::regclass FROM pg_inherits WHERE inhparent = 'partition...
|
|
||||||
^
|
|
||||||
\c - - - :master_port
|
|
||||||
SET citus.replication_model TO 'streaming';
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
-- 3-) Attaching non distributed table to a distributed table
|
|
||||||
CREATE TABLE partitioning_test_2012(id int, time date);
|
|
||||||
-- load some data
|
|
||||||
INSERT INTO partitioning_test_2012 VALUES (5, '2012-06-06');
|
|
||||||
INSERT INTO partitioning_test_2012 VALUES (6, '2012-07-07');
|
|
||||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2012 FOR VALUES FROM ('2012-01-01') TO ('2013-01-01');
|
|
||||||
ERROR: syntax error at or near "ATTACH"
|
|
||||||
LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_...
|
|
||||||
^
|
|
||||||
-- see from MX node, attached partition is distributed as well
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT
|
|
||||||
logicalrelid
|
|
||||||
FROM
|
|
||||||
pg_dist_partition
|
|
||||||
WHERE
|
|
||||||
logicalrelid IN ('partitioning_test', 'partitioning_test_2012')
|
|
||||||
ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 6: logicalrelid IN ('partitioning_test', 'partitioning_test_20...
|
|
||||||
^
|
|
||||||
SELECT
|
|
||||||
logicalrelid, count(*)
|
|
||||||
FROM pg_dist_shard
|
|
||||||
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2012')
|
|
||||||
GROUP BY
|
|
||||||
logicalrelid
|
|
||||||
ORDER BY
|
|
||||||
1,2;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 4: WHERE logicalrelid IN ('partitioning_test', 'partitioning_t...
|
|
||||||
^
|
|
||||||
-- see from MX node, see the data is loaded to shards
|
|
||||||
SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioning hierarchy is built
|
|
||||||
SELECT inhrelid::regclass FROM pg_inherits WHERE inhparent = 'partitioning_test'::regclass ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: ...elid::regclass FROM pg_inherits WHERE inhparent = 'partition...
|
|
||||||
^
|
|
||||||
\c - - - :master_port
|
|
||||||
SET citus.replication_model TO 'streaming';
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
-- 4-) Attaching distributed table to distributed table
|
|
||||||
CREATE TABLE partitioning_test_2013(id int, time date);
|
|
||||||
SELECT create_distributed_table('partitioning_test_2013', 'id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- load some data
|
|
||||||
INSERT INTO partitioning_test_2013 VALUES (7, '2013-06-06');
|
|
||||||
INSERT INTO partitioning_test_2013 VALUES (8, '2013-07-07');
|
|
||||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2013 FOR VALUES FROM ('2013-01-01') TO ('2014-01-01');
|
|
||||||
ERROR: syntax error at or near "ATTACH"
|
|
||||||
LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_...
|
|
||||||
^
|
|
||||||
-- see from MX node, see the data is loaded to shards
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: SELECT * FROM partitioning_test ORDER BY 1;
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioning hierarchy is built
|
|
||||||
SELECT inhrelid::regclass FROM pg_inherits WHERE inhparent = 'partitioning_test'::regclass ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: ...elid::regclass FROM pg_inherits WHERE inhparent = 'partition...
|
|
||||||
^
|
|
||||||
\c - - - :master_port
|
|
||||||
-- 5-) Detaching partition of the partitioned table
|
|
||||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
|
|
||||||
ERROR: syntax error at or near "DETACH"
|
|
||||||
LINE 1: ALTER TABLE partitioning_test DETACH PARTITION partitioning_...
|
|
||||||
^
|
|
||||||
-- see from MX node, partitioning hierarchy is built
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT inhrelid::regclass FROM pg_inherits WHERE inhparent = 'partitioning_test'::regclass ORDER BY 1;
|
|
||||||
ERROR: relation "partitioning_test" does not exist
|
|
||||||
LINE 1: ...elid::regclass FROM pg_inherits WHERE inhparent = 'partition...
|
|
||||||
^
|
|
||||||
-- make sure DROPping from worker node is not allowed
|
|
||||||
DROP TABLE partitioning_test;
|
|
||||||
ERROR: table "partitioning_test" does not exist
|
|
||||||
\c - - - :master_port
|
|
||||||
-- make sure we can repeatedly call start_metadata_sync_to_node
|
|
||||||
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_1_port);
|
|
||||||
start_metadata_sync_to_node
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT start_metadata_sync_to_node('localhost', :worker_1_port);
|
|
||||||
start_metadata_sync_to_node
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- make sure we can drop partitions
|
|
||||||
DROP TABLE partitioning_test_2009;
|
|
||||||
ERROR: table "partitioning_test_2009" does not exist
|
|
||||||
DROP TABLE partitioning_test_2010;
|
|
||||||
ERROR: table "partitioning_test_2010" does not exist
|
|
||||||
-- make sure we can drop partitioned table
|
|
||||||
DROP TABLE partitioning_test;
|
|
||||||
ERROR: table "partitioning_test" does not exist
|
|
||||||
DROP TABLE IF EXISTS partitioning_test_2013;
|
|
||||||
-- test schema drop with partitioned tables
|
|
||||||
SET citus.replication_model TO 'streaming';
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
CREATE SCHEMA partition_test;
|
|
||||||
SET SEARCH_PATH TO partition_test;
|
|
||||||
CREATE TABLE partition_parent_table(a int, b int, c int) PARTITION BY RANGE (b);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: ...TABLE partition_parent_table(a int, b int, c int) PARTITION ...
|
|
||||||
^
|
|
||||||
SELECT create_distributed_table('partition_parent_table', 'a');
|
|
||||||
ERROR: relation "partition_parent_table" does not exist
|
|
||||||
LINE 1: SELECT create_distributed_table('partition_parent_table', 'a...
|
|
||||||
^
|
|
||||||
CREATE TABLE partition_0 PARTITION OF partition_parent_table FOR VALUES FROM (1) TO (10);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partition_0 PARTITION OF partition_parent_table...
|
|
||||||
^
|
|
||||||
CREATE TABLE partition_1 PARTITION OF partition_parent_table FOR VALUES FROM (10) TO (20);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partition_1 PARTITION OF partition_parent_table...
|
|
||||||
^
|
|
||||||
CREATE TABLE partition_2 PARTITION OF partition_parent_table FOR VALUES FROM (20) TO (30);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partition_2 PARTITION OF partition_parent_table...
|
|
||||||
^
|
|
||||||
CREATE TABLE partition_3 PARTITION OF partition_parent_table FOR VALUES FROM (30) TO (40);
|
|
||||||
ERROR: syntax error at or near "PARTITION"
|
|
||||||
LINE 1: CREATE TABLE partition_3 PARTITION OF partition_parent_table...
|
|
||||||
^
|
|
||||||
DROP SCHEMA partition_test CASCADE;
|
|
||||||
RESET SEARCH_PATH;
|
|
||||||
|
|
@ -4,13 +4,6 @@
|
||||||
SET citus.next_shard_id TO 1660000;
|
SET citus.next_shard_id TO 1660000;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
server_version_above_ten
|
|
||||||
--------------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Distributed Partitioned Table Creation Tests
|
-- Distributed Partitioned Table Creation Tests
|
||||||
--
|
--
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,13 +4,6 @@
|
||||||
SET citus.next_shard_id TO 1660000;
|
SET citus.next_shard_id TO 1660000;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
server_version_above_ten
|
|
||||||
--------------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Distributed Partitioned Table Creation Tests
|
-- Distributed Partitioned Table Creation Tests
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
-- This test has different output per major version
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- create test functions
|
-- create test functions
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
|
|
|
||||||
|
|
@ -1,431 +0,0 @@
|
||||||
-- This test has different output per major version
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ===================================================================
|
|
||||||
-- create test functions
|
|
||||||
-- ===================================================================
|
|
||||||
CREATE FUNCTION generate_alter_table_detach_partition_command(regclass)
|
|
||||||
RETURNS text
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE FUNCTION generate_alter_table_attach_partition_command(regclass)
|
|
||||||
RETURNS text
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE FUNCTION generate_partition_information(regclass)
|
|
||||||
RETURNS text
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE FUNCTION print_partitions(regclass)
|
|
||||||
RETURNS text
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE FUNCTION table_inherits(regclass)
|
|
||||||
RETURNS bool
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE FUNCTION table_inherited(regclass)
|
|
||||||
RETURNS bool
|
|
||||||
AS 'citus'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
CREATE OR REPLACE FUNCTION detach_and_attach_partition(partition_name regclass, parent_table_name regclass)
|
|
||||||
RETURNS void LANGUAGE plpgsql VOLATILE
|
|
||||||
AS $function$
|
|
||||||
DECLARE
|
|
||||||
detach_partition_command text := '';
|
|
||||||
attach_partition_command text := '';
|
|
||||||
command_result text := '';
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
-- first generate the command
|
|
||||||
SELECT public.generate_alter_table_attach_partition_command(partition_name) INTO attach_partition_command;
|
|
||||||
|
|
||||||
-- now genereate the detach command
|
|
||||||
SELECT public.generate_alter_table_detach_partition_command(partition_name) INTO detach_partition_command;
|
|
||||||
|
|
||||||
-- later detach the same partition
|
|
||||||
EXECUTE detach_partition_command;
|
|
||||||
|
|
||||||
-- not attach it again
|
|
||||||
EXECUTE attach_partition_command;
|
|
||||||
END;
|
|
||||||
$function$;
|
|
||||||
CREATE OR REPLACE FUNCTION drop_and_recreate_partitioned_table(parent_table_name regclass)
|
|
||||||
RETURNS void LANGUAGE plpgsql VOLATILE
|
|
||||||
AS $function$
|
|
||||||
DECLARE
|
|
||||||
command text := '';
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
-- first generate the command
|
|
||||||
CREATE TABLE partitioned_table_create_commands AS SELECT master_get_table_ddl_events(parent_table_name::text);
|
|
||||||
|
|
||||||
-- later detach the same partition
|
|
||||||
EXECUTE 'DROP TABLE ' || parent_table_name::text || ';';
|
|
||||||
|
|
||||||
FOR command IN SELECT * FROM partitioned_table_create_commands
|
|
||||||
LOOP
|
|
||||||
-- can do some processing here
|
|
||||||
EXECUTE command;
|
|
||||||
END LOOP;
|
|
||||||
|
|
||||||
DROP TABLE partitioned_table_create_commands;
|
|
||||||
|
|
||||||
END;
|
|
||||||
$function$;
|
|
||||||
-- create a partitioned table
|
|
||||||
CREATE TABLE date_partitioned_table(id int, time date) PARTITION BY RANGE (time);
|
|
||||||
-- we should be able to get the partitioning information even if there are no partitions
|
|
||||||
SELECT generate_partition_information('date_partitioned_table');
|
|
||||||
generate_partition_information
|
|
||||||
--------------------------------
|
|
||||||
RANGE ("time")
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- we should be able to drop and re-create the partitioned table using the command that Citus generate
|
|
||||||
SELECT drop_and_recreate_partitioned_table('date_partitioned_table');
|
|
||||||
drop_and_recreate_partitioned_table
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- we should also be able to see the PARTITION BY ... for the parent table
|
|
||||||
SELECT master_get_table_ddl_events('date_partitioned_table');
|
|
||||||
master_get_table_ddl_events
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
CREATE TABLE public.date_partitioned_table (id integer, "time" date) PARTITION BY RANGE ("time")
|
|
||||||
ALTER TABLE public.date_partitioned_table OWNER TO postgres
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- now create the partitions
|
|
||||||
CREATE TABLE date_partition_2006 PARTITION OF date_partitioned_table FOR VALUES FROM ('2006-01-01') TO ('2007-01-01');
|
|
||||||
CREATE TABLE date_partition_2007 PARTITION OF date_partitioned_table FOR VALUES FROM ('2007-01-01') TO ('2008-01-01');
|
|
||||||
-- we should be able to get the partitioning information after the partitions are created
|
|
||||||
SELECT generate_partition_information('date_partitioned_table');
|
|
||||||
generate_partition_information
|
|
||||||
--------------------------------
|
|
||||||
RANGE ("time")
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- lets get the attach partition commands
|
|
||||||
SELECT generate_alter_table_attach_partition_command('date_partition_2006');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE public.date_partitioned_table ATTACH PARTITION public.date_partition_2006 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT generate_alter_table_attach_partition_command('date_partition_2007');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE public.date_partitioned_table ATTACH PARTITION public.date_partition_2007 FOR VALUES FROM ('01-01-2007') TO ('01-01-2008');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- detach and attach the partition by the command generated by us
|
|
||||||
\d+ date_partitioned_table
|
|
||||||
Table "public.date_partitioned_table"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | | | plain | |
|
|
||||||
time | date | | | | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
Partitions: date_partition_2006 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007'),
|
|
||||||
date_partition_2007 FOR VALUES FROM ('01-01-2007') TO ('01-01-2008')
|
|
||||||
|
|
||||||
SELECT detach_and_attach_partition('date_partition_2007', 'date_partitioned_table');
|
|
||||||
detach_and_attach_partition
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- check that both partitions are visiable
|
|
||||||
\d+ date_partitioned_table
|
|
||||||
Table "public.date_partitioned_table"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | | | plain | |
|
|
||||||
time | date | | | | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
Partitions: date_partition_2006 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007'),
|
|
||||||
date_partition_2007 FOR VALUES FROM ('01-01-2007') TO ('01-01-2008')
|
|
||||||
|
|
||||||
-- make sure that inter shard commands work as expected
|
|
||||||
-- assume that the shardId is 100
|
|
||||||
CREATE TABLE date_partitioned_table_100 (id int, time date) PARTITION BY RANGE (time);
|
|
||||||
CREATE TABLE date_partition_2007_100 (id int, time date );
|
|
||||||
-- now create the partitioning hierarcy
|
|
||||||
SELECT worker_apply_inter_shard_ddl_command(referencing_shard:=100, referencing_schema_name:='public',
|
|
||||||
referenced_shard:=100, referenced_schema_name:='public',
|
|
||||||
command:='ALTER TABLE date_partitioned_table ATTACH PARTITION date_partition_2007 FOR VALUES FROM (''2007-01-01'') TO (''2008-01-02'')' );
|
|
||||||
worker_apply_inter_shard_ddl_command
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- the hierarcy is successfully created
|
|
||||||
\d+ date_partitioned_table_100
|
|
||||||
Table "public.date_partitioned_table_100"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | | | plain | |
|
|
||||||
time | date | | | | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
Partitions: date_partition_2007_100 FOR VALUES FROM ('01-01-2007') TO ('01-02-2008')
|
|
||||||
|
|
||||||
-- Citus can also get the DDL events for the partitions as regular tables
|
|
||||||
SELECT master_get_table_ddl_events('date_partition_2007_100');
|
|
||||||
master_get_table_ddl_events
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
CREATE TABLE public.date_partition_2007_100 (id integer, "time" date)
|
|
||||||
ALTER TABLE public.date_partition_2007_100 OWNER TO postgres
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- now break the partitioning hierarcy
|
|
||||||
SELECT worker_apply_inter_shard_ddl_command(referencing_shard:=100, referencing_schema_name:='public',
|
|
||||||
referenced_shard:=100, referenced_schema_name:='public',
|
|
||||||
command:='ALTER TABLE date_partitioned_table DETACH PARTITION date_partition_2007' );
|
|
||||||
worker_apply_inter_shard_ddl_command
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- the hierarcy is successfully broken
|
|
||||||
\d+ date_partitioned_table_100
|
|
||||||
Table "public.date_partitioned_table_100"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | | | plain | |
|
|
||||||
time | date | | | | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
|
|
||||||
-- now lets have some more complex partitioning hierarcies with
|
|
||||||
-- tables on different schemas and constraints on the tables
|
|
||||||
CREATE SCHEMA partition_parent_schema;
|
|
||||||
CREATE TABLE partition_parent_schema.parent_table (id int NOT NULL, time date DEFAULT now()) PARTITION BY RANGE (time);
|
|
||||||
CREATE SCHEMA partition_child_1_schema;
|
|
||||||
CREATE TABLE partition_child_1_schema.child_1 (id int NOT NULL, time date );
|
|
||||||
CREATE SCHEMA partition_child_2_schema;
|
|
||||||
CREATE TABLE partition_child_2_schema.child_2 (id int NOT NULL, time date );
|
|
||||||
-- we should be able to get the partitioning information even if there are no partitions
|
|
||||||
SELECT generate_partition_information('partition_parent_schema.parent_table');
|
|
||||||
generate_partition_information
|
|
||||||
--------------------------------
|
|
||||||
RANGE ("time")
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- we should be able to drop and re-create the partitioned table using the command that Citus generate
|
|
||||||
SELECT drop_and_recreate_partitioned_table('partition_parent_schema.parent_table');
|
|
||||||
drop_and_recreate_partitioned_table
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ALTER TABLE partition_parent_schema.parent_table ATTACH PARTITION partition_child_1_schema.child_1 FOR VALUES FROM ('2009-01-01') TO ('2010-01-02');
|
|
||||||
SET search_path = 'partition_parent_schema';
|
|
||||||
ALTER TABLE parent_table ATTACH PARTITION partition_child_2_schema.child_2 FOR VALUES FROM ('2006-01-01') TO ('2007-01-01');
|
|
||||||
SELECT public.generate_partition_information('parent_table');
|
|
||||||
generate_partition_information
|
|
||||||
--------------------------------
|
|
||||||
RANGE ("time")
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- lets get the attach partition commands
|
|
||||||
SELECT public.generate_alter_table_attach_partition_command('partition_child_1_schema.child_1');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE partition_parent_schema.parent_table ATTACH PARTITION partition_child_1_schema.child_1 FOR VALUES FROM ('01-01-2009') TO ('01-02-2010');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET search_path = 'partition_child_2_schema';
|
|
||||||
SELECT public.generate_alter_table_attach_partition_command('child_2');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE partition_parent_schema.parent_table ATTACH PARTITION partition_child_2_schema.child_2 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET search_path = 'partition_parent_schema';
|
|
||||||
-- detach and attach the partition by the command generated by us
|
|
||||||
\d+ parent_table
|
|
||||||
Table "partition_parent_schema.parent_table"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | not null | | plain | |
|
|
||||||
time | date | | | now() | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
Partitions: partition_child_1_schema.child_1 FOR VALUES FROM ('01-01-2009') TO ('01-02-2010'),
|
|
||||||
partition_child_2_schema.child_2 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007')
|
|
||||||
|
|
||||||
SELECT public.detach_and_attach_partition('partition_child_1_schema.child_1', 'parent_table');
|
|
||||||
detach_and_attach_partition
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- check that both partitions are visiable
|
|
||||||
\d+ parent_table
|
|
||||||
Table "partition_parent_schema.parent_table"
|
|
||||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
|
||||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
|
||||||
id | integer | | not null | | plain | |
|
|
||||||
time | date | | | now() | plain | |
|
|
||||||
Partition key: RANGE ("time")
|
|
||||||
Partitions: partition_child_1_schema.child_1 FOR VALUES FROM ('01-01-2009') TO ('01-02-2010'),
|
|
||||||
partition_child_2_schema.child_2 FOR VALUES FROM ('01-01-2006') TO ('01-01-2007')
|
|
||||||
|
|
||||||
-- some very simple checks that should error out
|
|
||||||
SELECT public.generate_alter_table_attach_partition_command('parent_table');
|
|
||||||
ERROR: "parent_table" is not a partition
|
|
||||||
SELECT public.generate_partition_information('partition_child_1_schema.child_1');
|
|
||||||
ERROR: "child_1" is not a parent table
|
|
||||||
SELECT public.print_partitions('partition_child_1_schema.child_1');
|
|
||||||
ERROR: "child_1" is not a parent table
|
|
||||||
-- now pring the partitions
|
|
||||||
SELECT public.print_partitions('parent_table');
|
|
||||||
print_partitions
|
|
||||||
------------------
|
|
||||||
child_1,child_2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET search_path = 'public';
|
|
||||||
-- test multi column / expression partitioning with UNBOUNDED ranges
|
|
||||||
CREATE OR REPLACE FUNCTION some_function(input_val text)
|
|
||||||
RETURNS text LANGUAGE plpgsql IMMUTABLE
|
|
||||||
AS $function$
|
|
||||||
BEGIN
|
|
||||||
return reverse(input_val);
|
|
||||||
END;
|
|
||||||
$function$;
|
|
||||||
CREATE TABLE multi_column_partitioned (
|
|
||||||
a int,
|
|
||||||
b int,
|
|
||||||
c text
|
|
||||||
) PARTITION BY RANGE (a, (a+b+1), some_function(upper(c)));
|
|
||||||
CREATE TABLE multi_column_partition_1(
|
|
||||||
a int,
|
|
||||||
b int,
|
|
||||||
c text
|
|
||||||
);
|
|
||||||
CREATE TABLE multi_column_partition_2(
|
|
||||||
a int,
|
|
||||||
b int,
|
|
||||||
c text
|
|
||||||
);
|
|
||||||
-- partitioning information
|
|
||||||
SELECT generate_partition_information('multi_column_partitioned');
|
|
||||||
generate_partition_information
|
|
||||||
-----------------------------------------------------
|
|
||||||
RANGE (a, (((a + b) + 1)), some_function(upper(c)))
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_get_table_ddl_events('multi_column_partitioned');
|
|
||||||
master_get_table_ddl_events
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
CREATE TABLE public.multi_column_partitioned (a integer, b integer, c text) PARTITION BY RANGE (a, (((a + b) + 1)), public.some_function(upper(c)))
|
|
||||||
ALTER TABLE public.multi_column_partitioned OWNER TO postgres
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT drop_and_recreate_partitioned_table('multi_column_partitioned');
|
|
||||||
drop_and_recreate_partitioned_table
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- partitions and their ranges
|
|
||||||
ALTER TABLE multi_column_partitioned ATTACH PARTITION multi_column_partition_1 FOR VALUES FROM (1, 10, '250') TO (1, 20, '250');
|
|
||||||
SELECT generate_alter_table_attach_partition_command('multi_column_partition_1');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE public.multi_column_partitioned ATTACH PARTITION public.multi_column_partition_1 FOR VALUES FROM (1, 10, '250') TO (1, 20, '250');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ALTER TABLE multi_column_partitioned ATTACH PARTITION multi_column_partition_2 FOR VALUES FROM (10, 1000, '2500') TO (MAXVALUE, MAXVALUE, MAXVALUE);
|
|
||||||
SELECT generate_alter_table_attach_partition_command('multi_column_partition_2');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE public.multi_column_partitioned ATTACH PARTITION public.multi_column_partition_2 FOR VALUES FROM (10, 1000, '2500') TO (MAXVALUE, MAXVALUE, MAXVALUE);
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT generate_alter_table_detach_partition_command('multi_column_partition_2');
|
|
||||||
generate_alter_table_detach_partition_command
|
|
||||||
---------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE IF EXISTS public.multi_column_partitioned DETACH PARTITION public.multi_column_partition_2;
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- finally a test with LIST partitioning
|
|
||||||
CREATE TABLE list_partitioned (col1 NUMERIC, col2 NUMERIC, col3 VARCHAR(10)) PARTITION BY LIST (col1) ;
|
|
||||||
SELECT generate_partition_information('list_partitioned');
|
|
||||||
generate_partition_information
|
|
||||||
--------------------------------
|
|
||||||
LIST (col1)
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_get_table_ddl_events('list_partitioned');
|
|
||||||
master_get_table_ddl_events
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------
|
|
||||||
CREATE TABLE public.list_partitioned (col1 numeric, col2 numeric, col3 character varying(10)) PARTITION BY LIST (col1)
|
|
||||||
ALTER TABLE public.list_partitioned OWNER TO postgres
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT drop_and_recreate_partitioned_table('list_partitioned');
|
|
||||||
drop_and_recreate_partitioned_table
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE list_partitioned_1 PARTITION OF list_partitioned FOR VALUES IN (100, 101, 102, 103, 104);
|
|
||||||
SELECT generate_alter_table_attach_partition_command('list_partitioned_1');
|
|
||||||
generate_alter_table_attach_partition_command
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE public.list_partitioned ATTACH PARTITION public.list_partitioned_1 FOR VALUES IN ('100', '101', '102', '103', '104');
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- also differentiate partitions and inhereted tables
|
|
||||||
CREATE TABLE cities (
|
|
||||||
name text,
|
|
||||||
population float,
|
|
||||||
altitude int -- in feet
|
|
||||||
);
|
|
||||||
CREATE TABLE capitals (
|
|
||||||
state char(2)
|
|
||||||
) INHERITS (cities);
|
|
||||||
-- returns true since capitals inherits from cities
|
|
||||||
SELECT table_inherits('capitals');
|
|
||||||
table_inherits
|
|
||||||
----------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- although date_partition_2006 inherits from its parent
|
|
||||||
-- returns false since the hierarcy is formed via partitioning
|
|
||||||
SELECT table_inherits('date_partition_2006');
|
|
||||||
table_inherits
|
|
||||||
----------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- returns true since cities inherited by capitals
|
|
||||||
SELECT table_inherited('cities');
|
|
||||||
table_inherited
|
|
||||||
-----------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- although date_partitioned_table inherited by its partitions
|
|
||||||
-- returns false since the hierarcy is formed via partitioning
|
|
||||||
SELECT table_inherited('date_partitioned_table');
|
|
||||||
table_inherited
|
|
||||||
-----------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- also these are not supported
|
|
||||||
SELECT master_get_table_ddl_events('capitals');
|
|
||||||
ERROR: capitals is not a regular, foreign or partitioned table
|
|
||||||
SELECT master_get_table_ddl_events('cities');
|
|
||||||
ERROR: cities is not a regular, foreign or partitioned table
|
|
||||||
-- dropping parents frop the partitions
|
|
||||||
DROP TABLE date_partitioned_table, multi_column_partitioned, list_partitioned, partition_parent_schema.parent_table, cities, capitals;
|
|
||||||
|
|
@ -7,14 +7,6 @@
|
||||||
-- executor here, as we cannot run repartition jobs with real time executor.
|
-- executor here, as we cannot run repartition jobs with real time executor.
|
||||||
SET citus.next_shard_id TO 690000;
|
SET citus.next_shard_id TO 690000;
|
||||||
SET citus.enable_unique_job_ids TO off;
|
SET citus.enable_unique_job_ids TO off;
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
version_above_nine
|
|
||||||
--------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET client_min_messages TO DEBUG4;
|
SET client_min_messages TO DEBUG4;
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
SET citus.task_executor_type TO 'task-tracker';
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,6 @@
|
||||||
-- from a sql task to its depended tasks. Note that we set the executor type to task
|
-- from a sql task to its depended tasks. Note that we set the executor type to task
|
||||||
-- tracker executor here, as we cannot run repartition jobs with real time executor.
|
-- tracker executor here, as we cannot run repartition jobs with real time executor.
|
||||||
SET citus.next_shard_id TO 710000;
|
SET citus.next_shard_id TO 710000;
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
version_above_nine
|
|
||||||
--------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET client_min_messages TO DEBUG3;
|
SET client_min_messages TO DEBUG3;
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
SET citus.task_executor_type TO 'task-tracker';
|
||||||
|
|
|
||||||
|
|
@ -1,922 +0,0 @@
|
||||||
--
|
|
||||||
-- multi shard update delete
|
|
||||||
-- this file is intended to test multi shard update/delete queries
|
|
||||||
--
|
|
||||||
SET citus.next_shard_id TO 1440000;
|
|
||||||
SET citus.shard_replication_factor to 1;
|
|
||||||
SET citus.multi_shard_modify_mode to 'parallel';
|
|
||||||
CREATE TABLE users_test_table(user_id int, value_1 int, value_2 int, value_3 int);
|
|
||||||
SELECT create_distributed_table('users_test_table', 'user_id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\COPY users_test_table FROM STDIN DELIMITER AS ',';
|
|
||||||
CREATE TABLE events_test_table (user_id int, value_1 int, value_2 int, value_3 int);
|
|
||||||
SELECT create_distributed_table('events_test_table', 'user_id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\COPY events_test_table FROM STDIN DELIMITER AS ',';
|
|
||||||
CREATE TABLE events_reference_copy_table (like events_test_table);
|
|
||||||
SELECT create_reference_table('events_reference_copy_table');
|
|
||||||
create_reference_table
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO events_reference_copy_table SELECT * FROM events_test_table;
|
|
||||||
CREATE TABLE users_reference_copy_table (like users_test_table);
|
|
||||||
SELECT create_reference_table('users_reference_copy_table');
|
|
||||||
create_reference_table
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO users_reference_copy_table SELECT * FROM users_test_table;
|
|
||||||
-- Run multi shard updates and deletes without transaction on hash distributed tables
|
|
||||||
UPDATE users_test_table SET value_1 = 1;
|
|
||||||
SELECT COUNT(*), SUM(value_1) FROM users_test_table;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
15 | 15
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_test_table WHERE user_id = 1 or user_id = 3;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 52
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_2 = value_2 + 1 WHERE user_id = 1 or user_id = 3;
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_test_table WHERE user_id = 1 or user_id = 3;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 56
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_3 = 0 WHERE user_id <> 5;
|
|
||||||
SELECT SUM(value_3) FROM users_test_table WHERE user_id <> 5;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
4
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DELETE FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Run multi shard update delete queries within transactions
|
|
||||||
BEGIN;
|
|
||||||
UPDATE users_test_table SET value_3 = 0;
|
|
||||||
END;
|
|
||||||
SELECT SUM(value_3) FROM users_test_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Update can also be rollbacked
|
|
||||||
BEGIN;
|
|
||||||
UPDATE users_test_table SET value_3 = 1;
|
|
||||||
ROLLBACK;
|
|
||||||
SELECT SUM(value_3) FROM users_test_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Run with inserts (we need to set citus.multi_shard_modify_mode to sequential)
|
|
||||||
BEGIN;
|
|
||||||
INSERT INTO users_test_table (user_id, value_3) VALUES(20, 15);
|
|
||||||
INSERT INTO users_test_table (user_id, value_3) VALUES(16,1), (20,16), (7,1), (20,17);
|
|
||||||
SET citus.multi_shard_modify_mode to sequential;
|
|
||||||
UPDATE users_test_table SET value_3 = 1;
|
|
||||||
END;
|
|
||||||
SELECT COUNT()SUM(value_3) FROM users_test_table;
|
|
||||||
ERROR: syntax error at or near "("
|
|
||||||
LINE 1: SELECT COUNT()SUM(value_3) FROM users_test_table;
|
|
||||||
^
|
|
||||||
SET citus.multi_shard_modify_mode to 'sequential';
|
|
||||||
-- Run multiple multi shard updates (with sequential executor)
|
|
||||||
BEGIN;
|
|
||||||
UPDATE users_test_table SET value_3 = 5;
|
|
||||||
UPDATE users_test_table SET value_3 = 0;
|
|
||||||
END;
|
|
||||||
SELECT SUM(value_3) FROM users_copy_table;
|
|
||||||
ERROR: relation "users_copy_table" does not exist
|
|
||||||
LINE 1: SELECT SUM(value_3) FROM users_copy_table;
|
|
||||||
^
|
|
||||||
-- Run multiple multi shard updates (with parallel executor)
|
|
||||||
SET citus.multi_shard_modify_mode to 'parallel';
|
|
||||||
UPDATE users_test_table SET value_3 = 5;
|
|
||||||
BEGIN;
|
|
||||||
UPDATE users_test_table SET value_3 = 2;
|
|
||||||
UPDATE users_test_table SET value_3 = 0;
|
|
||||||
END;
|
|
||||||
SELECT SUM(value_3) FROM users_test_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Check with kind of constraints
|
|
||||||
UPDATE users_test_table SET value_3 = 1 WHERE user_id = 3 or true;
|
|
||||||
SELECT COUNT(*), SUM(value_3) FROM users_test_table;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
16 | 16
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_3 = 0 WHERE user_id = 20 and false;
|
|
||||||
SELECT COUNT(*), SUM(value_3) FROM users_test_table;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
16 | 16
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Run multi shard updates with prepared statements
|
|
||||||
PREPARE foo_plan(int,int) AS UPDATE users_test_table SET value_1 = $1, value_3 = $2;
|
|
||||||
EXECUTE foo_plan(1,5);
|
|
||||||
EXECUTE foo_plan(3,15);
|
|
||||||
EXECUTE foo_plan(5,25);
|
|
||||||
EXECUTE foo_plan(7,35);
|
|
||||||
EXECUTE foo_plan(9,45);
|
|
||||||
EXECUTE foo_plan(0,0);
|
|
||||||
SELECT SUM(value_1), SUM(value_3) FROM users_test_table;
|
|
||||||
sum | sum
|
|
||||||
-----+-----
|
|
||||||
0 | 0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Test on append table (set executor mode to sequential, since with the append
|
|
||||||
-- distributed tables parallel executor may create tons of connections)
|
|
||||||
SET citus.multi_shard_modify_mode to sequential;
|
|
||||||
CREATE TABLE append_stage_table(id int, col_2 int);
|
|
||||||
INSERT INTO append_stage_table VALUES(1,3);
|
|
||||||
INSERT INTO append_stage_table VALUES(3,2);
|
|
||||||
INSERT INTO append_stage_table VALUES(5,4);
|
|
||||||
CREATE TABLE append_stage_table_2(id int, col_2 int);
|
|
||||||
INSERT INTO append_stage_table_2 VALUES(8,3);
|
|
||||||
INSERT INTO append_stage_table_2 VALUES(9,2);
|
|
||||||
INSERT INTO append_stage_table_2 VALUES(10,4);
|
|
||||||
CREATE TABLE test_append_table(id int, col_2 int);
|
|
||||||
SELECT create_distributed_table('test_append_table','id','append');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('test_append_table');
|
|
||||||
master_create_empty_shard
|
|
||||||
---------------------------
|
|
||||||
1440010
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT * FROM master_append_table_to_shard(1440010, 'append_stage_table', 'localhost', :master_port);
|
|
||||||
master_append_table_to_shard
|
|
||||||
------------------------------
|
|
||||||
0.00533333
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_empty_shard('test_append_table') AS new_shard_id;
|
|
||||||
new_shard_id
|
|
||||||
--------------
|
|
||||||
1440011
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT * FROM master_append_table_to_shard(1440011, 'append_stage_table_2', 'localhost', :master_port);
|
|
||||||
master_append_table_to_shard
|
|
||||||
------------------------------
|
|
||||||
0.00533333
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE test_append_table SET col_2 = 5;
|
|
||||||
SELECT * FROM test_append_table;
|
|
||||||
id | col_2
|
|
||||||
----+-------
|
|
||||||
8 | 5
|
|
||||||
9 | 5
|
|
||||||
10 | 5
|
|
||||||
1 | 5
|
|
||||||
3 | 5
|
|
||||||
5 | 5
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
DROP TABLE append_stage_table;
|
|
||||||
DROP TABLE append_stage_table_2;
|
|
||||||
DROP TABLE test_append_table;
|
|
||||||
-- Update multi shard of partitioned distributed table
|
|
||||||
SET citus.multi_shard_modify_mode to 'parallel';
|
|
||||||
SET citus.shard_replication_factor to 1;
|
|
||||||
CREATE TABLE tt1(id int, col_2 int) partition by range (col_2);
|
|
||||||
ERROR: syntax error at or near "partition"
|
|
||||||
LINE 1: CREATE TABLE tt1(id int, col_2 int) partition by range (col_...
|
|
||||||
^
|
|
||||||
CREATE TABLE tt1_510 partition of tt1 for VALUES FROM (5) to (10);
|
|
||||||
ERROR: syntax error at or near "partition"
|
|
||||||
LINE 1: CREATE TABLE tt1_510 partition of tt1 for VALUES FROM (5) to...
|
|
||||||
^
|
|
||||||
CREATE TABLE tt1_1120 partition of tt1 for VALUES FROM (11) to (20);
|
|
||||||
ERROR: syntax error at or near "partition"
|
|
||||||
LINE 1: CREATE TABLE tt1_1120 partition of tt1 for VALUES FROM (11) ...
|
|
||||||
^
|
|
||||||
INSERT INTO tt1 VALUES (1,11), (3,15), (5,17), (6,19), (8,17), (2,12);
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: INSERT INTO tt1 VALUES (1,11), (3,15), (5,17), (6,19), (8,17...
|
|
||||||
^
|
|
||||||
SELECT create_distributed_table('tt1','id');
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: SELECT create_distributed_table('tt1','id');
|
|
||||||
^
|
|
||||||
UPDATE tt1 SET col_2 = 13;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: UPDATE tt1 SET col_2 = 13;
|
|
||||||
^
|
|
||||||
DELETE FROM tt1 WHERE id = 1 or id = 3 or id = 5;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: DELETE FROM tt1 WHERE id = 1 or id = 3 or id = 5;
|
|
||||||
^
|
|
||||||
SELECT * FROM tt1;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: SELECT * FROM tt1;
|
|
||||||
^
|
|
||||||
-- Partitioned distributed table within transaction
|
|
||||||
INSERT INTO tt1 VALUES(4,6);
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: INSERT INTO tt1 VALUES(4,6);
|
|
||||||
^
|
|
||||||
INSERT INTO tt1 VALUES(7,7);
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: INSERT INTO tt1 VALUES(7,7);
|
|
||||||
^
|
|
||||||
INSERT INTO tt1 VALUES(9,8);
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: INSERT INTO tt1 VALUES(9,8);
|
|
||||||
^
|
|
||||||
BEGIN;
|
|
||||||
-- Update rows from partititon tt1_1120
|
|
||||||
UPDATE tt1 SET col_2 = 12 WHERE col_2 > 10 and col_2 < 20;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: UPDATE tt1 SET col_2 = 12 WHERE col_2 > 10 and col_2 < 20;
|
|
||||||
^
|
|
||||||
-- Update rows from partititon tt1_510
|
|
||||||
UPDATE tt1 SET col_2 = 7 WHERE col_2 < 10 and col_2 > 5;
|
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
COMMIT;
|
|
||||||
SELECT * FROM tt1 ORDER BY id;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: SELECT * FROM tt1 ORDER BY id;
|
|
||||||
^
|
|
||||||
-- Modify main table and partition table within same transaction
|
|
||||||
BEGIN;
|
|
||||||
UPDATE tt1 SET col_2 = 12 WHERE col_2 > 10 and col_2 < 20;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: UPDATE tt1 SET col_2 = 12 WHERE col_2 > 10 and col_2 < 20;
|
|
||||||
^
|
|
||||||
UPDATE tt1 SET col_2 = 7 WHERE col_2 < 10 and col_2 > 5;
|
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
DELETE FROM tt1_510;
|
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
DELETE FROM tt1_1120;
|
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
COMMIT;
|
|
||||||
SELECT * FROM tt1 ORDER BY id;
|
|
||||||
ERROR: relation "tt1" does not exist
|
|
||||||
LINE 1: SELECT * FROM tt1 ORDER BY id;
|
|
||||||
^
|
|
||||||
DROP TABLE tt1;
|
|
||||||
ERROR: table "tt1" does not exist
|
|
||||||
-- Update and copy in the same transaction
|
|
||||||
CREATE TABLE tt2(id int, col_2 int);
|
|
||||||
SELECT create_distributed_table('tt2','id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
\COPY tt2 FROM STDIN DELIMITER AS ',';
|
|
||||||
UPDATE tt2 SET col_2 = 1;
|
|
||||||
COMMIT;
|
|
||||||
SELECT * FROM tt2 ORDER BY id;
|
|
||||||
id | col_2
|
|
||||||
----+-------
|
|
||||||
1 | 1
|
|
||||||
2 | 1
|
|
||||||
3 | 1
|
|
||||||
7 | 1
|
|
||||||
9 | 1
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- Test returning with both type of executors
|
|
||||||
UPDATE tt2 SET col_2 = 5 RETURNING id, col_2;
|
|
||||||
id | col_2
|
|
||||||
----+-------
|
|
||||||
1 | 5
|
|
||||||
3 | 5
|
|
||||||
7 | 5
|
|
||||||
9 | 5
|
|
||||||
2 | 5
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
SET citus.multi_shard_modify_mode to sequential;
|
|
||||||
UPDATE tt2 SET col_2 = 3 RETURNING id, col_2;
|
|
||||||
id | col_2
|
|
||||||
----+-------
|
|
||||||
1 | 3
|
|
||||||
3 | 3
|
|
||||||
7 | 3
|
|
||||||
9 | 3
|
|
||||||
2 | 3
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
DROP TABLE tt2;
|
|
||||||
-- Multiple RTEs are only supported if subquery is pushdownable
|
|
||||||
SET citus.multi_shard_modify_mode to DEFAULT;
|
|
||||||
-- To test colocation between tables in modify query
|
|
||||||
SET citus.shard_count to 6;
|
|
||||||
CREATE TABLE events_test_table_2 (user_id int, value_1 int, value_2 int, value_3 int);
|
|
||||||
SELECT create_distributed_table('events_test_table_2', 'user_id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\COPY events_test_table_2 FROM STDIN DELIMITER AS ',';
|
|
||||||
CREATE TABLE events_test_table_local (user_id int, value_1 int, value_2 int, value_3 int);
|
|
||||||
\COPY events_test_table_local FROM STDIN DELIMITER AS ',';
|
|
||||||
CREATE TABLE test_table_1(id int, date_col timestamptz, col_3 int);
|
|
||||||
INSERT INTO test_table_1 VALUES(1, '2014-04-05 08:32:12', 5);
|
|
||||||
INSERT INTO test_table_1 VALUES(2, '2015-02-01 08:31:16', 7);
|
|
||||||
INSERT INTO test_table_1 VALUES(3, '2111-01-12 08:35:19', 9);
|
|
||||||
SELECT create_distributed_table('test_table_1', 'id');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- We can pushdown query if there is partition key equality
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
DELETE FROM users_test_table
|
|
||||||
USING events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 3
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM events_test_table);
|
|
||||||
DELETE FROM users_test_table
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM events_test_table);
|
|
||||||
DELETE FROM events_test_table_2
|
|
||||||
WHERE now() > (SELECT max(date_col)
|
|
||||||
FROM test_table_1
|
|
||||||
WHERE test_table_1.id = events_test_table_2.user_id
|
|
||||||
GROUP BY id)
|
|
||||||
RETURNING *;
|
|
||||||
user_id | value_1 | value_2 | value_3
|
|
||||||
---------+---------+---------+---------
|
|
||||||
1 | 5 | 7 | 7
|
|
||||||
1 | 20 | 12 | 25
|
|
||||||
1 | 60 | 17 | 17
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id
|
|
||||||
AND events_test_table.user_id > 5;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
UNION
|
|
||||||
SELECT user_id
|
|
||||||
FROM events_test_table);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
UNION
|
|
||||||
SELECT user_id
|
|
||||||
FROM events_test_table) returning value_3;
|
|
||||||
value_3
|
|
||||||
---------
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
(11 rows)
|
|
||||||
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
UNION ALL
|
|
||||||
SELECT user_id
|
|
||||||
FROM events_test_table) returning value_3;
|
|
||||||
value_3
|
|
||||||
---------
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
(11 rows)
|
|
||||||
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 5
|
|
||||||
WHERE
|
|
||||||
value_2 >
|
|
||||||
(SELECT
|
|
||||||
max(value_2)
|
|
||||||
FROM
|
|
||||||
events_test_table
|
|
||||||
WHERE
|
|
||||||
users_test_table.user_id = events_test_table.user_id
|
|
||||||
GROUP BY
|
|
||||||
user_id
|
|
||||||
);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_3 = 1
|
|
||||||
WHERE
|
|
||||||
value_2 >
|
|
||||||
(SELECT
|
|
||||||
max(value_2)
|
|
||||||
FROM
|
|
||||||
events_test_table
|
|
||||||
WHERE
|
|
||||||
users_test_table.user_id = events_test_table.user_id AND
|
|
||||||
users_test_table.value_2 > events_test_table.value_2
|
|
||||||
GROUP BY
|
|
||||||
user_id
|
|
||||||
);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 4
|
|
||||||
WHERE
|
|
||||||
value_1 > 1 AND value_1 < 3
|
|
||||||
AND value_2 >= 1
|
|
||||||
AND user_id IN
|
|
||||||
(
|
|
||||||
SELECT
|
|
||||||
e1.user_id
|
|
||||||
FROM (
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
1 AS view_homepage
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE
|
|
||||||
value_1 IN (0, 1)
|
|
||||||
) e1 LEFT JOIN LATERAL (
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
1 AS use_demo
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE
|
|
||||||
user_id = e1.user_id
|
|
||||||
) e2 ON true
|
|
||||||
);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_3 = 5
|
|
||||||
WHERE value_2 IN (SELECT AVG(value_1) OVER (PARTITION BY user_id) FROM events_test_table WHERE events_test_table.user_id = users_test_table.user_id);
|
|
||||||
-- Test it within transaction
|
|
||||||
BEGIN;
|
|
||||||
INSERT INTO users_test_table
|
|
||||||
SELECT * FROM events_test_table
|
|
||||||
WHERE events_test_table.user_id = 1 OR events_test_table.user_id = 5;
|
|
||||||
SELECT SUM(value_2) FROM users_test_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
169
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 1
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
SELECT SUM(value_2) FROM users_test_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
97
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
-- Test with schema
|
|
||||||
CREATE SCHEMA sec_schema;
|
|
||||||
CREATE TABLE sec_schema.tt1(id int, value_1 int);
|
|
||||||
SELECT create_distributed_table('sec_schema.tt1','id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO sec_schema.tt1 values(1,1),(2,2),(7,7),(9,9);
|
|
||||||
UPDATE sec_schema.tt1
|
|
||||||
SET value_1 = 11
|
|
||||||
WHERE id < (SELECT max(value_2) FROM events_test_table_2
|
|
||||||
WHERE sec_schema.tt1.id = events_test_table_2.user_id
|
|
||||||
GROUP BY user_id)
|
|
||||||
RETURNING *;
|
|
||||||
id | value_1
|
|
||||||
----+---------
|
|
||||||
7 | 11
|
|
||||||
9 | 11
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
DROP SCHEMA sec_schema CASCADE;
|
|
||||||
NOTICE: drop cascades to table sec_schema.tt1
|
|
||||||
-- We don't need partition key equality with reference tables
|
|
||||||
UPDATE events_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM users_reference_copy_table
|
|
||||||
WHERE users_reference_copy_table.user_id = events_test_table.value_1;
|
|
||||||
-- Both reference tables and hash distributed tables can be used in subquery
|
|
||||||
UPDATE events_test_table as ett
|
|
||||||
SET value_2 = 6
|
|
||||||
WHERE ett.value_3 IN (SELECT utt.value_3
|
|
||||||
FROM users_test_table as utt, users_reference_copy_table as uct
|
|
||||||
WHERE utt.user_id = uct.user_id AND utt.user_id = ett.user_id);
|
|
||||||
-- We don't need equality check with constant values in sub-select
|
|
||||||
UPDATE users_reference_copy_table
|
|
||||||
SET value_2 = 6
|
|
||||||
WHERE user_id IN (SELECT 2);
|
|
||||||
UPDATE users_reference_copy_table
|
|
||||||
SET value_2 = 6
|
|
||||||
WHERE value_1 IN (SELECT 2);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 6
|
|
||||||
WHERE user_id IN (SELECT 2);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 6
|
|
||||||
WHERE value_1 IN (SELECT 2);
|
|
||||||
-- Function calls in subqueries will be recursively planned
|
|
||||||
UPDATE test_table_1
|
|
||||||
SET col_3 = 6
|
|
||||||
WHERE date_col IN (SELECT now());
|
|
||||||
-- Test with prepared statements
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE value_1 = 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
PREPARE foo_plan_2(int,int) AS UPDATE users_test_table
|
|
||||||
SET value_1 = $1, value_3 = $2
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
EXECUTE foo_plan_2(1,5);
|
|
||||||
EXECUTE foo_plan_2(3,15);
|
|
||||||
EXECUTE foo_plan_2(5,25);
|
|
||||||
EXECUTE foo_plan_2(7,35);
|
|
||||||
EXECUTE foo_plan_2(9,45);
|
|
||||||
EXECUTE foo_plan_2(0,0);
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE value_1 = 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
6
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Test with varying WHERE expressions
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 7
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id OR FALSE;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 7
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id AND TRUE;
|
|
||||||
-- Test with inactive shard-placement
|
|
||||||
-- manually set shardstate of one placement of users_test_table as inactive
|
|
||||||
UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = 1440000;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
ERROR: cannot find a worker that has active placements for all shards in the query
|
|
||||||
-- manually set shardstate of one placement of events_test_table as inactive
|
|
||||||
UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = 1440004;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
ERROR: cannot find a worker that has active placements for all shards in the query
|
|
||||||
UPDATE pg_dist_shard_placement SET shardstate = 1 WHERE shardid = 1440000;
|
|
||||||
UPDATE pg_dist_shard_placement SET shardstate = 1 WHERE shardid = 1440004;
|
|
||||||
-- Subquery must return single value to use it with comparison operators
|
|
||||||
UPDATE users_test_table as utt
|
|
||||||
SET value_1 = 3
|
|
||||||
WHERE value_2 > (SELECT value_3 FROM events_test_table as ett WHERE utt.user_id = ett.user_id);
|
|
||||||
ERROR: more than one row returned by a subquery used as an expression
|
|
||||||
CONTEXT: while executing command on localhost:57637
|
|
||||||
-- We can not pushdown a query if the target relation is reference table
|
|
||||||
UPDATE users_reference_copy_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_reference_copy_table.user_id = events_test_table.user_id;
|
|
||||||
ERROR: only reference tables may be queried when targeting a reference table with multi shard UPDATE/DELETE queries with multiple tables
|
|
||||||
-- We cannot push down it if the query has outer join and using
|
|
||||||
UPDATE events_test_table
|
|
||||||
SET value_2 = users_test_table.user_id
|
|
||||||
FROM users_test_table
|
|
||||||
FULL OUTER JOIN events_test_table e2 USING (user_id)
|
|
||||||
WHERE e2.user_id = events_test_table.user_id RETURNING events_test_table.value_2;
|
|
||||||
ERROR: a join with USING causes an internal naming conflict, use ON instead
|
|
||||||
-- Non-pushdownable subqueries, but will be handled through recursive planning
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 1
|
|
||||||
WHERE user_id IN (SELECT Count(value_1)
|
|
||||||
FROM events_test_table
|
|
||||||
GROUP BY user_id);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = (SELECT Count(*)
|
|
||||||
FROM events_test_table);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
UNION
|
|
||||||
SELECT value_1
|
|
||||||
FROM events_test_table);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN (SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
INTERSECT
|
|
||||||
SELECT Sum(value_1)
|
|
||||||
FROM events_test_table
|
|
||||||
GROUP BY user_id);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = (SELECT value_3
|
|
||||||
FROM users_test_table);
|
|
||||||
ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 2
|
|
||||||
WHERE
|
|
||||||
value_2 >
|
|
||||||
(SELECT
|
|
||||||
max(value_2)
|
|
||||||
FROM
|
|
||||||
events_test_table
|
|
||||||
WHERE
|
|
||||||
users_test_table.user_id > events_test_table.user_id AND
|
|
||||||
users_test_table.value_1 = events_test_table.value_1
|
|
||||||
GROUP BY
|
|
||||||
user_id
|
|
||||||
);
|
|
||||||
ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET (value_1, value_2) = (2,1)
|
|
||||||
WHERE user_id IN
|
|
||||||
(SELECT user_id
|
|
||||||
FROM users_test_table
|
|
||||||
INTERSECT
|
|
||||||
SELECT user_id
|
|
||||||
FROM events_test_table);
|
|
||||||
-- Reference tables can not locate on the outer part of the outer join
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_1 = 4
|
|
||||||
WHERE user_id IN
|
|
||||||
(SELECT DISTINCT e2.user_id
|
|
||||||
FROM users_reference_copy_table
|
|
||||||
LEFT JOIN users_test_table e2 ON (e2.user_id = users_reference_copy_table.value_1)) RETURNING *;
|
|
||||||
ERROR: cannot pushdown the subquery
|
|
||||||
DETAIL: There exist a reference table in the outer part of the outer join
|
|
||||||
-- Volatile functions are also not supported
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id * random();
|
|
||||||
ERROR: functions used in the WHERE clause of modification queries on distributed tables must not be VOLATILE
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5 * random()
|
|
||||||
FROM events_test_table
|
|
||||||
WHERE users_test_table.user_id = events_test_table.user_id;
|
|
||||||
ERROR: functions used in UPDATE queries on distributed tables must not be VOLATILE
|
|
||||||
-- Recursive modify planner does not take care of following test because the query
|
|
||||||
-- is fully pushdownable, yet not allowed because it would lead to inconsistent replicas.
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = subquery.random FROM (SELECT user_id, random()
|
|
||||||
FROM events_test_table) subquery
|
|
||||||
WHERE users_test_table.user_id = subquery.user_id;
|
|
||||||
ERROR: functions used in UPDATE queries on distributed tables must not be VOLATILE
|
|
||||||
-- Volatile functions in a subquery are recursively planned
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
WHERE users_test_table.user_id IN (SELECT user_id * random() FROM events_test_table);
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = subquery.random FROM (SELECT user_id, random()
|
|
||||||
FROM events_test_table) subquery;
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = subquery.random FROM (SELECT user_id, random()
|
|
||||||
FROM events_test_table OFFSET 0) subquery
|
|
||||||
WHERE users_test_table.user_id = subquery.user_id;
|
|
||||||
-- Make following tests consistent
|
|
||||||
UPDATE users_test_table SET value_2 = 0;
|
|
||||||
-- Local tables are not supported
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table_local
|
|
||||||
WHERE users_test_table.user_id = events_test_table_local.user_id;
|
|
||||||
ERROR: relation events_test_table_local is not distributed
|
|
||||||
UPDATE events_test_table_local
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM users_test_table
|
|
||||||
WHERE events_test_table_local.user_id = users_test_table.user_id;
|
|
||||||
ERROR: relation events_test_table_local is not distributed
|
|
||||||
-- Local tables in a subquery are supported through recursive planning
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
WHERE users_test_table.user_id IN(SELECT user_id FROM events_test_table_local);
|
|
||||||
-- Shard counts of tables must be equal to pushdown the query
|
|
||||||
UPDATE users_test_table
|
|
||||||
SET value_2 = 5
|
|
||||||
FROM events_test_table_2
|
|
||||||
WHERE users_test_table.user_id = events_test_table_2.user_id;
|
|
||||||
ERROR: cannot push down this subquery
|
|
||||||
DETAIL: Shards of relations in subquery need to have 1-to-1 shard partitioning
|
|
||||||
-- Should error out due to multiple row return from subquery, but we can not get this information within
|
|
||||||
-- subquery pushdown planner. This query will be sent to worker with recursive planner.
|
|
||||||
DELETE FROM users_test_table
|
|
||||||
WHERE users_test_table.user_id = (SELECT user_id
|
|
||||||
FROM events_test_table);
|
|
||||||
ERROR: more than one row returned by a subquery used as an expression
|
|
||||||
CONTEXT: while executing command on localhost:57637
|
|
||||||
-- Cursors are not supported
|
|
||||||
BEGIN;
|
|
||||||
DECLARE test_cursor CURSOR FOR SELECT * FROM users_test_table ORDER BY user_id;
|
|
||||||
FETCH test_cursor;
|
|
||||||
user_id | value_1 | value_2 | value_3
|
|
||||||
---------+---------+---------+---------
|
|
||||||
1 | 2 | 5 | 0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_2 = 5 WHERE CURRENT OF test_cursor;
|
|
||||||
ERROR: cannot run DML queries with cursors
|
|
||||||
ROLLBACK;
|
|
||||||
-- Stable functions are supported
|
|
||||||
SELECT * FROM test_table_1;
|
|
||||||
id | date_col | col_3
|
|
||||||
----+------------------------------+-------
|
|
||||||
1 | Sat Apr 05 08:32:12 2014 PDT | 5
|
|
||||||
3 | Mon Jan 12 08:35:19 2111 PST | 9
|
|
||||||
2 | Sun Feb 01 08:31:16 2015 PST | 7
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
UPDATE test_table_1 SET col_3 = 3 WHERE date_col < now();
|
|
||||||
SELECT * FROM test_table_1;
|
|
||||||
id | date_col | col_3
|
|
||||||
----+------------------------------+-------
|
|
||||||
1 | Sat Apr 05 08:32:12 2014 PDT | 3
|
|
||||||
3 | Mon Jan 12 08:35:19 2111 PST | 9
|
|
||||||
2 | Sun Feb 01 08:31:16 2015 PST | 3
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
DELETE FROM test_table_1 WHERE date_col < current_timestamp;
|
|
||||||
SELECT * FROM test_table_1;
|
|
||||||
id | date_col | col_3
|
|
||||||
----+------------------------------+-------
|
|
||||||
3 | Mon Jan 12 08:35:19 2111 PST | 9
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE test_table_1;
|
|
||||||
-- Volatile functions are not supported
|
|
||||||
CREATE TABLE test_table_2(id int, double_col double precision);
|
|
||||||
INSERT INTO test_table_2 VALUES(1, random());
|
|
||||||
INSERT INTO test_table_2 VALUES(2, random());
|
|
||||||
INSERT INTO test_table_2 VALUES(3, random());
|
|
||||||
SELECT create_distributed_table('test_table_2', 'id');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE test_table_2 SET double_col = random();
|
|
||||||
ERROR: functions used in UPDATE queries on distributed tables must not be VOLATILE
|
|
||||||
DROP TABLE test_table_2;
|
|
||||||
-- Run multi shard updates and deletes without transaction on reference tables
|
|
||||||
SELECT COUNT(*) FROM users_reference_copy_table;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
15
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_reference_copy_table SET value_1 = 1;
|
|
||||||
SELECT SUM(value_1) FROM users_reference_copy_table;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
15
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_reference_copy_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 52
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_reference_copy_table SET value_2 = value_2 + 1 WHERE user_id = 3 or user_id = 5;
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_reference_copy_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 56
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_reference_copy_table SET value_3 = 0 WHERE user_id <> 3;
|
|
||||||
SELECT SUM(value_3) FROM users_reference_copy_table WHERE user_id <> 3;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DELETE FROM users_reference_copy_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
SELECT COUNT(*) FROM users_reference_copy_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Do some tests by changing shard replication factor
|
|
||||||
DROP TABLE users_test_table;
|
|
||||||
SET citus.shard_replication_factor to 2;
|
|
||||||
CREATE TABLE users_test_table(user_id int, value_1 int, value_2 int, value_3 int);
|
|
||||||
SELECT create_distributed_table('users_test_table', 'user_id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
\COPY users_test_table FROM STDIN DELIMITER AS ',';
|
|
||||||
-- Run multi shard updates and deletes without transaction on hash distributed tables
|
|
||||||
UPDATE users_test_table SET value_1 = 1;
|
|
||||||
SELECT COUNT(*), SUM(value_1) FROM users_test_table;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
15 | 15
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_test_table WHERE user_id = 1 or user_id = 3;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 52
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_2 = value_2 + 1 WHERE user_id = 1 or user_id = 3;
|
|
||||||
SELECT COUNT(*), SUM(value_2) FROM users_test_table WHERE user_id = 1 or user_id = 3;
|
|
||||||
count | sum
|
|
||||||
-------+-----
|
|
||||||
4 | 56
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
UPDATE users_test_table SET value_3 = 0 WHERE user_id <> 5;
|
|
||||||
SELECT SUM(value_3) FROM users_test_table WHERE user_id <> 5;
|
|
||||||
sum
|
|
||||||
-----
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
4
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DELETE FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
SELECT COUNT(*) FROM users_test_table WHERE user_id = 3 or user_id = 5;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
0
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE users_test_table;
|
|
||||||
DROP TABLE events_test_table;
|
|
||||||
DROP TABLE events_reference_copy_table;
|
|
||||||
DROP TABLE users_reference_copy_table;
|
|
||||||
|
|
@ -2,14 +2,6 @@
|
||||||
-- MULTI_TASK_ASSIGNMENT
|
-- MULTI_TASK_ASSIGNMENT
|
||||||
--
|
--
|
||||||
SET citus.next_shard_id TO 880000;
|
SET citus.next_shard_id TO 880000;
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
version_above_nine
|
|
||||||
--------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- the function simply parses the results and returns 'shardId@worker'
|
-- the function simply parses the results and returns 'shardId@worker'
|
||||||
-- for all the explain task outputs
|
-- for all the explain task outputs
|
||||||
CREATE OR REPLACE FUNCTION parse_explain_output(in qry text, in table_name text, out r text)
|
CREATE OR REPLACE FUNCTION parse_explain_output(in qry text, in table_name text, out r text)
|
||||||
|
|
@ -78,25 +70,25 @@ SET client_min_messages TO DEBUG3;
|
||||||
SET citus.task_assignment_policy TO 'greedy';
|
SET citus.task_assignment_policy TO 'greedy';
|
||||||
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
||||||
DEBUG: Router planner does not support append-partitioned tables.
|
DEBUG: Router planner does not support append-partitioned tables.
|
||||||
DEBUG: assigned task 3 to node localhost:57637
|
DEBUG: assigned task 1 to node localhost:57637
|
||||||
DEBUG: assigned task 1 to node localhost:57638
|
DEBUG: assigned task 3 to node localhost:57638
|
||||||
DEBUG: assigned task 2 to node localhost:57637
|
DEBUG: assigned task 2 to node localhost:57637
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
||||||
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
|
-> Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
||||||
DEBUG: Router planner does not support append-partitioned tables.
|
DEBUG: Router planner does not support append-partitioned tables.
|
||||||
DEBUG: assigned task 3 to node localhost:57637
|
DEBUG: assigned task 1 to node localhost:57637
|
||||||
DEBUG: assigned task 1 to node localhost:57638
|
DEBUG: assigned task 3 to node localhost:57638
|
||||||
DEBUG: assigned task 2 to node localhost:57637
|
DEBUG: assigned task 2 to node localhost:57637
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
||||||
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
|
-> Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
|
|
@ -104,25 +96,25 @@ DEBUG: assigned task 2 to node localhost:57637
|
||||||
SET citus.task_assignment_policy TO 'first-replica';
|
SET citus.task_assignment_policy TO 'first-replica';
|
||||||
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
||||||
DEBUG: Router planner does not support append-partitioned tables.
|
DEBUG: Router planner does not support append-partitioned tables.
|
||||||
DEBUG: assigned task 3 to node localhost:57637
|
DEBUG: assigned task 1 to node localhost:57637
|
||||||
DEBUG: assigned task 2 to node localhost:57637
|
DEBUG: assigned task 2 to node localhost:57637
|
||||||
DEBUG: assigned task 1 to node localhost:57638
|
DEBUG: assigned task 3 to node localhost:57638
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
||||||
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
|
-> Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
EXPLAIN SELECT count(*) FROM task_assignment_test_table;
|
||||||
DEBUG: Router planner does not support append-partitioned tables.
|
DEBUG: Router planner does not support append-partitioned tables.
|
||||||
DEBUG: assigned task 3 to node localhost:57637
|
DEBUG: assigned task 1 to node localhost:57637
|
||||||
DEBUG: assigned task 2 to node localhost:57637
|
DEBUG: assigned task 2 to node localhost:57637
|
||||||
DEBUG: assigned task 1 to node localhost:57638
|
DEBUG: assigned task 3 to node localhost:57638
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
||||||
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
|
-> Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
|
|
@ -145,7 +137,7 @@ DEBUG: Creating router plan
|
||||||
DEBUG: Plan is router executable
|
DEBUG: Plan is router executable
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
Custom Scan (Citus Router)
|
Custom Scan (Citus Adaptive)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
|
@ -155,7 +147,7 @@ DEBUG: Creating router plan
|
||||||
DEBUG: Plan is router executable
|
DEBUG: Plan is router executable
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
Custom Scan (Citus Router)
|
Custom Scan (Citus Adaptive)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
|
@ -166,7 +158,7 @@ DEBUG: Creating router plan
|
||||||
DEBUG: Plan is router executable
|
DEBUG: Plan is router executable
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
Custom Scan (Citus Router)
|
Custom Scan (Citus Adaptive)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
|
@ -176,7 +168,7 @@ DEBUG: Creating router plan
|
||||||
DEBUG: Plan is router executable
|
DEBUG: Plan is router executable
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
Custom Scan (Citus Router)
|
Custom Scan (Citus Adaptive)
|
||||||
explain statements for distributed queries are not enabled
|
explain statements for distributed queries are not enabled
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
SET citus.next_shard_id TO 990000;
|
SET citus.next_shard_id TO 990000;
|
||||||
-- print server version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 as version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- test utility statement functionality
|
-- test utility statement functionality
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
|
|
|
||||||
|
|
@ -1,466 +0,0 @@
|
||||||
SET citus.next_shard_id TO 990000;
|
|
||||||
-- print server version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 as version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ===================================================================
|
|
||||||
-- test utility statement functionality
|
|
||||||
-- ===================================================================
|
|
||||||
SET citus.shard_count TO 2;
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
|
||||||
CREATE TABLE sharded_table ( name text, id bigint );
|
|
||||||
SELECT create_distributed_table('sharded_table', 'id', 'hash');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- COPY out is supported with distributed tables
|
|
||||||
COPY sharded_table TO STDOUT;
|
|
||||||
COPY (SELECT COUNT(*) FROM sharded_table) TO STDOUT;
|
|
||||||
0
|
|
||||||
BEGIN;
|
|
||||||
SET TRANSACTION READ ONLY;
|
|
||||||
COPY sharded_table TO STDOUT;
|
|
||||||
COPY (SELECT COUNT(*) FROM sharded_table) TO STDOUT;
|
|
||||||
0
|
|
||||||
COMMIT;
|
|
||||||
-- ANALYZE is supported in a transaction block
|
|
||||||
BEGIN;
|
|
||||||
ANALYZE sharded_table;
|
|
||||||
ANALYZE sharded_table;
|
|
||||||
END;
|
|
||||||
-- cursors may not involve distributed tables
|
|
||||||
DECLARE all_sharded_rows CURSOR FOR SELECT * FROM sharded_table;
|
|
||||||
ERROR: DECLARE CURSOR can only be used in transaction blocks
|
|
||||||
-- verify PREPARE functionality
|
|
||||||
PREPARE sharded_insert AS INSERT INTO sharded_table VALUES ('adam', 1);
|
|
||||||
PREPARE sharded_update AS UPDATE sharded_table SET name = 'bob' WHERE id = 1;
|
|
||||||
PREPARE sharded_delete AS DELETE FROM sharded_table WHERE id = 1;
|
|
||||||
PREPARE sharded_query AS SELECT name FROM sharded_table WHERE id = 1;
|
|
||||||
EXECUTE sharded_query;
|
|
||||||
name
|
|
||||||
------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
EXECUTE sharded_insert;
|
|
||||||
EXECUTE sharded_query;
|
|
||||||
name
|
|
||||||
------
|
|
||||||
adam
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
EXECUTE sharded_update;
|
|
||||||
EXECUTE sharded_query;
|
|
||||||
name
|
|
||||||
------
|
|
||||||
bob
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
EXECUTE sharded_delete;
|
|
||||||
EXECUTE sharded_query;
|
|
||||||
name
|
|
||||||
------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
-- try to drop shards with where clause
|
|
||||||
SELECT master_apply_delete_command('DELETE FROM sharded_table WHERE id > 0');
|
|
||||||
ERROR: cannot delete from hash distributed table with this command
|
|
||||||
DETAIL: Delete statements on hash-partitioned tables are not supported with master_apply_delete_command.
|
|
||||||
HINT: Use the DELETE command instead.
|
|
||||||
-- drop all shards
|
|
||||||
SELECT master_apply_delete_command('DELETE FROM sharded_table');
|
|
||||||
ERROR: cannot delete from hash distributed table with this command
|
|
||||||
DETAIL: Delete statements on hash-partitioned tables are not supported with master_apply_delete_command.
|
|
||||||
HINT: Use the DELETE command instead.
|
|
||||||
-- lock shard metadata: take some share locks and exclusive locks
|
|
||||||
BEGIN;
|
|
||||||
SELECT lock_shard_metadata(5, ARRAY[999001, 999002, 999002]);
|
|
||||||
lock_shard_metadata
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT lock_shard_metadata(7, ARRAY[999001, 999003, 999004]);
|
|
||||||
lock_shard_metadata
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT locktype, objid, mode, granted
|
|
||||||
FROM pg_locks
|
|
||||||
WHERE objid IN (999001, 999002, 999003, 999004)
|
|
||||||
ORDER BY objid, mode;
|
|
||||||
locktype | objid | mode | granted
|
|
||||||
----------+--------+---------------+---------
|
|
||||||
advisory | 999001 | ExclusiveLock | t
|
|
||||||
advisory | 999001 | ShareLock | t
|
|
||||||
advisory | 999002 | ShareLock | t
|
|
||||||
advisory | 999003 | ExclusiveLock | t
|
|
||||||
advisory | 999004 | ExclusiveLock | t
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
END;
|
|
||||||
-- lock shard metadata: unsupported lock type
|
|
||||||
SELECT lock_shard_metadata(0, ARRAY[990001, 999002]);
|
|
||||||
ERROR: unsupported lockmode 0
|
|
||||||
-- lock shard metadata: invalid shard ID
|
|
||||||
SELECT lock_shard_metadata(5, ARRAY[0]);
|
|
||||||
lock_shard_metadata
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- lock shard metadata: lock nothing
|
|
||||||
SELECT lock_shard_metadata(5, ARRAY[]::bigint[]);
|
|
||||||
ERROR: no locks specified
|
|
||||||
-- lock shard resources: take some share locks and exclusive locks
|
|
||||||
BEGIN;
|
|
||||||
SELECT lock_shard_resources(5, ARRAY[999001, 999002, 999002]);
|
|
||||||
lock_shard_resources
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT lock_shard_resources(7, ARRAY[999001, 999003, 999004]);
|
|
||||||
lock_shard_resources
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT locktype, objid, mode, granted
|
|
||||||
FROM pg_locks
|
|
||||||
WHERE objid IN (999001, 999002, 999003, 999004)
|
|
||||||
ORDER BY objid, mode;
|
|
||||||
locktype | objid | mode | granted
|
|
||||||
----------+--------+---------------+---------
|
|
||||||
advisory | 999001 | ExclusiveLock | t
|
|
||||||
advisory | 999001 | ShareLock | t
|
|
||||||
advisory | 999002 | ShareLock | t
|
|
||||||
advisory | 999003 | ExclusiveLock | t
|
|
||||||
advisory | 999004 | ExclusiveLock | t
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
END;
|
|
||||||
-- lock shard metadata: unsupported lock type
|
|
||||||
SELECT lock_shard_resources(0, ARRAY[990001, 999002]);
|
|
||||||
ERROR: unsupported lockmode 0
|
|
||||||
-- lock shard metadata: invalid shard ID
|
|
||||||
SELECT lock_shard_resources(5, ARRAY[-1]);
|
|
||||||
lock_shard_resources
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- lock shard metadata: lock nothing
|
|
||||||
SELECT lock_shard_resources(5, ARRAY[]::bigint[]);
|
|
||||||
ERROR: no locks specified
|
|
||||||
-- drop table
|
|
||||||
DROP TABLE sharded_table;
|
|
||||||
-- VACUUM tests
|
|
||||||
-- create a table with a single shard (for convenience)
|
|
||||||
SET citus.shard_count TO 1;
|
|
||||||
SET citus.shard_replication_factor TO 2;
|
|
||||||
CREATE TABLE dustbunnies (id integer, name text, age integer);
|
|
||||||
SELECT create_distributed_table('dustbunnies', 'id', 'hash');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- add some data to the distributed table
|
|
||||||
\copy dustbunnies (id, name) from stdin with csv
|
|
||||||
CREATE TABLE second_dustbunnies(id integer, name text, age integer);
|
|
||||||
SELECT master_create_distributed_table('second_dustbunnies', 'id', 'hash');
|
|
||||||
master_create_distributed_table
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_worker_shards('second_dustbunnies', 1, 2);
|
|
||||||
master_create_worker_shards
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- following approach adapted from PostgreSQL's stats.sql file
|
|
||||||
-- save relevant stat counter values in refreshable view
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
CREATE MATERIALIZED VIEW prevcounts AS
|
|
||||||
SELECT analyze_count, vacuum_count FROM pg_stat_user_tables
|
|
||||||
WHERE relname='dustbunnies_990002';
|
|
||||||
-- create function that sleeps until those counters increment
|
|
||||||
create function wait_for_stats() returns void as $$
|
|
||||||
declare
|
|
||||||
start_time timestamptz := clock_timestamp();
|
|
||||||
analyze_updated bool;
|
|
||||||
vacuum_updated bool;
|
|
||||||
begin
|
|
||||||
-- we don't want to wait forever; loop will exit after 10 seconds
|
|
||||||
for i in 1 .. 100 loop
|
|
||||||
|
|
||||||
-- check to see if analyze has been updated
|
|
||||||
SELECT (st.analyze_count >= pc.analyze_count + 1) INTO analyze_updated
|
|
||||||
FROM pg_stat_user_tables AS st, pg_class AS cl, prevcounts AS pc
|
|
||||||
WHERE st.relname='dustbunnies_990002' AND cl.relname='dustbunnies_990002';
|
|
||||||
|
|
||||||
-- check to see if vacuum has been updated
|
|
||||||
SELECT (st.vacuum_count >= pc.vacuum_count + 1) INTO vacuum_updated
|
|
||||||
FROM pg_stat_user_tables AS st, pg_class AS cl, prevcounts AS pc
|
|
||||||
WHERE st.relname='dustbunnies_990002' AND cl.relname='dustbunnies_990002';
|
|
||||||
|
|
||||||
exit when analyze_updated or vacuum_updated;
|
|
||||||
|
|
||||||
-- wait a little
|
|
||||||
perform pg_sleep(0.1);
|
|
||||||
|
|
||||||
-- reset stats snapshot so we can test again
|
|
||||||
perform pg_stat_clear_snapshot();
|
|
||||||
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
-- report time waited in postmaster log (where it won't change test output)
|
|
||||||
raise log 'wait_for_stats delayed % seconds',
|
|
||||||
extract(epoch from clock_timestamp() - start_time);
|
|
||||||
end
|
|
||||||
$$ language plpgsql;
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
CREATE MATERIALIZED VIEW prevcounts AS
|
|
||||||
SELECT analyze_count, vacuum_count FROM pg_stat_user_tables
|
|
||||||
WHERE relname='dustbunnies_990001';
|
|
||||||
-- create function that sleeps until those counters increment
|
|
||||||
create function wait_for_stats() returns void as $$
|
|
||||||
declare
|
|
||||||
start_time timestamptz := clock_timestamp();
|
|
||||||
analyze_updated bool;
|
|
||||||
vacuum_updated bool;
|
|
||||||
begin
|
|
||||||
-- we don't want to wait forever; loop will exit after 10 seconds
|
|
||||||
for i in 1 .. 100 loop
|
|
||||||
|
|
||||||
-- check to see if analyze has been updated
|
|
||||||
SELECT (st.analyze_count >= pc.analyze_count + 1) INTO analyze_updated
|
|
||||||
FROM pg_stat_user_tables AS st, pg_class AS cl, prevcounts AS pc
|
|
||||||
WHERE st.relname='dustbunnies_990001' AND cl.relname='dustbunnies_990001';
|
|
||||||
|
|
||||||
-- check to see if vacuum has been updated
|
|
||||||
SELECT (st.vacuum_count >= pc.vacuum_count + 1) INTO vacuum_updated
|
|
||||||
FROM pg_stat_user_tables AS st, pg_class AS cl, prevcounts AS pc
|
|
||||||
WHERE st.relname='dustbunnies_990001' AND cl.relname='dustbunnies_990001';
|
|
||||||
|
|
||||||
exit when analyze_updated or vacuum_updated;
|
|
||||||
|
|
||||||
-- wait a little
|
|
||||||
perform pg_sleep(0.1);
|
|
||||||
|
|
||||||
-- reset stats snapshot so we can test again
|
|
||||||
perform pg_stat_clear_snapshot();
|
|
||||||
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
-- report time waited in postmaster log (where it won't change test output)
|
|
||||||
raise log 'wait_for_stats delayed % seconds',
|
|
||||||
extract(epoch from clock_timestamp() - start_time);
|
|
||||||
end
|
|
||||||
$$ language plpgsql;
|
|
||||||
-- run VACUUM and ANALYZE against the table on the master
|
|
||||||
\c - - - :master_port
|
|
||||||
VACUUM dustbunnies;
|
|
||||||
ANALYZE dustbunnies;
|
|
||||||
-- verify that the VACUUM and ANALYZE ran
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT wait_for_stats();
|
|
||||||
wait_for_stats
|
|
||||||
----------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
REFRESH MATERIALIZED VIEW prevcounts;
|
|
||||||
SELECT pg_stat_get_vacuum_count('dustbunnies_990002'::regclass);
|
|
||||||
pg_stat_get_vacuum_count
|
|
||||||
--------------------------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT pg_stat_get_analyze_count('dustbunnies_990002'::regclass);
|
|
||||||
pg_stat_get_analyze_count
|
|
||||||
---------------------------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- get file node to verify VACUUM FULL
|
|
||||||
SELECT relfilenode AS oldnode FROM pg_class WHERE oid='dustbunnies_990002'::regclass
|
|
||||||
\gset
|
|
||||||
-- send a VACUUM FULL and a VACUUM ANALYZE
|
|
||||||
\c - - - :master_port
|
|
||||||
VACUUM (FULL) dustbunnies;
|
|
||||||
VACUUM ANALYZE dustbunnies;
|
|
||||||
-- verify that relfilenode changed
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT relfilenode != :oldnode AS table_rewritten FROM pg_class
|
|
||||||
WHERE oid='dustbunnies_990002'::regclass;
|
|
||||||
table_rewritten
|
|
||||||
-----------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- verify the VACUUM ANALYZE incremented both vacuum and analyze counts
|
|
||||||
SELECT wait_for_stats();
|
|
||||||
wait_for_stats
|
|
||||||
----------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT pg_stat_get_vacuum_count('dustbunnies_990002'::regclass);
|
|
||||||
pg_stat_get_vacuum_count
|
|
||||||
--------------------------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT pg_stat_get_analyze_count('dustbunnies_990002'::regclass);
|
|
||||||
pg_stat_get_analyze_count
|
|
||||||
---------------------------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- disable auto-VACUUM for next test
|
|
||||||
ALTER TABLE dustbunnies_990002 SET (autovacuum_enabled = false);
|
|
||||||
SELECT relfrozenxid AS frozenxid FROM pg_class WHERE oid='dustbunnies_990002'::regclass
|
|
||||||
\gset
|
|
||||||
-- send a VACUUM FREEZE after adding a new row
|
|
||||||
\c - - - :master_port
|
|
||||||
INSERT INTO dustbunnies VALUES (5, 'peter');
|
|
||||||
VACUUM (FREEZE) dustbunnies;
|
|
||||||
-- verify that relfrozenxid increased
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT relfrozenxid::text::integer > :frozenxid AS frozen_performed FROM pg_class
|
|
||||||
WHERE oid='dustbunnies_990002'::regclass;
|
|
||||||
frozen_performed
|
|
||||||
------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- check there are no nulls in either column
|
|
||||||
SELECT attname, null_frac FROM pg_stats
|
|
||||||
WHERE tablename = 'dustbunnies_990002' ORDER BY attname;
|
|
||||||
attname | null_frac
|
|
||||||
---------+-----------
|
|
||||||
age | 1
|
|
||||||
id | 0
|
|
||||||
name | 0
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- add NULL values, then perform column-specific ANALYZE
|
|
||||||
\c - - - :master_port
|
|
||||||
INSERT INTO dustbunnies VALUES (6, NULL, NULL);
|
|
||||||
ANALYZE dustbunnies (name);
|
|
||||||
-- verify that name's NULL ratio is updated but age's is not
|
|
||||||
\c - - - :worker_1_port
|
|
||||||
SELECT attname, null_frac FROM pg_stats
|
|
||||||
WHERE tablename = 'dustbunnies_990002' ORDER BY attname;
|
|
||||||
attname | null_frac
|
|
||||||
---------+-----------
|
|
||||||
age | 1
|
|
||||||
id | 0
|
|
||||||
name | 0.166667
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
\c - - - :master_port
|
|
||||||
-- verify warning for unqualified VACUUM
|
|
||||||
VACUUM;
|
|
||||||
WARNING: not propagating VACUUM command to worker nodes
|
|
||||||
HINT: Provide a specific table in order to VACUUM distributed tables.
|
|
||||||
-- check for multiple table vacuum
|
|
||||||
VACUUM dustbunnies, second_dustbunnies;
|
|
||||||
ERROR: syntax error at or near ","
|
|
||||||
LINE 1: VACUUM dustbunnies, second_dustbunnies;
|
|
||||||
^
|
|
||||||
-- check the current number of vacuum and analyze run on dustbunnies
|
|
||||||
SELECT run_command_on_workers($$SELECT wait_for_stats()$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT pg_stat_get_vacuum_count(tablename::regclass) from pg_tables where tablename LIKE 'dustbunnies_%' limit 1$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,3)
|
|
||||||
(localhost,57638,t,3)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT pg_stat_get_analyze_count(tablename::regclass) from pg_tables where tablename LIKE 'dustbunnies_%' limit 1$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,3)
|
|
||||||
(localhost,57638,t,3)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- and warning when using targeted VACUUM without DDL propagation
|
|
||||||
SET citus.enable_ddl_propagation to false;
|
|
||||||
VACUUM dustbunnies;
|
|
||||||
WARNING: not propagating VACUUM command to worker nodes
|
|
||||||
HINT: Set citus.enable_ddl_propagation to true in order to send targeted VACUUM commands to worker nodes.
|
|
||||||
ANALYZE dustbunnies;
|
|
||||||
WARNING: not propagating ANALYZE command to worker nodes
|
|
||||||
HINT: Set citus.enable_ddl_propagation to true in order to send targeted ANALYZE commands to worker nodes.
|
|
||||||
SET citus.enable_ddl_propagation to DEFAULT;
|
|
||||||
-- should not propagate the vacuum and analyze
|
|
||||||
SELECT run_command_on_workers($$SELECT wait_for_stats()$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,"")
|
|
||||||
(localhost,57638,t,"")
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT pg_stat_get_vacuum_count(tablename::regclass) from pg_tables where tablename LIKE 'dustbunnies_%' limit 1$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,3)
|
|
||||||
(localhost,57638,t,3)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT run_command_on_workers($$SELECT pg_stat_get_analyze_count(tablename::regclass) from pg_tables where tablename LIKE 'dustbunnies_%' limit 1$$);
|
|
||||||
run_command_on_workers
|
|
||||||
------------------------
|
|
||||||
(localhost,57637,t,3)
|
|
||||||
(localhost,57638,t,3)
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- test worker_hash
|
|
||||||
SELECT worker_hash(123);
|
|
||||||
worker_hash
|
|
||||||
-------------
|
|
||||||
-205084363
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT worker_hash('1997-08-08'::date);
|
|
||||||
worker_hash
|
|
||||||
-------------
|
|
||||||
-499701663
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test a custom type (this test should run after multi_data_types)
|
|
||||||
SELECT worker_hash('(1, 2)');
|
|
||||||
ERROR: cannot find a hash function for the input type
|
|
||||||
HINT: Cast input to a data type with a hash function.
|
|
||||||
SELECT worker_hash('(1, 2)'::test_composite_type);
|
|
||||||
worker_hash
|
|
||||||
-------------
|
|
||||||
-1895345704
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT citus_truncate_trigger();
|
|
||||||
ERROR: must be called as trigger
|
|
||||||
-- confirm that citus_create_restore_point works
|
|
||||||
SELECT 1 FROM citus_create_restore_point('regression-test');
|
|
||||||
?column?
|
|
||||||
----------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
|
|
@ -5,14 +5,6 @@
|
||||||
-- Citus features: simple selects, aggregates, joins, outer joins
|
-- Citus features: simple selects, aggregates, joins, outer joins
|
||||||
-- router queries, single row inserts, multi row inserts via insert
|
-- router queries, single row inserts, multi row inserts via insert
|
||||||
-- into select, multi row insert via copy commands.
|
-- into select, multi row insert via copy commands.
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM lineitem_hash_part;
|
SELECT count(*) FROM lineitem_hash_part;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
|
|
@ -815,7 +807,7 @@ EXPLAIN (COSTS FALSE) SELECT user_id FROM recent_selected_users GROUP BY 1 ORDER
|
||||||
Sort Key: remote_scan.user_id
|
Sort Key: remote_scan.user_id
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
Group Key: remote_scan.user_id
|
Group Key: remote_scan.user_id
|
||||||
-> Custom Scan (Citus Real-Time)
|
-> Custom Scan (Citus Adaptive)
|
||||||
Task Count: 4
|
Task Count: 4
|
||||||
Tasks Shown: One of 4
|
Tasks Shown: One of 4
|
||||||
-> Task
|
-> Task
|
||||||
|
|
@ -845,7 +837,7 @@ EXPLAIN (COSTS FALSE) SELECT *
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
Sort
|
Sort
|
||||||
Sort Key: remote_scan.user_id
|
Sort Key: remote_scan.user_id
|
||||||
-> Custom Scan (Citus Real-Time)
|
-> Custom Scan (Citus Adaptive)
|
||||||
Task Count: 4
|
Task Count: 4
|
||||||
Tasks Shown: One of 4
|
Tasks Shown: One of 4
|
||||||
-> Task
|
-> Task
|
||||||
|
|
@ -874,14 +866,14 @@ EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USIN
|
||||||
Limit
|
Limit
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: remote_scan."time" DESC
|
Sort Key: remote_scan."time" DESC
|
||||||
-> Custom Scan (Citus Real-Time)
|
-> Custom Scan (Citus Adaptive)
|
||||||
-> Distributed Subplan 98_1
|
-> Distributed Subplan 98_1
|
||||||
-> Limit
|
-> Limit
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: max((max(remote_scan.lastseen))) DESC
|
Sort Key: max((max(remote_scan.lastseen))) DESC
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
Group Key: remote_scan.user_id
|
Group Key: remote_scan.user_id
|
||||||
-> Custom Scan (Citus Real-Time)
|
-> Custom Scan (Citus Adaptive)
|
||||||
Task Count: 4
|
Task Count: 4
|
||||||
Tasks Shown: One of 4
|
Tasks Shown: One of 4
|
||||||
-> Task
|
-> Task
|
||||||
|
|
@ -913,7 +905,7 @@ EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USIN
|
||||||
Limit
|
Limit
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: remote_scan."time" DESC
|
Sort Key: remote_scan."time" DESC
|
||||||
-> Custom Scan (Citus Real-Time)
|
-> Custom Scan (Citus Adaptive)
|
||||||
Task Count: 4
|
Task Count: 4
|
||||||
Tasks Shown: One of 4
|
Tasks Shown: One of 4
|
||||||
-> Task
|
-> Task
|
||||||
|
|
|
||||||
|
|
@ -1,949 +0,0 @@
|
||||||
--
|
|
||||||
-- MULTI_VIEW
|
|
||||||
--
|
|
||||||
-- This file contains test cases for view support. It verifies various
|
|
||||||
-- Citus features: simple selects, aggregates, joins, outer joins
|
|
||||||
-- router queries, single row inserts, multi row inserts via insert
|
|
||||||
-- into select, multi row insert via copy commands.
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM lineitem_hash_part;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
12000
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM orders_hash_part;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2985
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- create a view for priority orders
|
|
||||||
CREATE VIEW priority_orders AS SELECT * FROM orders_hash_part WHERE o_orderpriority < '3-MEDIUM';
|
|
||||||
-- aggregate pushdown
|
|
||||||
SELECT o_orderpriority, count(*) FROM priority_orders GROUP BY 1 ORDER BY 2, 1;
|
|
||||||
o_orderpriority | count
|
|
||||||
-----------------+-------
|
|
||||||
2-HIGH | 593
|
|
||||||
1-URGENT | 604
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT o_orderpriority, count(*) FROM orders_hash_part WHERE o_orderpriority < '3-MEDIUM' GROUP BY 1 ORDER BY 2,1;
|
|
||||||
o_orderpriority | count
|
|
||||||
-----------------+-------
|
|
||||||
2-HIGH | 593
|
|
||||||
1-URGENT | 604
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- filters
|
|
||||||
SELECT o_orderpriority, count(*) as all, count(*) FILTER (WHERE o_orderstatus ='F') as fullfilled FROM priority_orders GROUP BY 1 ORDER BY 2, 1;
|
|
||||||
o_orderpriority | all | fullfilled
|
|
||||||
-----------------+-----+------------
|
|
||||||
2-HIGH | 593 | 271
|
|
||||||
1-URGENT | 604 | 280
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- having
|
|
||||||
SELECT o_orderdate, count(*) from priority_orders group by 1 having (count(*) > 3) order by 2 desc, 1 desc;
|
|
||||||
o_orderdate | count
|
|
||||||
-------------+-------
|
|
||||||
08-20-1996 | 5
|
|
||||||
10-10-1994 | 4
|
|
||||||
05-05-1994 | 4
|
|
||||||
04-07-1994 | 4
|
|
||||||
03-17-1993 | 4
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- having with filters
|
|
||||||
SELECT o_orderdate, count(*) as all, count(*) FILTER(WHERE o_orderstatus = 'F') from priority_orders group by 1 having (count(*) > 3) order by 2 desc, 1 desc;
|
|
||||||
o_orderdate | all | count
|
|
||||||
-------------+-----+-------
|
|
||||||
08-20-1996 | 5 | 0
|
|
||||||
10-10-1994 | 4 | 4
|
|
||||||
05-05-1994 | 4 | 4
|
|
||||||
04-07-1994 | 4 | 4
|
|
||||||
03-17-1993 | 4 | 4
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- limit
|
|
||||||
SELECT o_orderkey, o_totalprice from orders_hash_part order by 2 desc, 1 asc limit 5 ;
|
|
||||||
o_orderkey | o_totalprice
|
|
||||||
------------+--------------
|
|
||||||
4421 | 401055.62
|
|
||||||
10209 | 400191.77
|
|
||||||
11142 | 395039.05
|
|
||||||
14179 | 384265.43
|
|
||||||
11296 | 378166.33
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
SELECT o_orderkey, o_totalprice from priority_orders order by 2 desc, 1 asc limit 1 ;
|
|
||||||
o_orderkey | o_totalprice
|
|
||||||
------------+--------------
|
|
||||||
14179 | 384265.43
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE VIEW priority_lineitem AS SELECT li.* FROM lineitem_hash_part li JOIN priority_orders ON (l_orderkey = o_orderkey);
|
|
||||||
SELECT l_orderkey, count(*) FROM priority_lineitem GROUP BY 1 ORDER BY 2 DESC, 1 LIMIT 5;
|
|
||||||
l_orderkey | count
|
|
||||||
------------+-------
|
|
||||||
7 | 7
|
|
||||||
225 | 7
|
|
||||||
226 | 7
|
|
||||||
322 | 7
|
|
||||||
326 | 7
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
CREATE VIEW air_shipped_lineitems AS SELECT * FROM lineitem_hash_part WHERE l_shipmode = 'AIR';
|
|
||||||
-- join between view and table
|
|
||||||
SELECT count(*) FROM orders_hash_part join air_shipped_lineitems ON (o_orderkey = l_orderkey);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- join between views
|
|
||||||
SELECT count(*) FROM priority_orders join air_shipped_lineitems ON (o_orderkey = l_orderkey);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
700
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- count distinct on partition column is supported
|
|
||||||
SELECT count(distinct o_orderkey) FROM priority_orders join air_shipped_lineitems ON (o_orderkey = l_orderkey);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
551
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- count distinct on non-partition column is supported
|
|
||||||
SELECT count(distinct o_orderpriority) FROM priority_orders join air_shipped_lineitems ON (o_orderkey = l_orderkey);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- count distinct on partition column is supported on router queries
|
|
||||||
SELECT count(distinct o_orderkey) FROM priority_orders join air_shipped_lineitems
|
|
||||||
ON (o_orderkey = l_orderkey)
|
|
||||||
WHERE (o_orderkey = 231);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- select distinct on router joins of views also works
|
|
||||||
SELECT distinct(o_orderkey) FROM priority_orders join air_shipped_lineitems
|
|
||||||
ON (o_orderkey = l_orderkey)
|
|
||||||
WHERE (o_orderkey = 231);
|
|
||||||
o_orderkey
|
|
||||||
------------
|
|
||||||
231
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- left join support depends on flattening of the query
|
|
||||||
SELECT o_orderkey, l_orderkey FROM priority_orders left join air_shipped_lineitems ON (o_orderkey = l_orderkey) ORDER BY o_orderkey LIMIT 1;
|
|
||||||
o_orderkey | l_orderkey
|
|
||||||
------------+------------
|
|
||||||
2 |
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- however, this works
|
|
||||||
SELECT count(*) FROM priority_orders left join lineitem_hash_part ON (o_orderkey = l_orderkey) WHERE l_shipmode ='AIR';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
700
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- view on the inner side is supported
|
|
||||||
SELECT count(*) FROM priority_orders right join lineitem_hash_part ON (o_orderkey = l_orderkey) WHERE l_shipmode ='AIR';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- view on the outer side is supported
|
|
||||||
SELECT count(*) FROM lineitem_hash_part right join priority_orders ON (o_orderkey = l_orderkey) WHERE l_shipmode ='AIR';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
700
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- left join on router query is supported
|
|
||||||
SELECT o_orderkey, l_linenumber FROM priority_orders left join air_shipped_lineitems ON (o_orderkey = l_orderkey)
|
|
||||||
WHERE o_orderkey = 2;
|
|
||||||
o_orderkey | l_linenumber
|
|
||||||
------------+--------------
|
|
||||||
2 |
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- repartition query on view join
|
|
||||||
-- it passes planning, fails at execution stage
|
|
||||||
SET client_min_messages TO DEBUG1;
|
|
||||||
SELECT * FROM priority_orders JOIN air_shipped_lineitems ON (o_custkey = l_suppkey) ORDER BY o_orderkey DESC, o_custkey DESC, o_orderpriority DESC LIMIT 5;
|
|
||||||
DEBUG: generating subplan 22_1 for subquery SELECT lineitem_hash_part.l_orderkey, lineitem_hash_part.l_partkey, lineitem_hash_part.l_suppkey, lineitem_hash_part.l_linenumber, lineitem_hash_part.l_quantity, lineitem_hash_part.l_extendedprice, lineitem_hash_part.l_discount, lineitem_hash_part.l_tax, lineitem_hash_part.l_returnflag, lineitem_hash_part.l_linestatus, lineitem_hash_part.l_shipdate, lineitem_hash_part.l_commitdate, lineitem_hash_part.l_receiptdate, lineitem_hash_part.l_shipinstruct, lineitem_hash_part.l_shipmode, lineitem_hash_part.l_comment FROM public.lineitem_hash_part WHERE (lineitem_hash_part.l_shipmode OPERATOR(pg_catalog.=) 'AIR'::bpchar)
|
|
||||||
DEBUG: Plan 22 query after replacing subqueries and CTEs: SELECT priority_orders.o_orderkey, priority_orders.o_custkey, priority_orders.o_orderstatus, priority_orders.o_totalprice, priority_orders.o_orderdate, priority_orders.o_orderpriority, priority_orders.o_clerk, priority_orders.o_shippriority, priority_orders.o_comment, air_shipped_lineitems.l_orderkey, air_shipped_lineitems.l_partkey, air_shipped_lineitems.l_suppkey, air_shipped_lineitems.l_linenumber, air_shipped_lineitems.l_quantity, air_shipped_lineitems.l_extendedprice, air_shipped_lineitems.l_discount, air_shipped_lineitems.l_tax, air_shipped_lineitems.l_returnflag, air_shipped_lineitems.l_linestatus, air_shipped_lineitems.l_shipdate, air_shipped_lineitems.l_commitdate, air_shipped_lineitems.l_receiptdate, air_shipped_lineitems.l_shipinstruct, air_shipped_lineitems.l_shipmode, air_shipped_lineitems.l_comment FROM ((SELECT orders_hash_part.o_orderkey, orders_hash_part.o_custkey, orders_hash_part.o_orderstatus, orders_hash_part.o_totalprice, orders_hash_part.o_orderdate, orders_hash_part.o_orderpriority, orders_hash_part.o_clerk, orders_hash_part.o_shippriority, orders_hash_part.o_comment FROM public.orders_hash_part WHERE (orders_hash_part.o_orderpriority OPERATOR(pg_catalog.<) '3-MEDIUM'::bpchar)) priority_orders JOIN (SELECT intermediate_result.l_orderkey, intermediate_result.l_partkey, intermediate_result.l_suppkey, intermediate_result.l_linenumber, intermediate_result.l_quantity, intermediate_result.l_extendedprice, intermediate_result.l_discount, intermediate_result.l_tax, intermediate_result.l_returnflag, intermediate_result.l_linestatus, intermediate_result.l_shipdate, intermediate_result.l_commitdate, intermediate_result.l_receiptdate, intermediate_result.l_shipinstruct, intermediate_result.l_shipmode, intermediate_result.l_comment FROM read_intermediate_result('22_1'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint, l_partkey integer, l_suppkey integer, l_linenumber integer, l_quantity numeric(15,2), l_extendedprice numeric(15,2), l_discount numeric(15,2), l_tax numeric(15,2), l_returnflag character(1), l_linestatus character(1), l_shipdate date, l_commitdate date, l_receiptdate date, l_shipinstruct character(25), l_shipmode character(10), l_comment character varying(44))) air_shipped_lineitems ON ((priority_orders.o_custkey OPERATOR(pg_catalog.=) air_shipped_lineitems.l_suppkey))) ORDER BY priority_orders.o_orderkey DESC, priority_orders.o_custkey DESC, priority_orders.o_orderpriority DESC LIMIT 5
|
|
||||||
DEBUG: push down of limit count: 5
|
|
||||||
o_orderkey | o_custkey | o_orderstatus | o_totalprice | o_orderdate | o_orderpriority | o_clerk | o_shippriority | o_comment | l_orderkey | l_partkey | l_suppkey | l_linenumber | l_quantity | l_extendedprice | l_discount | l_tax | l_returnflag | l_linestatus | l_shipdate | l_commitdate | l_receiptdate | l_shipinstruct | l_shipmode | l_comment
|
|
||||||
------------+-----------+---------------+--------------+-------------+-----------------+-----------------+----------------+-------------------------------------------------------+------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+------------+--------------+---------------+---------------------------+------------+-------------------------------------------
|
|
||||||
14821 | 1435 | O | 322002.95 | 06-12-1998 | 2-HIGH | Clerk#000000630 | 0 | n packages are furiously ironic ideas. d | 1607 | 118923 | 1435 | 2 | 37.00 | 71851.04 | 0.05 | 0.02 | N | O | 02-27-1996 | 02-18-1996 | 03-16-1996 | NONE | AIR | alongside
|
|
||||||
14790 | 613 | O | 270163.54 | 08-21-1996 | 2-HIGH | Clerk#000000347 | 0 | p. regular deposits wake. final n | 2629 | 123076 | 613 | 2 | 31.00 | 34071.17 | 0.08 | 0.03 | N | O | 05-24-1998 | 05-26-1998 | 06-10-1998 | COLLECT COD | AIR | ate blithely bold, regular deposits. bold
|
|
||||||
14758 | 1225 | F | 37812.49 | 10-27-1993 | 2-HIGH | Clerk#000000687 | 0 | ages nag about the furio | 9156 | 176190 | 1225 | 2 | 22.00 | 27856.18 | 0.03 | 0.00 | R | F | 02-08-1994 | 04-01-1994 | 02-24-1994 | DELIVER IN PERSON | AIR | equests dete
|
|
||||||
14725 | 569 | O | 261801.45 | 06-17-1995 | 2-HIGH | Clerk#000000177 | 0 | ng asymptotes. final, ironic accounts cajole after | 14688 | 173017 | 569 | 3 | 10.00 | 10900.10 | 0.02 | 0.08 | N | O | 03-14-1997 | 04-22-1997 | 04-05-1997 | COLLECT COD | AIR | riously even packages sleep a
|
|
||||||
14657 | 370 | F | 116160.53 | 02-28-1994 | 1-URGENT | Clerk#000000756 | 0 | ly across the ironic, ironic instructions. bold ideas | 5153 | 67863 | 370 | 3 | 30.00 | 54925.80 | 0.09 | 0.01 | N | O | 11-10-1995 | 11-14-1995 | 11-16-1995 | DELIVER IN PERSON | AIR | beans sleep bl
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
RESET client_min_messages;
|
|
||||||
SELECT count(*) FROM priority_orders JOIN air_shipped_lineitems ON (o_custkey = l_suppkey);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
192
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- materialized views work
|
|
||||||
-- insert into... select works with views
|
|
||||||
CREATE TABLE temp_lineitem(LIKE lineitem_hash_part);
|
|
||||||
SELECT create_distributed_table('temp_lineitem', 'l_orderkey', 'hash', 'lineitem_hash_part');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems;
|
|
||||||
SELECT count(*) FROM temp_lineitem;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- following is a where false query, should not be inserting anything
|
|
||||||
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems WHERE l_shipmode = 'MAIL';
|
|
||||||
SELECT count(*) FROM temp_lineitem;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- can create and query materialized views
|
|
||||||
CREATE MATERIALIZED VIEW mode_counts
|
|
||||||
AS SELECT l_shipmode, count(*) FROM temp_lineitem GROUP BY l_shipmode;
|
|
||||||
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
||||||
l_shipmode | count
|
|
||||||
------------+-------
|
|
||||||
AIR | 1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- materialized views are local, cannot join with distributed tables
|
|
||||||
SELECT count(*) FROM mode_counts JOIN temp_lineitem USING (l_shipmode);
|
|
||||||
ERROR: relation mode_counts is not distributed
|
|
||||||
-- new data is not immediately reflected in the view
|
|
||||||
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems;
|
|
||||||
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
||||||
l_shipmode | count
|
|
||||||
------------+-------
|
|
||||||
AIR | 1706
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- refresh updates the materialised view with new data
|
|
||||||
REFRESH MATERIALIZED VIEW mode_counts;
|
|
||||||
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
||||||
l_shipmode | count
|
|
||||||
------------+-------
|
|
||||||
AIR | 3412
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP MATERIALIZED VIEW mode_counts;
|
|
||||||
SET citus.task_executor_type to "task-tracker";
|
|
||||||
-- single view repartition subqueries are not supported
|
|
||||||
SELECT l_suppkey, count(*) FROM
|
|
||||||
(SELECT l_suppkey, l_shipdate, count(*)
|
|
||||||
FROM air_shipped_lineitems GROUP BY l_suppkey, l_shipdate) supps
|
|
||||||
GROUP BY l_suppkey ORDER BY 2 DESC, 1 LIMIT 5;
|
|
||||||
ERROR: cannot perform distributed planning on this query
|
|
||||||
DETAIL: Subqueries without group by clause are not supported yet
|
|
||||||
-- logically same query without a view works fine
|
|
||||||
SELECT l_suppkey, count(*) FROM
|
|
||||||
(SELECT l_suppkey, l_shipdate, count(*)
|
|
||||||
FROM lineitem_hash_part WHERE l_shipmode = 'AIR' GROUP BY l_suppkey, l_shipdate) supps
|
|
||||||
GROUP BY l_suppkey ORDER BY 2 DESC, 1 LIMIT 5;
|
|
||||||
l_suppkey | count
|
|
||||||
-----------+-------
|
|
||||||
7680 | 4
|
|
||||||
160 | 3
|
|
||||||
1042 | 3
|
|
||||||
1318 | 3
|
|
||||||
5873 | 3
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- when a view is replaced by actual query it still fails
|
|
||||||
SELECT l_suppkey, count(*) FROM
|
|
||||||
(SELECT l_suppkey, l_shipdate, count(*)
|
|
||||||
FROM (SELECT * FROM lineitem_hash_part WHERE l_shipmode = 'AIR') asi
|
|
||||||
GROUP BY l_suppkey, l_shipdate) supps
|
|
||||||
GROUP BY l_suppkey ORDER BY 2 DESC, 1 LIMIT 5;
|
|
||||||
ERROR: cannot perform distributed planning on this query
|
|
||||||
DETAIL: Subqueries without group by clause are not supported yet
|
|
||||||
-- repartition query on view with single table subquery
|
|
||||||
CREATE VIEW supp_count_view AS SELECT * FROM (SELECT l_suppkey, count(*) FROM lineitem_hash_part GROUP BY 1) s1;
|
|
||||||
SELECT * FROM supp_count_view ORDER BY 2 DESC, 1 LIMIT 10;
|
|
||||||
l_suppkey | count
|
|
||||||
-----------+-------
|
|
||||||
6104 | 8
|
|
||||||
1868 | 6
|
|
||||||
5532 | 6
|
|
||||||
5849 | 6
|
|
||||||
6169 | 6
|
|
||||||
6669 | 6
|
|
||||||
6692 | 6
|
|
||||||
7703 | 6
|
|
||||||
7869 | 6
|
|
||||||
8426 | 6
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
SET citus.task_executor_type to DEFAULT;
|
|
||||||
-- create a view with aggregate
|
|
||||||
CREATE VIEW lineitems_by_shipping_method AS
|
|
||||||
SELECT l_shipmode, count(*) as cnt FROM lineitem_hash_part GROUP BY 1;
|
|
||||||
-- following will be supported via recursive planning
|
|
||||||
SELECT * FROM lineitems_by_shipping_method ORDER BY 1,2 LIMIT 5;
|
|
||||||
l_shipmode | cnt
|
|
||||||
------------+------
|
|
||||||
AIR | 1706
|
|
||||||
FOB | 1709
|
|
||||||
MAIL | 1739
|
|
||||||
RAIL | 1706
|
|
||||||
REG AIR | 1679
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- create a view with group by on partition column
|
|
||||||
CREATE VIEW lineitems_by_orderkey AS
|
|
||||||
SELECT
|
|
||||||
l_orderkey, count(*)
|
|
||||||
FROM
|
|
||||||
lineitem_hash_part
|
|
||||||
GROUP BY 1;
|
|
||||||
-- this should work since we're able to push down this query
|
|
||||||
SELECT * FROM lineitems_by_orderkey ORDER BY 2 DESC, 1 ASC LIMIT 10;
|
|
||||||
l_orderkey | count
|
|
||||||
------------+-------
|
|
||||||
7 | 7
|
|
||||||
68 | 7
|
|
||||||
129 | 7
|
|
||||||
164 | 7
|
|
||||||
194 | 7
|
|
||||||
225 | 7
|
|
||||||
226 | 7
|
|
||||||
322 | 7
|
|
||||||
326 | 7
|
|
||||||
354 | 7
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
-- it would also work since it is made router plannable
|
|
||||||
SELECT * FROM lineitems_by_orderkey WHERE l_orderkey = 100;
|
|
||||||
l_orderkey | count
|
|
||||||
------------+-------
|
|
||||||
100 | 5
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP TABLE temp_lineitem CASCADE;
|
|
||||||
DROP VIEW supp_count_view;
|
|
||||||
DROP VIEW lineitems_by_orderkey;
|
|
||||||
DROP VIEW lineitems_by_shipping_method;
|
|
||||||
DROP VIEW air_shipped_lineitems;
|
|
||||||
DROP VIEW priority_lineitem;
|
|
||||||
DROP VIEW priority_orders;
|
|
||||||
-- new tests for real time use case including views and subqueries
|
|
||||||
-- create view to display recent user who has an activity after a timestamp
|
|
||||||
CREATE VIEW recent_users AS
|
|
||||||
SELECT user_id, max(time) as lastseen FROM users_table
|
|
||||||
GROUP BY user_id
|
|
||||||
HAVING max(time) > '2017-11-23 16:20:33.264457'::timestamp order by 2 DESC;
|
|
||||||
SELECT * FROM recent_users ORDER BY 2 DESC, 1 DESC;
|
|
||||||
user_id | lastseen
|
|
||||||
---------+---------------------------------
|
|
||||||
1 | Thu Nov 23 17:30:34.635085 2017
|
|
||||||
3 | Thu Nov 23 17:18:51.048758 2017
|
|
||||||
5 | Thu Nov 23 16:48:32.08896 2017
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- create a view for recent_events
|
|
||||||
CREATE VIEW recent_events AS
|
|
||||||
SELECT user_id, time FROM events_table
|
|
||||||
WHERE time > '2017-11-23 16:20:33.264457'::timestamp;
|
|
||||||
SELECT count(*) FROM recent_events;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
6
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- count number of events of recent_users
|
|
||||||
SELECT count(*) FROM recent_users ru JOIN events_table et ON (ru.user_id = et.user_id);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
50
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- count number of events of per recent users order by count
|
|
||||||
SELECT ru.user_id, count(*)
|
|
||||||
FROM recent_users ru
|
|
||||||
JOIN events_table et
|
|
||||||
ON (ru.user_id = et.user_id)
|
|
||||||
GROUP BY ru.user_id
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | count
|
|
||||||
---------+-------
|
|
||||||
3 | 21
|
|
||||||
1 | 15
|
|
||||||
5 | 14
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- the same query with a left join however, it would still generate the same result
|
|
||||||
SELECT ru.user_id, count(*)
|
|
||||||
FROM recent_users ru
|
|
||||||
LEFT JOIN events_table et
|
|
||||||
ON (ru.user_id = et.user_id)
|
|
||||||
GROUP BY ru.user_id
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | count
|
|
||||||
---------+-------
|
|
||||||
3 | 21
|
|
||||||
1 | 15
|
|
||||||
5 | 14
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- query wrapped inside a subquery, it needs another top level order by
|
|
||||||
SELECT * FROM
|
|
||||||
(SELECT ru.user_id, count(*)
|
|
||||||
FROM recent_users ru
|
|
||||||
JOIN events_table et
|
|
||||||
ON (ru.user_id = et.user_id)
|
|
||||||
GROUP BY ru.user_id
|
|
||||||
ORDER BY 2 DESC, 1) s1
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | count
|
|
||||||
---------+-------
|
|
||||||
3 | 21
|
|
||||||
1 | 15
|
|
||||||
5 | 14
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- non-partition key joins are supported inside subquery
|
|
||||||
-- via pull-push execution
|
|
||||||
SELECT * FROM
|
|
||||||
(SELECT ru.user_id, count(*)
|
|
||||||
FROM recent_users ru
|
|
||||||
JOIN events_table et
|
|
||||||
ON (ru.user_id = et.event_type)
|
|
||||||
GROUP BY ru.user_id
|
|
||||||
ORDER BY 2 DESC, 1) s1
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | count
|
|
||||||
---------+-------
|
|
||||||
1 | 24
|
|
||||||
3 | 23
|
|
||||||
5 | 7
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- join between views
|
|
||||||
-- recent users who has an event in recent events
|
|
||||||
SELECT ru.user_id FROM recent_users ru JOIN recent_events re USING(user_id) GROUP BY ru.user_id ORDER BY ru.user_id;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
3
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- outer join inside a subquery
|
|
||||||
-- recent_events who are not done by recent users
|
|
||||||
SELECT count(*) FROM (
|
|
||||||
SELECT re.*, ru.user_id AS recent_user
|
|
||||||
FROM recent_events re LEFT JOIN recent_users ru USING(user_id)) reu
|
|
||||||
WHERE recent_user IS NULL;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- same query with anti-join
|
|
||||||
SELECT count(*)
|
|
||||||
FROM recent_events re LEFT JOIN recent_users ru ON(ru.user_id = re.user_id)
|
|
||||||
WHERE ru.user_id IS NULL;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- join between view and table
|
|
||||||
-- users who has recent activity and they have an entry with value_1 is less than 3
|
|
||||||
SELECT ut.* FROM recent_users ru JOIN users_table ut USING (user_id) WHERE ut.value_1 < 3 ORDER BY 1,2;
|
|
||||||
user_id | time | value_1 | value_2 | value_3 | value_4
|
|
||||||
---------+---------------------------------+---------+---------+---------+---------
|
|
||||||
1 | Thu Nov 23 09:26:42.145043 2017 | 1 | 3 | 3 |
|
|
||||||
3 | Wed Nov 22 18:43:51.450263 2017 | 1 | 1 | 4 |
|
|
||||||
3 | Wed Nov 22 20:43:31.008625 2017 | 1 | 3 | 2 |
|
|
||||||
3 | Thu Nov 23 00:15:45.610845 2017 | 1 | 1 | 4 |
|
|
||||||
3 | Thu Nov 23 03:23:24.702501 2017 | 1 | 2 | 5 |
|
|
||||||
3 | Thu Nov 23 06:20:05.854857 2017 | 1 | 4 | 2 |
|
|
||||||
3 | Thu Nov 23 09:57:41.540228 2017 | 2 | 2 | 3 |
|
|
||||||
3 | Thu Nov 23 11:18:53.114408 2017 | 2 | 2 | 0 |
|
|
||||||
3 | Thu Nov 23 12:56:49.29191 2017 | 0 | 5 | 1 |
|
|
||||||
3 | Thu Nov 23 17:18:51.048758 2017 | 1 | 5 | 5 |
|
|
||||||
5 | Wed Nov 22 20:43:18.667473 2017 | 0 | 3 | 2 |
|
|
||||||
5 | Wed Nov 22 21:02:07.575129 2017 | 2 | 0 | 2 |
|
|
||||||
5 | Wed Nov 22 22:10:24.315371 2017 | 1 | 2 | 1 |
|
|
||||||
5 | Thu Nov 23 00:54:44.192608 2017 | 1 | 3 | 2 |
|
|
||||||
5 | Thu Nov 23 07:47:09.542999 2017 | 1 | 4 | 3 |
|
|
||||||
5 | Thu Nov 23 09:05:08.53142 2017 | 2 | 2 | 2 |
|
|
||||||
5 | Thu Nov 23 09:17:47.706703 2017 | 2 | 5 | 3 |
|
|
||||||
5 | Thu Nov 23 10:15:31.764558 2017 | 2 | 2 | 2 |
|
|
||||||
5 | Thu Nov 23 14:29:02.557934 2017 | 2 | 1 | 2 |
|
|
||||||
5 | Thu Nov 23 15:55:08.493462 2017 | 0 | 3 | 3 |
|
|
||||||
5 | Thu Nov 23 16:28:38.455322 2017 | 2 | 5 | 4 |
|
|
||||||
(21 rows)
|
|
||||||
|
|
||||||
-- determine if a recent user has done a given event type or not
|
|
||||||
SELECT ru.user_id, CASE WHEN et.user_id IS NULL THEN 'NO' ELSE 'YES' END as done_event
|
|
||||||
FROM recent_users ru
|
|
||||||
LEFT JOIN events_table et
|
|
||||||
ON(ru.user_id = et.user_id AND et.event_type = 6)
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | done_event
|
|
||||||
---------+------------
|
|
||||||
1 | YES
|
|
||||||
3 | NO
|
|
||||||
5 | NO
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- view vs table join wrapped inside a subquery
|
|
||||||
SELECT * FROM
|
|
||||||
(SELECT ru.user_id, CASE WHEN et.user_id IS NULL THEN 'NO' ELSE 'YES' END as done_event
|
|
||||||
FROM recent_users ru
|
|
||||||
LEFT JOIN events_table et
|
|
||||||
ON(ru.user_id = et.user_id AND et.event_type = 6)
|
|
||||||
) s1
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
user_id | done_event
|
|
||||||
---------+------------
|
|
||||||
1 | YES
|
|
||||||
3 | NO
|
|
||||||
5 | NO
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- event vs table non-partition-key join is not supported
|
|
||||||
-- given that we cannot recursively plan tables yet
|
|
||||||
SELECT * FROM
|
|
||||||
(SELECT ru.user_id, CASE WHEN et.user_id IS NULL THEN 'NO' ELSE 'YES' END as done_event
|
|
||||||
FROM recent_users ru
|
|
||||||
LEFT JOIN events_table et
|
|
||||||
ON(ru.user_id = et.event_type)
|
|
||||||
) s1
|
|
||||||
ORDER BY 2 DESC, 1;
|
|
||||||
ERROR: cannot pushdown the subquery
|
|
||||||
DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join
|
|
||||||
-- create a select only view
|
|
||||||
CREATE VIEW selected_users AS SELECT * FROM users_table WHERE value_1 >= 1 and value_1 <3;
|
|
||||||
CREATE VIEW recent_selected_users AS SELECT su.* FROM selected_users su JOIN recent_users ru USING(user_id);
|
|
||||||
SELECT user_id FROM recent_selected_users GROUP BY 1 ORDER BY 1;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
3
|
|
||||||
5
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- this would be supported when we implement where partition_key in (subquery) support
|
|
||||||
SELECT et.user_id, et.time FROM events_table et WHERE et.user_id IN (SELECT user_id FROM recent_selected_users) GROUP BY 1,2 ORDER BY 1 DESC,2 DESC LIMIT 5;
|
|
||||||
user_id | time
|
|
||||||
---------+---------------------------------
|
|
||||||
5 | Thu Nov 23 16:11:02.929469 2017
|
|
||||||
5 | Thu Nov 23 14:40:40.467511 2017
|
|
||||||
5 | Thu Nov 23 14:28:51.833214 2017
|
|
||||||
5 | Thu Nov 23 14:23:09.889786 2017
|
|
||||||
5 | Thu Nov 23 13:26:45.571108 2017
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- it is supported when it is a router query
|
|
||||||
SELECT count(*) FROM events_table et WHERE et.user_id IN (SELECT user_id FROM recent_selected_users WHERE user_id = 1);
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
15
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- union between views is supported through recursive planning
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION
|
|
||||||
(SELECT user_id FROM selected_users)
|
|
||||||
ORDER BY 1;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
6
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
-- wrapping it inside a SELECT * works
|
|
||||||
SELECT *
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION
|
|
||||||
(SELECT user_id FROM selected_users) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0
|
|
||||||
ORDER BY user_id;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- union all also works for views
|
|
||||||
SELECT *
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION ALL
|
|
||||||
(SELECT user_id FROM selected_users) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0
|
|
||||||
ORDER BY user_id;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
1
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT count(*)
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION
|
|
||||||
(SELECT user_id FROM selected_users) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- UNION ALL between views is supported through recursive planning
|
|
||||||
SELECT count(*)
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION ALL
|
|
||||||
(SELECT user_id FROM selected_users) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- expand view definitions and re-run last 2 queries
|
|
||||||
SELECT count(*)
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM (SELECT user_id, max(time) as lastseen FROM users_table
|
|
||||||
GROUP BY user_id
|
|
||||||
HAVING max(time) > '2017-11-22 05:45:49.978738'::timestamp order by 2 DESC) aa
|
|
||||||
)
|
|
||||||
UNION
|
|
||||||
(SELECT user_id FROM (SELECT * FROM users_table WHERE value_1 >= 1 and value_1 < 3) bb) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*)
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM (SELECT user_id, max(time) as lastseen FROM users_table
|
|
||||||
GROUP BY user_id
|
|
||||||
HAVING max(time) > '2017-11-22 05:45:49.978738'::timestamp order by 2 DESC) aa
|
|
||||||
)
|
|
||||||
UNION ALL
|
|
||||||
(SELECT user_id FROM (SELECT * FROM users_table WHERE value_1 >= 1 and value_1 < 3) bb) ) u
|
|
||||||
WHERE user_id < 2 AND user_id > 0;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- test distinct
|
|
||||||
-- distinct is supported if it is on a partition key
|
|
||||||
CREATE VIEW distinct_user_with_value_1_3 AS SELECT DISTINCT user_id FROM users_table WHERE value_1 = 3;
|
|
||||||
SELECT * FROM distinct_user_with_value_1_3 ORDER BY user_id;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
6
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
-- distinct is not supported if it is on a non-partition key
|
|
||||||
-- but will be supported via recursive planning
|
|
||||||
CREATE VIEW distinct_value_1 AS SELECT DISTINCT value_1 FROM users_table WHERE value_2 = 3;
|
|
||||||
SELECT * FROM distinct_value_1 ORDER BY 1 DESC LIMIT 5;
|
|
||||||
value_1
|
|
||||||
---------
|
|
||||||
5
|
|
||||||
4
|
|
||||||
3
|
|
||||||
2
|
|
||||||
1
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- CTEs are supported even if they are on views
|
|
||||||
CREATE VIEW cte_view_1 AS
|
|
||||||
WITH c1 AS (SELECT * FROM users_table WHERE value_1 = 3) SELECT * FROM c1 WHERE value_2 < 4 AND EXISTS (SELECT * FROM c1);
|
|
||||||
SELECT * FROM cte_view_1 ORDER BY 1,2,3,4,5 LIMIT 5;
|
|
||||||
user_id | time | value_1 | value_2 | value_3 | value_4
|
|
||||||
---------+---------------------------------+---------+---------+---------+---------
|
|
||||||
1 | Thu Nov 23 03:32:50.803031 2017 | 3 | 2 | 1 |
|
|
||||||
2 | Thu Nov 23 13:52:54.83829 2017 | 3 | 1 | 4 |
|
|
||||||
3 | Wed Nov 22 23:24:32.080584 2017 | 3 | 2 | 5 |
|
|
||||||
4 | Wed Nov 22 23:59:46.493416 2017 | 3 | 1 | 3 |
|
|
||||||
4 | Thu Nov 23 01:55:21.824618 2017 | 3 | 1 | 4 |
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- this is single shard query and still not supported since it has view + cte
|
|
||||||
-- router planner can't detect it
|
|
||||||
SELECT * FROM cte_view_1 WHERE user_id = 2 ORDER BY 1,2,3,4,5;
|
|
||||||
user_id | time | value_1 | value_2 | value_3 | value_4
|
|
||||||
---------+--------------------------------+---------+---------+---------+---------
|
|
||||||
2 | Thu Nov 23 13:52:54.83829 2017 | 3 | 1 | 4 |
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- if CTE itself prunes down to a single shard than the view is supported (router plannable)
|
|
||||||
CREATE VIEW cte_view_2 AS
|
|
||||||
WITH c1 AS (SELECT * FROM users_table WHERE user_id = 2) SELECT * FROM c1 WHERE value_1 = 3;
|
|
||||||
SELECT * FROM cte_view_2;
|
|
||||||
user_id | time | value_1 | value_2 | value_3 | value_4
|
|
||||||
---------+---------------------------------+---------+---------+---------+---------
|
|
||||||
2 | Thu Nov 23 00:19:14.138058 2017 | 3 | 4 | 0 |
|
|
||||||
2 | Thu Nov 23 13:52:54.83829 2017 | 3 | 1 | 4 |
|
|
||||||
2 | Wed Nov 22 18:19:49.944985 2017 | 3 | 5 | 1 |
|
|
||||||
2 | Thu Nov 23 11:41:04.042936 2017 | 3 | 4 | 1 |
|
|
||||||
(4 rows)
|
|
||||||
|
|
||||||
CREATE VIEW router_view AS SELECT * FROM users_table WHERE user_id = 2;
|
|
||||||
-- router plannable
|
|
||||||
SELECT user_id FROM router_view GROUP BY 1;
|
|
||||||
user_id
|
|
||||||
---------
|
|
||||||
2
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- join a router view
|
|
||||||
SELECT * FROM (SELECT user_id FROM router_view GROUP BY 1) rv JOIN recent_events USING (user_id) ORDER BY 2 LIMIT 3;
|
|
||||||
user_id | time
|
|
||||||
---------+---------------------------------
|
|
||||||
2 | Thu Nov 23 17:26:14.563216 2017
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT * FROM (SELECT user_id FROM router_view GROUP BY 1) rv JOIN (SELECT * FROM recent_events) re USING (user_id) ORDER BY 2 LIMIT 3;
|
|
||||||
user_id | time
|
|
||||||
---------+---------------------------------
|
|
||||||
2 | Thu Nov 23 17:26:14.563216 2017
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- views with limits
|
|
||||||
CREATE VIEW recent_10_users AS
|
|
||||||
SELECT user_id, max(time) as lastseen FROM users_table
|
|
||||||
GROUP BY user_id
|
|
||||||
ORDER BY lastseen DESC
|
|
||||||
LIMIT 10;
|
|
||||||
-- this is not supported since it has limit in it and subquery_pushdown is not set
|
|
||||||
SELECT * FROM recent_10_users;
|
|
||||||
user_id | lastseen
|
|
||||||
---------+---------------------------------
|
|
||||||
1 | Thu Nov 23 17:30:34.635085 2017
|
|
||||||
3 | Thu Nov 23 17:18:51.048758 2017
|
|
||||||
5 | Thu Nov 23 16:48:32.08896 2017
|
|
||||||
4 | Thu Nov 23 15:32:02.360969 2017
|
|
||||||
6 | Thu Nov 23 14:43:18.024104 2017
|
|
||||||
2 | Thu Nov 23 13:52:54.83829 2017
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
SET citus.subquery_pushdown to ON;
|
|
||||||
-- still not supported since outer query does not have limit
|
|
||||||
-- it shows a different (subquery with single relation) error message
|
|
||||||
SELECT * FROM recent_10_users;
|
|
||||||
ERROR: cannot perform distributed planning on this query
|
|
||||||
DETAIL: Subqueries with limit are not supported yet
|
|
||||||
-- now it displays more correct error message
|
|
||||||
SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id);
|
|
||||||
ERROR: cannot push down this subquery
|
|
||||||
DETAIL: Limit in subquery without limit in the outermost query is unsupported
|
|
||||||
-- now both are supported when there is a limit on the outer most query
|
|
||||||
SELECT * FROM recent_10_users ORDER BY lastseen DESC LIMIT 10;
|
|
||||||
user_id | lastseen
|
|
||||||
---------+---------------------------------
|
|
||||||
1 | Thu Nov 23 17:30:34.635085 2017
|
|
||||||
3 | Thu Nov 23 17:18:51.048758 2017
|
|
||||||
5 | Thu Nov 23 16:48:32.08896 2017
|
|
||||||
4 | Thu Nov 23 15:32:02.360969 2017
|
|
||||||
6 | Thu Nov 23 14:43:18.024104 2017
|
|
||||||
2 | Thu Nov 23 13:52:54.83829 2017
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
|
||||||
user_id | time | event_type | value_2 | value_3 | value_4
|
|
||||||
---------+---------------------------------+------------+---------+---------+---------
|
|
||||||
1 | Thu Nov 23 21:54:46.924477 2017 | 6 | 4 | 5 |
|
|
||||||
4 | Thu Nov 23 18:10:21.338399 2017 | 1 | 2 | 4 |
|
|
||||||
3 | Thu Nov 23 18:08:26.550729 2017 | 2 | 4 | 3 |
|
|
||||||
2 | Thu Nov 23 17:26:14.563216 2017 | 1 | 5 | 3 |
|
|
||||||
3 | Thu Nov 23 16:44:41.903713 2017 | 4 | 2 | 2 |
|
|
||||||
3 | Thu Nov 23 16:31:56.219594 2017 | 5 | 1 | 2 |
|
|
||||||
4 | Thu Nov 23 16:20:33.264457 2017 | 0 | 0 | 3 |
|
|
||||||
5 | Thu Nov 23 16:11:02.929469 2017 | 4 | 2 | 0 |
|
|
||||||
2 | Thu Nov 23 15:58:49.273421 2017 | 5 | 1 | 2 |
|
|
||||||
5 | Thu Nov 23 14:40:40.467511 2017 | 1 | 4 | 1 |
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
RESET citus.subquery_pushdown;
|
|
||||||
VACUUM ANALYZE users_table;
|
|
||||||
-- explain tests
|
|
||||||
EXPLAIN (COSTS FALSE) SELECT user_id FROM recent_selected_users GROUP BY 1 ORDER BY 1;
|
|
||||||
QUERY PLAN
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Sort
|
|
||||||
Sort Key: remote_scan.user_id
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: users_table.user_id
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (users_table.user_id = ru.user_id)
|
|
||||||
-> Seq Scan on users_table_1400256 users_table
|
|
||||||
Filter: ((value_1 >= 1) AND (value_1 < 3))
|
|
||||||
-> Hash
|
|
||||||
-> Subquery Scan on ru
|
|
||||||
-> Sort
|
|
||||||
Sort Key: (max(users_table_1."time")) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: users_table_1.user_id
|
|
||||||
Filter: (max(users_table_1."time") > '2017-11-23 16:20:33.264457'::timestamp without time zone)
|
|
||||||
-> Seq Scan on users_table_1400256 users_table_1
|
|
||||||
(23 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE) SELECT *
|
|
||||||
FROM (
|
|
||||||
(SELECT user_id FROM recent_users)
|
|
||||||
UNION
|
|
||||||
(SELECT user_id FROM selected_users) ) u
|
|
||||||
WHERE user_id < 4 AND user_id > 1
|
|
||||||
ORDER BY user_id;
|
|
||||||
QUERY PLAN
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Sort
|
|
||||||
Sort Key: remote_scan.user_id
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Unique
|
|
||||||
-> Sort
|
|
||||||
Sort Key: recent_users.user_id
|
|
||||||
-> Append
|
|
||||||
-> Subquery Scan on recent_users
|
|
||||||
-> Sort
|
|
||||||
Sort Key: (max(users_table."time")) DESC
|
|
||||||
-> GroupAggregate
|
|
||||||
Group Key: users_table.user_id
|
|
||||||
Filter: (max(users_table."time") > '2017-11-23 16:20:33.264457'::timestamp without time zone)
|
|
||||||
-> Sort
|
|
||||||
Sort Key: users_table.user_id
|
|
||||||
-> Seq Scan on users_table_1400256 users_table
|
|
||||||
Filter: ((user_id < 4) AND (user_id > 1))
|
|
||||||
-> Seq Scan on users_table_1400256 users_table_1
|
|
||||||
Filter: ((value_1 >= 1) AND (value_1 < 3) AND (user_id < 4) AND (user_id > 1))
|
|
||||||
(23 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
|
||||||
QUERY PLAN
|
|
||||||
---------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan."time" DESC
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
-> Distributed Subplan 98_1
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: max((max(remote_scan.lastseen))) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: (max("time")) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: user_id
|
|
||||||
-> Seq Scan on users_table_1400256 users_table
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: et."time" DESC
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (intermediate_result.user_id = et.user_id)
|
|
||||||
-> Function Scan on read_intermediate_result intermediate_result
|
|
||||||
-> Hash
|
|
||||||
-> Seq Scan on events_table_1400260 et
|
|
||||||
(33 rows)
|
|
||||||
|
|
||||||
SET citus.subquery_pushdown to ON;
|
|
||||||
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
|
||||||
QUERY PLAN
|
|
||||||
---------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan."time" DESC
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: et."time" DESC
|
|
||||||
-> Hash Join
|
|
||||||
Hash Cond: (et.user_id = recent_10_users.user_id)
|
|
||||||
-> Seq Scan on events_table_1400260 et
|
|
||||||
-> Hash
|
|
||||||
-> Subquery Scan on recent_10_users
|
|
||||||
-> Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: (max(users_table."time")) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: users_table.user_id
|
|
||||||
-> Seq Scan on users_table_1400256 users_table
|
|
||||||
(22 rows)
|
|
||||||
|
|
||||||
RESET citus.subquery_pushdown;
|
|
||||||
DROP VIEW recent_10_users;
|
|
||||||
DROP VIEW router_view;
|
|
||||||
DROP VIEW cte_view_2;
|
|
||||||
DROP VIEW cte_view_1;
|
|
||||||
DROP VIEW distinct_value_1;
|
|
||||||
DROP VIEW distinct_user_with_value_1_3;
|
|
||||||
DROP VIEW recent_selected_users;
|
|
||||||
DROP VIEW selected_users;
|
|
||||||
DROP VIEW recent_events;
|
|
||||||
DROP VIEW recent_users;
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
---
|
---
|
||||||
--- tests around access tracking within transaction blocks
|
--- tests around access tracking within transaction blocks
|
||||||
---
|
---
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 10 AS version_ten_or_above;
|
|
||||||
version_ten_or_above
|
|
||||||
----------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE SCHEMA access_tracking;
|
CREATE SCHEMA access_tracking;
|
||||||
SET search_path TO 'access_tracking';
|
SET search_path TO 'access_tracking';
|
||||||
CREATE OR REPLACE FUNCTION relation_select_access_mode(relationId Oid)
|
CREATE OR REPLACE FUNCTION relation_select_access_mode(relationId Oid)
|
||||||
|
|
@ -417,7 +410,6 @@ BEGIN;
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
-- recursively planned SELECT
|
-- recursively planned SELECT
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -889,7 +881,6 @@ NOTICE: truncate cascades to table "table_2"
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- CTEs with SELECT only should work fine
|
-- CTEs with SELECT only should work fine
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
WITH cte AS (SELECT count(*) FROM table_1)
|
WITH cte AS (SELECT count(*) FROM table_1)
|
||||||
SELECT * FROM cte;
|
SELECT * FROM cte;
|
||||||
count
|
count
|
||||||
|
|
@ -923,7 +914,6 @@ BEGIN;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- modifying CTEs should work fine with multi-row inserts, which are by default in sequential
|
-- modifying CTEs should work fine with multi-row inserts, which are by default in sequential
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
WITH cte_1 AS (INSERT INTO table_1 VALUES (1000,1000), (1001, 1001), (1002, 1002) RETURNING *)
|
WITH cte_1 AS (INSERT INTO table_1 VALUES (1000,1000), (1001, 1001), (1002, 1002) RETURNING *)
|
||||||
SELECT * FROM cte_1 ORDER BY 1;
|
SELECT * FROM cte_1 ORDER BY 1;
|
||||||
key | value
|
key | value
|
||||||
|
|
@ -942,7 +932,6 @@ BEGIN;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- modifying CTEs should work fine with parallel mode
|
-- modifying CTEs should work fine with parallel mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
|
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
|
||||||
SELECT count(*) FROM cte_1 ORDER BY 1;
|
SELECT count(*) FROM cte_1 ORDER BY 1;
|
||||||
count
|
count
|
||||||
|
|
@ -959,7 +948,6 @@ BEGIN;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- modifying CTEs should work fine with sequential mode
|
-- modifying CTEs should work fine with sequential mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
|
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
|
||||||
SELECT count(*) FROM cte_1 ORDER BY 1;
|
SELECT count(*) FROM cte_1 ORDER BY 1;
|
||||||
count
|
count
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,6 @@ CREATE SCHEMA partitioned_table_replicated;
|
||||||
SET search_path TO partitioned_table_replicated;
|
SET search_path TO partitioned_table_replicated;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 2;
|
SET citus.shard_replication_factor TO 2;
|
||||||
-- print major version number for version-specific tests
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int < 11 AS server_version_is_10;
|
|
||||||
server_version_is_10
|
|
||||||
----------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE collections (
|
CREATE TABLE collections (
|
||||||
key bigint,
|
key bigint,
|
||||||
ts timestamptz,
|
ts timestamptz,
|
||||||
|
|
|
||||||
|
|
@ -1,299 +0,0 @@
|
||||||
--
|
|
||||||
-- Distributed Partitioned Table Tests
|
|
||||||
--
|
|
||||||
SET citus.next_shard_id TO 1760000;
|
|
||||||
CREATE SCHEMA partitioned_table_replicated;
|
|
||||||
SET search_path TO partitioned_table_replicated;
|
|
||||||
SET citus.shard_count TO 4;
|
|
||||||
SET citus.shard_replication_factor TO 2;
|
|
||||||
-- print major version number for version-specific tests
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int < 11 AS server_version_is_10;
|
|
||||||
server_version_is_10
|
|
||||||
----------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE collections (
|
|
||||||
key bigint,
|
|
||||||
ts timestamptz,
|
|
||||||
collection_id integer,
|
|
||||||
value numeric
|
|
||||||
) PARTITION BY LIST ( collection_id );
|
|
||||||
CREATE TABLE collections_1
|
|
||||||
PARTITION OF collections (key, ts, collection_id, value)
|
|
||||||
FOR VALUES IN ( 1 );
|
|
||||||
CREATE TABLE collections_2
|
|
||||||
PARTITION OF collections (key, ts, collection_id, value)
|
|
||||||
FOR VALUES IN ( 2 );
|
|
||||||
-- load some data data
|
|
||||||
INSERT INTO collections (key, ts, collection_id, value) VALUES (1, '2009-01-01', 1, 1);
|
|
||||||
INSERT INTO collections (key, ts, collection_id, value) VALUES (2, '2009-01-01', 1, 2);
|
|
||||||
INSERT INTO collections (key, ts, collection_id, value) VALUES (3, '2009-01-01', 2, 1);
|
|
||||||
INSERT INTO collections (key, ts, collection_id, value) VALUES (4, '2009-01-01', 2, 2);
|
|
||||||
-- in the first case, we'll distributed the
|
|
||||||
-- already existing partitioninong hierarcy
|
|
||||||
SELECT create_distributed_table('collections', 'key');
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- now create partition of a already distributed table
|
|
||||||
CREATE TABLE collections_3 PARTITION OF collections FOR VALUES IN ( 3 );
|
|
||||||
-- now attaching non distributed table to a distributed table
|
|
||||||
CREATE TABLE collections_4 AS SELECT * FROM collections LIMIT 0;
|
|
||||||
-- load some data
|
|
||||||
INSERT INTO collections_4 SELECT i, '2009-01-01', 4, i FROM generate_series (0, 10) i;
|
|
||||||
ALTER TABLE collections ATTACH PARTITION collections_4 FOR VALUES IN ( 4 );
|
|
||||||
NOTICE: Copying data from local table...
|
|
||||||
-- finally attach a distributed table to a distributed table
|
|
||||||
CREATE TABLE collections_5 AS SELECT * FROM collections LIMIT 0;
|
|
||||||
SELECT create_distributed_table('collections_5', 'key');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- load some data
|
|
||||||
INSERT INTO collections_5 SELECT i, '2009-01-01', 5, i FROM generate_series (0, 10) i;
|
|
||||||
ALTER TABLE collections ATTACH PARTITION collections_5 FOR VALUES IN ( 5 );
|
|
||||||
-- make sure that we've all the placements
|
|
||||||
SELECT
|
|
||||||
logicalrelid, count(*) as placement_count
|
|
||||||
FROM
|
|
||||||
pg_dist_shard, pg_dist_shard_placement
|
|
||||||
WHERE
|
|
||||||
logicalrelid::text LIKE '%collections%' AND
|
|
||||||
pg_dist_shard.shardid = pg_dist_shard_placement.shardid
|
|
||||||
GROUP BY
|
|
||||||
logicalrelid
|
|
||||||
ORDER BY
|
|
||||||
1,2;
|
|
||||||
logicalrelid | placement_count
|
|
||||||
---------------+-----------------
|
|
||||||
collections | 8
|
|
||||||
collections_1 | 8
|
|
||||||
collections_2 | 8
|
|
||||||
collections_3 | 8
|
|
||||||
collections_4 | 8
|
|
||||||
collections_5 | 8
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
-- and, make sure that all tables are colocated
|
|
||||||
SELECT
|
|
||||||
count(DISTINCT colocationid)
|
|
||||||
FROM
|
|
||||||
pg_dist_partition
|
|
||||||
WHERE
|
|
||||||
logicalrelid::text LIKE '%collections%';
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- make sure that any kind of modification is disallowed on partitions
|
|
||||||
-- given that replication factor > 1
|
|
||||||
INSERT INTO collections_4 (key, ts, collection_id, value) VALUES (4, '2009-01-01', 2, 2);
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- single shard update/delete not allowed
|
|
||||||
UPDATE collections_1 SET ts = now() WHERE key = 1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
DELETE FROM collections_1 WHERE ts = now() AND key = 1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- multi shard update/delete are not allowed
|
|
||||||
UPDATE collections_1 SET ts = now();
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
DELETE FROM collections_1 WHERE ts = now();
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- insert..select pushdown
|
|
||||||
INSERT INTO collections_1 SELECT * FROM collections_1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- insert..select via coordinator
|
|
||||||
INSERT INTO collections_1 SELECT * FROM collections_1 OFFSET 0;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- COPY is not allowed
|
|
||||||
COPY collections_1 FROM STDIN;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
\.
|
|
||||||
invalid command \.
|
|
||||||
-- DDLs are not allowed
|
|
||||||
CREATE INDEX index_on_partition ON collections_1(key);
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- EXPLAIN with modifications is not allowed as well
|
|
||||||
UPDATE collections_1 SET ts = now() WHERE key = 1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- TRUNCATE is also not allowed
|
|
||||||
TRUNCATE collections_1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
TRUNCATE collections, collections_1;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- modifying CTEs are also not allowed
|
|
||||||
WITH collections_5_cte AS
|
|
||||||
(
|
|
||||||
DELETE FROM collections_5 RETURNING *
|
|
||||||
)
|
|
||||||
SELECT * FROM collections_5_cte;
|
|
||||||
ERROR: modifications on partitions when replication factor is greater than 1 is not supported
|
|
||||||
HINT: Run the query on the parent table "collections" instead.
|
|
||||||
-- foreign key creation is disallowed due to replication factor > 1
|
|
||||||
CREATE TABLE fkey_test (key bigint PRIMARY KEY);
|
|
||||||
SELECT create_distributed_table('fkey_test', 'key');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ALTER TABLE
|
|
||||||
collections_5
|
|
||||||
ADD CONSTRAINT
|
|
||||||
fkey_delete FOREIGN KEY(key)
|
|
||||||
REFERENCES
|
|
||||||
fkey_test(key) ON DELETE CASCADE;
|
|
||||||
ERROR: cannot create foreign key constraint
|
|
||||||
DETAIL: Citus Community Edition currently supports foreign key constraints only for "citus.shard_replication_factor = 1".
|
|
||||||
HINT: Please change "citus.shard_replication_factor to 1". To learn more about using foreign keys with other replication factors, please contact us at https://citusdata.com/about/contact_us.
|
|
||||||
-- we should be able to attach and detach partitions
|
|
||||||
-- given that those DDLs are on the parent table
|
|
||||||
CREATE TABLE collections_6
|
|
||||||
PARTITION OF collections (key, ts, collection_id, value)
|
|
||||||
FOR VALUES IN ( 6 );
|
|
||||||
ALTER TABLE collections DETACH PARTITION collections_6;
|
|
||||||
ALTER TABLE collections ATTACH PARTITION collections_6 FOR VALUES IN ( 6 );
|
|
||||||
-- read queries works just fine
|
|
||||||
SELECT count(*) FROM collections_1 WHERE key = 1;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT count(*) FROM collections_1 WHERE key != 1;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- rollups SELECT'ing from partitions should work just fine
|
|
||||||
CREATE TABLE collections_agg (
|
|
||||||
key bigint,
|
|
||||||
sum_value numeric
|
|
||||||
);
|
|
||||||
SELECT create_distributed_table('collections_agg', 'key');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- pushdown roll-up
|
|
||||||
INSERT INTO collections_agg SELECT key, sum(key) FROM collections_1 GROUP BY key;
|
|
||||||
-- coordinator roll-up
|
|
||||||
INSERT INTO collections_agg SELECT collection_id, sum(key) FROM collections_1 GROUP BY collection_id;
|
|
||||||
-- now make sure that repair functionality works fine
|
|
||||||
-- create a table and create its distribution metadata
|
|
||||||
CREATE TABLE customer_engagements (id integer, event_id int) PARTITION BY LIST ( event_id );
|
|
||||||
CREATE TABLE customer_engagements_1
|
|
||||||
PARTITION OF customer_engagements
|
|
||||||
FOR VALUES IN ( 1 );
|
|
||||||
CREATE TABLE customer_engagements_2
|
|
||||||
PARTITION OF customer_engagements
|
|
||||||
FOR VALUES IN ( 2 );
|
|
||||||
-- add some indexes
|
|
||||||
CREATE INDEX ON customer_engagements (id);
|
|
||||||
ERROR: cannot create index on partitioned table "customer_engagements"
|
|
||||||
CREATE INDEX ON customer_engagements (event_id);
|
|
||||||
ERROR: cannot create index on partitioned table "customer_engagements"
|
|
||||||
CREATE INDEX ON customer_engagements (id, event_id);
|
|
||||||
ERROR: cannot create index on partitioned table "customer_engagements"
|
|
||||||
-- distribute the table
|
|
||||||
-- create a single shard on the first worker
|
|
||||||
SET citus.shard_count TO 1;
|
|
||||||
SET citus.shard_replication_factor TO 2;
|
|
||||||
SELECT create_distributed_table('customer_engagements', 'id', 'hash');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- ingest some data for the tests
|
|
||||||
INSERT INTO customer_engagements VALUES (1, 1);
|
|
||||||
INSERT INTO customer_engagements VALUES (2, 1);
|
|
||||||
INSERT INTO customer_engagements VALUES (1, 2);
|
|
||||||
INSERT INTO customer_engagements VALUES (2, 2);
|
|
||||||
-- the following queries does the following:
|
|
||||||
-- (i) create a new shard
|
|
||||||
-- (ii) mark the second shard placements as unhealthy
|
|
||||||
-- (iii) do basic checks i.e., only allow copy from healthy placement to unhealthy ones
|
|
||||||
-- (iv) do a successful master_copy_shard_placement from the first placement to the second
|
|
||||||
-- (v) mark the first placement as unhealthy and execute a query that is routed to the second placement
|
|
||||||
SELECT groupid AS worker_2_group FROM pg_dist_node WHERE nodeport=:worker_2_port \gset
|
|
||||||
SELECT groupid AS worker_1_group FROM pg_dist_node WHERE nodeport=:worker_1_port \gset
|
|
||||||
-- get the newshardid
|
|
||||||
SELECT shardid as newshardid FROM pg_dist_shard WHERE logicalrelid = 'customer_engagements'::regclass
|
|
||||||
\gset
|
|
||||||
-- now, update the second placement as unhealthy
|
|
||||||
UPDATE pg_dist_placement SET shardstate = 3 WHERE shardid = :newshardid
|
|
||||||
AND groupid = :worker_2_group;
|
|
||||||
-- cannot repair a shard after a modification (transaction still open during repair)
|
|
||||||
BEGIN;
|
|
||||||
INSERT INTO customer_engagements VALUES (1, 1);
|
|
||||||
SELECT master_copy_shard_placement(:newshardid, 'localhost', :worker_1_port, 'localhost', :worker_2_port);
|
|
||||||
ERROR: cannot open new connections after the first modification command within a transaction
|
|
||||||
ROLLBACK;
|
|
||||||
-- modifications after reparing a shard are fine (will use new metadata)
|
|
||||||
BEGIN;
|
|
||||||
SELECT master_copy_shard_placement(:newshardid, 'localhost', :worker_1_port, 'localhost', :worker_2_port);
|
|
||||||
master_copy_shard_placement
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ALTER TABLE customer_engagements ADD COLUMN value float DEFAULT 1.0;
|
|
||||||
SELECT * FROM customer_engagements ORDER BY 1,2,3;
|
|
||||||
id | event_id | value
|
|
||||||
----+----------+-------
|
|
||||||
1 | 1 | 1
|
|
||||||
1 | 2 | 1
|
|
||||||
2 | 1 | 1
|
|
||||||
2 | 2 | 1
|
|
||||||
(4 rows)
|
|
||||||
|
|
||||||
ROLLBACK;
|
|
||||||
BEGIN;
|
|
||||||
SELECT master_copy_shard_placement(:newshardid, 'localhost', :worker_1_port, 'localhost', :worker_2_port);
|
|
||||||
master_copy_shard_placement
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO customer_engagements VALUES (1, 1);
|
|
||||||
SELECT count(*) FROM customer_engagements;
|
|
||||||
count
|
|
||||||
-------
|
|
||||||
5
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
ROLLBACK;
|
|
||||||
-- TRUNCATE is allowed on the parent table
|
|
||||||
-- try it just before dropping the table
|
|
||||||
TRUNCATE collections;
|
|
||||||
SET search_path TO public;
|
|
||||||
DROP SCHEMA partitioned_table_replicated CASCADE;
|
|
||||||
NOTICE: drop cascades to 4 other objects
|
|
||||||
DETAIL: drop cascades to table partitioned_table_replicated.collections
|
|
||||||
drop cascades to table partitioned_table_replicated.fkey_test
|
|
||||||
drop cascades to table partitioned_table_replicated.collections_agg
|
|
||||||
drop cascades to table partitioned_table_replicated.customer_engagements
|
|
||||||
|
|
@ -3,14 +3,6 @@
|
||||||
--
|
--
|
||||||
-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures.
|
-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures.
|
||||||
--
|
--
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 100500;
|
SET citus.next_shard_id TO 100500;
|
||||||
CREATE SCHEMA procedure_schema;
|
CREATE SCHEMA procedure_schema;
|
||||||
SET SEARCH_PATH = procedure_schema;
|
SET SEARCH_PATH = procedure_schema;
|
||||||
|
|
|
||||||
|
|
@ -1,284 +0,0 @@
|
||||||
--
|
|
||||||
-- SQL_PROCEDURE
|
|
||||||
--
|
|
||||||
-- Tests basic PROCEDURE functionality with SQL and PLPGSQL procedures.
|
|
||||||
--
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 100500;
|
|
||||||
CREATE SCHEMA procedure_schema;
|
|
||||||
SET SEARCH_PATH = procedure_schema;
|
|
||||||
CREATE TABLE test_table(id integer , org_id integer);
|
|
||||||
CREATE UNIQUE INDEX idx_table ON test_table(id, org_id);
|
|
||||||
SELECT create_distributed_table('test_table','id');
|
|
||||||
create_distributed_table
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
INSERT INTO test_table VALUES(1, 1);
|
|
||||||
-- test CREATE PROCEDURE
|
|
||||||
CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE SQL AS $$
|
|
||||||
DELETE FROM test_table;
|
|
||||||
INSERT INTO test_table VALUES(id, org_id);
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_delete_insert(id int, org_id...
|
|
||||||
^
|
|
||||||
CALL test_procedure_delete_insert(2,3);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_delete_insert(2,3);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- commit/rollback is not allowed in procedures in SQL
|
|
||||||
-- following calls should fail
|
|
||||||
CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id int) LANGUAGE SQL AS $$
|
|
||||||
DELETE FROM test_table;
|
|
||||||
COMMIT;
|
|
||||||
INSERT INTO test_table VALUES(tt_id, -1);
|
|
||||||
UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id;
|
|
||||||
COMMIT;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_commit(tt_id int, tt_org_id ...
|
|
||||||
^
|
|
||||||
CALL test_procedure_commit(2,5);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_commit(2,5);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE SQL AS $$
|
|
||||||
DELETE FROM test_table;
|
|
||||||
ROLLBACK;
|
|
||||||
UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id;
|
|
||||||
COMMIT;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_i...
|
|
||||||
^
|
|
||||||
CALL test_procedure_rollback(2,15);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_rollback(2,15);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP PROCEDURE test_procedure_delete_insert(int, int);
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: DROP PROCEDURE test_procedure_delete_insert(int, int);
|
|
||||||
^
|
|
||||||
DROP PROCEDURE test_procedure_commit(int, int);
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: DROP PROCEDURE test_procedure_commit(int, int);
|
|
||||||
^
|
|
||||||
DROP PROCEDURE test_procedure_rollback(int, int);
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: DROP PROCEDURE test_procedure_rollback(int, int);
|
|
||||||
^
|
|
||||||
-- same tests with plpgsql
|
|
||||||
-- test CREATE PROCEDURE
|
|
||||||
CREATE PROCEDURE test_procedure_delete_insert(id int, org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM test_table;
|
|
||||||
INSERT INTO test_table VALUES(id, org_id);
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_delete_insert(id int, org_id...
|
|
||||||
^
|
|
||||||
CALL test_procedure_delete_insert(2,3);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_delete_insert(2,3);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- notice that the update succeed and committed
|
|
||||||
CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id;
|
|
||||||
COMMIT;
|
|
||||||
INSERT INTO test_table VALUES (tt_id, tt_org_id);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_modify_insert(tt_id int, tt_...
|
|
||||||
^
|
|
||||||
CALL test_procedure_modify_insert(2,12);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_modify_insert(2,12);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id;
|
|
||||||
COMMIT;
|
|
||||||
INSERT INTO test_table VALUES (tt_id, tt_org_id);
|
|
||||||
COMMIT;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_modify_insert_commit(tt_id i...
|
|
||||||
^
|
|
||||||
CALL test_procedure_modify_insert_commit(2,30);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_modify_insert_commit(2,30);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- delete is commited but insert is rolled back
|
|
||||||
CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM test_table;
|
|
||||||
COMMIT;
|
|
||||||
INSERT INTO test_table VALUES (tt_id, tt_org_id);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_rollback(tt_id int, tt_org_i...
|
|
||||||
^
|
|
||||||
CALL test_procedure_rollback(2,5);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_rollback(2,5);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- rollback is successfull when insert is on multiple rows
|
|
||||||
CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM test_table;
|
|
||||||
COMMIT;
|
|
||||||
INSERT INTO test_table VALUES (tt_id, tt_org_id), (tt_id+1, tt_org_id+1);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org...
|
|
||||||
^
|
|
||||||
CALL test_procedure_rollback_2(12, 15);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_rollback_2(12, 15);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- delete is rolled back, update is committed
|
|
||||||
CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM test_table;
|
|
||||||
ROLLBACK;
|
|
||||||
UPDATE test_table SET org_id = tt_org_id WHERE id = tt_id;
|
|
||||||
COMMIT;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE PROCEDURE test_procedure_rollback_3(tt_id int, tt_org...
|
|
||||||
^
|
|
||||||
INSERT INTO test_table VALUES (1, 1), (2, 2);
|
|
||||||
ERROR: duplicate key value violates unique constraint "idx_table_100500"
|
|
||||||
DETAIL: Key (id, org_id)=(1, 1) already exists.
|
|
||||||
CONTEXT: while executing command on localhost:57638
|
|
||||||
CALL test_procedure_rollback_3(2,15);
|
|
||||||
ERROR: syntax error at or near "CALL"
|
|
||||||
LINE 1: CALL test_procedure_rollback_3(2,15);
|
|
||||||
^
|
|
||||||
SELECT * FROM test_table ORDER BY 1, 2;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
1 | 1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
TRUNCATE test_table;
|
|
||||||
-- nested procedure calls should roll back normally
|
|
||||||
CREATE OR REPLACE PROCEDURE test_procedure_rollback(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO test_table VALUES (tt_id+12, tt_org_id+12);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE OR REPLACE PROCEDURE test_procedure_rollback(tt_id in...
|
|
||||||
^
|
|
||||||
CREATE OR REPLACE PROCEDURE test_procedure_rollback_2(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO test_table VALUES (tt_id+2, tt_org_id+1);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE OR REPLACE PROCEDURE test_procedure_rollback_2(tt_id ...
|
|
||||||
^
|
|
||||||
CREATE OR REPLACE PROCEDURE test_procedure(tt_id int, tt_org_id int) LANGUAGE PLPGSQL AS $$
|
|
||||||
BEGIN
|
|
||||||
CALL test_procedure_rollback(tt_id, tt_org_id);
|
|
||||||
CALL test_procedure_rollback_2(tt_id, tt_org_id);
|
|
||||||
INSERT INTO test_table VALUES (tt_id+100, tt_org_id+100);
|
|
||||||
ROLLBACK;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
ERROR: syntax error at or near "PROCEDURE"
|
|
||||||
LINE 1: CREATE OR REPLACE PROCEDURE test_procedure(tt_id int, tt_org...
|
|
||||||
^
|
|
||||||
SELECT * from test_table;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
call test_procedure(1,1);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call test_procedure(1,1);
|
|
||||||
^
|
|
||||||
call test_procedure(20, 20);
|
|
||||||
ERROR: syntax error at or near "call"
|
|
||||||
LINE 1: call test_procedure(20, 20);
|
|
||||||
^
|
|
||||||
SELECT * from test_table;
|
|
||||||
id | org_id
|
|
||||||
----+--------
|
|
||||||
(0 rows)
|
|
||||||
|
|
||||||
\set VERBOSITY terse
|
|
||||||
DROP SCHEMA procedure_schema CASCADE;
|
|
||||||
NOTICE: drop cascades to table test_table
|
|
||||||
\set VERBOSITY default
|
|
||||||
RESET SEARCH_PATH;
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- test top level window functions that are pushdownable
|
-- test top level window functions that are pushdownable
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- a very simple window function with an aggregate and a window function
|
-- a very simple window function with an aggregate and a window function
|
||||||
-- distribution column is on the partition by clause
|
-- distribution column is on the partition by clause
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -737,7 +730,6 @@ LIMIT
|
||||||
4 | 2
|
4 | 2
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
|
||||||
-- not a meaningful query, with interesting syntax
|
-- not a meaningful query, with interesting syntax
|
||||||
SELECT
|
SELECT
|
||||||
user_id,
|
user_id,
|
||||||
|
|
|
||||||
|
|
@ -1,933 +0,0 @@
|
||||||
-- ===================================================================
|
|
||||||
-- test top level window functions that are pushdownable
|
|
||||||
-- ===================================================================
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
version_above_ten
|
|
||||||
-------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- a very simple window function with an aggregate and a window function
|
|
||||||
-- distribution column is on the partition by clause
|
|
||||||
SELECT
|
|
||||||
user_id, COUNT(*) OVER (PARTITION BY user_id),
|
|
||||||
rank() OVER (PARTITION BY user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
ORDER BY
|
|
||||||
1 DESC, 2 DESC, 3 DESC
|
|
||||||
LIMIT 5;
|
|
||||||
user_id | count | rank
|
|
||||||
---------+-------+------
|
|
||||||
6 | 10 | 1
|
|
||||||
6 | 10 | 1
|
|
||||||
6 | 10 | 1
|
|
||||||
6 | 10 | 1
|
|
||||||
6 | 10 | 1
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- a more complicated window clause, including an aggregate
|
|
||||||
-- in both the window clause and the target entry
|
|
||||||
SELECT
|
|
||||||
user_id, avg(avg(value_3)) OVER (PARTITION BY user_id, MIN(value_2))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
1
|
|
||||||
ORDER BY
|
|
||||||
2 DESC NULLS LAST, 1 DESC;
|
|
||||||
user_id | avg
|
|
||||||
---------+------------------
|
|
||||||
2 | 3
|
|
||||||
4 | 2.82608695652174
|
|
||||||
3 | 2.70588235294118
|
|
||||||
6 | 2.6
|
|
||||||
1 | 2.57142857142857
|
|
||||||
5 | 2.46153846153846
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
-- window clause operates on the results of a subquery
|
|
||||||
SELECT
|
|
||||||
user_id, max(value_1) OVER (PARTITION BY user_id, MIN(value_2))
|
|
||||||
FROM (
|
|
||||||
SELECT
|
|
||||||
DISTINCT us.user_id, us.value_2, value_1, random() as r1
|
|
||||||
FROM
|
|
||||||
users_table as us, events_table
|
|
||||||
WHERE
|
|
||||||
us.user_id = events_table.user_id AND event_type IN (1,2)
|
|
||||||
ORDER BY
|
|
||||||
user_id, value_2
|
|
||||||
) s
|
|
||||||
GROUP BY
|
|
||||||
1, value_1
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 1;
|
|
||||||
user_id | max
|
|
||||||
---------+-----
|
|
||||||
1 | 5
|
|
||||||
3 | 5
|
|
||||||
3 | 5
|
|
||||||
4 | 5
|
|
||||||
5 | 5
|
|
||||||
5 | 5
|
|
||||||
6 | 5
|
|
||||||
6 | 5
|
|
||||||
1 | 4
|
|
||||||
2 | 4
|
|
||||||
3 | 4
|
|
||||||
3 | 4
|
|
||||||
3 | 4
|
|
||||||
4 | 4
|
|
||||||
4 | 4
|
|
||||||
5 | 4
|
|
||||||
5 | 4
|
|
||||||
1 | 3
|
|
||||||
2 | 3
|
|
||||||
2 | 3
|
|
||||||
2 | 3
|
|
||||||
6 | 3
|
|
||||||
2 | 2
|
|
||||||
4 | 2
|
|
||||||
4 | 2
|
|
||||||
4 | 2
|
|
||||||
6 | 2
|
|
||||||
1 | 1
|
|
||||||
3 | 1
|
|
||||||
5 | 1
|
|
||||||
6 | 1
|
|
||||||
5 | 0
|
|
||||||
(32 rows)
|
|
||||||
|
|
||||||
-- window function operates on the results of
|
|
||||||
-- a join
|
|
||||||
SELECT
|
|
||||||
us.user_id,
|
|
||||||
SUM(us.value_1) OVER (PARTITION BY us.user_id)
|
|
||||||
FROM
|
|
||||||
users_table us
|
|
||||||
JOIN
|
|
||||||
events_table ev
|
|
||||||
ON (us.user_id = ev.user_id)
|
|
||||||
GROUP BY
|
|
||||||
1,
|
|
||||||
value_1
|
|
||||||
ORDER BY
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
LIMIT 5;
|
|
||||||
user_id | sum
|
|
||||||
---------+-----
|
|
||||||
1 | 13
|
|
||||||
1 | 13
|
|
||||||
1 | 13
|
|
||||||
1 | 13
|
|
||||||
2 | 10
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- the same query, but this time join with an alias
|
|
||||||
SELECT
|
|
||||||
user_id, value_1, SUM(j.value_1) OVER (PARTITION BY j.user_id)
|
|
||||||
FROM
|
|
||||||
(users_table us
|
|
||||||
JOIN
|
|
||||||
events_table ev
|
|
||||||
USING (user_id )
|
|
||||||
) j
|
|
||||||
GROUP BY
|
|
||||||
user_id,
|
|
||||||
value_1
|
|
||||||
ORDER BY
|
|
||||||
3 DESC, 2 DESC, 1 DESC
|
|
||||||
LIMIT 5;
|
|
||||||
user_id | value_1 | sum
|
|
||||||
---------+---------+-----
|
|
||||||
5 | 5 | 15
|
|
||||||
4 | 5 | 15
|
|
||||||
3 | 5 | 15
|
|
||||||
5 | 4 | 15
|
|
||||||
4 | 4 | 15
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- querying views that have window functions should be ok
|
|
||||||
CREATE VIEW window_view AS
|
|
||||||
SELECT
|
|
||||||
DISTINCT user_id, rank() OVER (PARTITION BY user_id ORDER BY value_1)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_1
|
|
||||||
HAVING count(*) > 1;
|
|
||||||
-- Window function in View works
|
|
||||||
SELECT *
|
|
||||||
FROM
|
|
||||||
window_view
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 1
|
|
||||||
LIMIT 10;
|
|
||||||
user_id | rank
|
|
||||||
---------+------
|
|
||||||
5 | 6
|
|
||||||
2 | 5
|
|
||||||
4 | 5
|
|
||||||
5 | 5
|
|
||||||
2 | 4
|
|
||||||
3 | 4
|
|
||||||
4 | 4
|
|
||||||
5 | 4
|
|
||||||
6 | 4
|
|
||||||
2 | 3
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
-- the other way around also should work fine
|
|
||||||
-- query a view using window functions
|
|
||||||
CREATE VIEW users_view AS SELECT * FROM users_table;
|
|
||||||
SELECT
|
|
||||||
DISTINCT user_id, rank() OVER (PARTITION BY user_id ORDER BY value_1)
|
|
||||||
FROM
|
|
||||||
users_view
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_1
|
|
||||||
HAVING count(*) > 4
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 1;
|
|
||||||
user_id | rank
|
|
||||||
---------+------
|
|
||||||
4 | 2
|
|
||||||
5 | 2
|
|
||||||
2 | 1
|
|
||||||
3 | 1
|
|
||||||
4 | 1
|
|
||||||
5 | 1
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
DROP VIEW users_view, window_view;
|
|
||||||
-- window function uses columns from two different tables
|
|
||||||
SELECT
|
|
||||||
DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk
|
|
||||||
FROM
|
|
||||||
events_table, users_table
|
|
||||||
WHERE
|
|
||||||
users_table.user_id = events_table.user_id
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY events_table.user_id, users_table.value_1 ORDER BY events_table.time DESC)
|
|
||||||
ORDER BY
|
|
||||||
rnk DESC, 1 DESC
|
|
||||||
LIMIT 10;
|
|
||||||
user_id | rnk
|
|
||||||
---------+-----
|
|
||||||
3 | 121
|
|
||||||
5 | 118
|
|
||||||
2 | 116
|
|
||||||
3 | 115
|
|
||||||
4 | 113
|
|
||||||
2 | 111
|
|
||||||
5 | 109
|
|
||||||
3 | 109
|
|
||||||
4 | 106
|
|
||||||
2 | 106
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
-- the same query with reference table column is also on the partition by clause
|
|
||||||
SELECT
|
|
||||||
DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk
|
|
||||||
FROM
|
|
||||||
events_table, users_ref_test_table uref
|
|
||||||
WHERE
|
|
||||||
uref.id = events_table.user_id
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY events_table.user_id, uref.k_no ORDER BY events_table.time DESC)
|
|
||||||
ORDER BY
|
|
||||||
rnk DESC, 1 DESC
|
|
||||||
LIMIT 10;
|
|
||||||
user_id | rnk
|
|
||||||
---------+-----
|
|
||||||
2 | 24
|
|
||||||
2 | 23
|
|
||||||
2 | 22
|
|
||||||
3 | 21
|
|
||||||
2 | 21
|
|
||||||
3 | 20
|
|
||||||
2 | 20
|
|
||||||
3 | 19
|
|
||||||
2 | 19
|
|
||||||
3 | 18
|
|
||||||
(10 rows)
|
|
||||||
|
|
||||||
-- similar query with no distribution column is on the partition by clause
|
|
||||||
-- is not supported
|
|
||||||
SELECT
|
|
||||||
DISTINCT ON (events_table.user_id, rnk) events_table.user_id, rank() OVER my_win AS rnk
|
|
||||||
FROM
|
|
||||||
events_table, users_ref_test_table uref
|
|
||||||
WHERE
|
|
||||||
uref.id = events_table.user_id
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY events_table.value_2, uref.k_no ORDER BY events_table.time DESC)
|
|
||||||
ORDER BY
|
|
||||||
rnk DESC, 1 DESC
|
|
||||||
LIMIT 10;
|
|
||||||
ERROR: could not run distributed query because the window function that is used cannot be pushed down
|
|
||||||
HINT: Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions with a PARTITION BY clause containing the distribution column
|
|
||||||
-- ORDER BY in the window function is an aggragate
|
|
||||||
SELECT
|
|
||||||
user_id, rank() OVER my_win as rnk, avg(value_2) as avg_val_2
|
|
||||||
FROM
|
|
||||||
events_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, date_trunc('day', time)
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY user_id ORDER BY avg(event_type) DESC)
|
|
||||||
ORDER BY
|
|
||||||
3 DESC, 2 DESC, 1 DESC;
|
|
||||||
user_id | rnk | avg_val_2
|
|
||||||
---------+-----+--------------------
|
|
||||||
1 | 1 | 3.3750000000000000
|
|
||||||
3 | 2 | 3.1666666666666667
|
|
||||||
5 | 1 | 2.6666666666666667
|
|
||||||
6 | 1 | 2.5000000000000000
|
|
||||||
4 | 1 | 2.5000000000000000
|
|
||||||
2 | 1 | 2.4736842105263158
|
|
||||||
4 | 2 | 2.4000000000000000
|
|
||||||
1 | 2 | 2.1428571428571429
|
|
||||||
5 | 2 | 2.0909090909090909
|
|
||||||
6 | 2 | 2.0000000000000000
|
|
||||||
2 | 2 | 2.0000000000000000
|
|
||||||
3 | 1 | 1.8000000000000000
|
|
||||||
(12 rows)
|
|
||||||
|
|
||||||
-- lets push the limits of writing complex expressions aling with the window functions
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER (PARTITION BY user_id, user_id + 1),
|
|
||||||
rank() OVER (PARTITION BY user_id) as cnt1,
|
|
||||||
COUNT(*) OVER (PARTITION BY user_id, abs(value_1 - value_2)) as cnt2,
|
|
||||||
date_trunc('min', lag(time) OVER (PARTITION BY user_id ORDER BY time)) as datee,
|
|
||||||
rank() OVER my_win as rnnk,
|
|
||||||
avg(CASE
|
|
||||||
WHEN user_id > 4
|
|
||||||
THEN value_1
|
|
||||||
ELSE value_2
|
|
||||||
END) FILTER (WHERE user_id > 2) OVER my_win_2 as filtered_count,
|
|
||||||
sum(user_id * (5.0 / (value_1 + value_2 + 0.1)) * value_3) FILTER (WHERE value_1::text LIKE '%1%') OVER my_win_4 as cnt_with_filter_2
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY user_id, (value_1%3)::int ORDER BY time DESC),
|
|
||||||
my_win_2 AS (PARTITION BY user_id, (value_1)::int ORDER BY time DESC),
|
|
||||||
my_win_3 AS (PARTITION BY user_id, date_trunc('min', time)),
|
|
||||||
my_win_4 AS (my_win_3 ORDER BY value_2, value_3)
|
|
||||||
ORDER BY
|
|
||||||
cnt_with_filter_2 DESC NULLS LAST, filtered_count DESC NULLS LAST, datee DESC NULLS LAST, rnnk DESC, cnt2 DESC, cnt1 DESC, user_id DESC
|
|
||||||
LIMIT 5;
|
|
||||||
count | cnt1 | cnt2 | datee | rnnk | filtered_count | cnt_with_filter_2
|
|
||||||
-------+------+------+--------------------------+------+------------------------+-------------------
|
|
||||||
23 | 1 | 7 | Thu Nov 23 02:14:00 2017 | 6 | 0.00000000000000000000 | 72.7272727272727
|
|
||||||
10 | 1 | 3 | Wed Nov 22 23:01:00 2017 | 1 | 1.00000000000000000000 | 57.1428571428571
|
|
||||||
17 | 1 | 5 | Wed Nov 22 23:24:00 2017 | 8 | 3.0000000000000000 | 28.5714285714286
|
|
||||||
17 | 1 | 5 | | 10 | 2.6666666666666667 | 28.5714285714286
|
|
||||||
17 | 1 | 5 | Thu Nov 23 00:15:00 2017 | 7 | 3.6666666666666667 | 24.1935483870968
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- some tests with GROUP BY along with PARTITION BY
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
rank() OVER my_win as my_rank,
|
|
||||||
avg(avg(event_type)) OVER my_win_2 as avg,
|
|
||||||
max(time) as mx_time
|
|
||||||
FROM
|
|
||||||
events_table
|
|
||||||
GROUP BY
|
|
||||||
user_id,
|
|
||||||
value_2
|
|
||||||
WINDOW
|
|
||||||
my_win AS (PARTITION BY user_id, max(event_type) ORDER BY count(*) DESC),
|
|
||||||
my_win_2 AS (PARTITION BY user_id, avg(user_id) ORDER BY count(*) DESC)
|
|
||||||
ORDER BY
|
|
||||||
avg DESC,
|
|
||||||
mx_time DESC,
|
|
||||||
my_rank DESC,
|
|
||||||
user_id DESC;
|
|
||||||
user_id | my_rank | avg | mx_time
|
|
||||||
---------+---------+------------------------+---------------------------------
|
|
||||||
6 | 1 | 3.0000000000000000 | Thu Nov 23 14:00:13.20013 2017
|
|
||||||
6 | 2 | 3.0000000000000000 | Thu Nov 23 11:16:13.106691 2017
|
|
||||||
6 | 1 | 3.0000000000000000 | Thu Nov 23 07:27:32.822068 2017
|
|
||||||
3 | 1 | 2.9857142857142857 | Thu Nov 23 16:31:56.219594 2017
|
|
||||||
4 | 2 | 2.9555555555555556 | Thu Nov 23 14:19:25.765876 2017
|
|
||||||
4 | 1 | 2.9555555555555556 | Thu Nov 23 08:36:53.871919 2017
|
|
||||||
1 | 4 | 2.8633333333333333 | Wed Nov 22 21:06:57.457147 2017
|
|
||||||
1 | 1 | 2.8250000000000000 | Thu Nov 23 21:54:46.924477 2017
|
|
||||||
2 | 2 | 2.7738095238095238 | Thu Nov 23 13:27:37.441959 2017
|
|
||||||
1 | 2 | 2.7722222222222222 | Thu Nov 23 09:23:30.994345 2017
|
|
||||||
3 | 1 | 2.7682539682539682 | Thu Nov 23 01:17:49.040685 2017
|
|
||||||
2 | 1 | 2.7142857142857143 | Thu Nov 23 15:58:49.273421 2017
|
|
||||||
1 | 3 | 2.5791666666666667 | Thu Nov 23 11:09:38.074595 2017
|
|
||||||
3 | 1 | 2.5714285714285714 | Thu Nov 23 16:44:41.903713 2017
|
|
||||||
2 | 1 | 2.5158730158730159 | Thu Nov 23 14:02:47.738901 2017
|
|
||||||
4 | 1 | 2.47777777777777778333 | Thu Nov 23 16:20:33.264457 2017
|
|
||||||
4 | 3 | 2.47777777777777778333 | Thu Nov 23 08:14:18.231273 2017
|
|
||||||
4 | 3 | 2.47777777777777778333 | Thu Nov 23 07:32:45.521278 2017
|
|
||||||
1 | 1 | 2.4000000000000000 | Thu Nov 23 10:23:27.617726 2017
|
|
||||||
2 | 1 | 2.3869047619047619 | Thu Nov 23 17:26:14.563216 2017
|
|
||||||
3 | 1 | 2.3841269841269841 | Thu Nov 23 18:08:26.550729 2017
|
|
||||||
3 | 1 | 2.3841269841269841 | Thu Nov 23 09:38:45.338008 2017
|
|
||||||
3 | 2 | 2.3841269841269841 | Thu Nov 23 06:44:50.887182 2017
|
|
||||||
2 | 2 | 2.3095238095238095 | Thu Nov 23 04:05:16.217731 2017
|
|
||||||
5 | 2 | 2.3000000000000000 | Thu Nov 23 14:28:51.833214 2017
|
|
||||||
5 | 2 | 2.3000000000000000 | Thu Nov 23 14:23:09.889786 2017
|
|
||||||
4 | 1 | 2.2000000000000000 | Thu Nov 23 18:10:21.338399 2017
|
|
||||||
2 | 1 | 2.09126984126984126667 | Thu Nov 23 03:35:04.321504 2017
|
|
||||||
5 | 1 | 2.0000000000000000 | Thu Nov 23 16:11:02.929469 2017
|
|
||||||
5 | 1 | 2.0000000000000000 | Thu Nov 23 14:40:40.467511 2017
|
|
||||||
5 | 1 | 2.0000000000000000 | Thu Nov 23 13:26:45.571108 2017
|
|
||||||
(31 rows)
|
|
||||||
|
|
||||||
-- test for range and rows mode and different window functions
|
|
||||||
-- mostly to make sure that deparsing works fine
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
rank() OVER (PARTITION BY user_id ROWS BETWEEN
|
|
||||||
UNBOUNDED PRECEDING AND CURRENT ROW),
|
|
||||||
dense_rank() OVER (PARTITION BY user_id RANGE BETWEEN
|
|
||||||
UNBOUNDED PRECEDING AND CURRENT ROW),
|
|
||||||
CUME_DIST() OVER (PARTITION BY user_id RANGE BETWEEN
|
|
||||||
UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
|
|
||||||
PERCENT_RANK() OVER (PARTITION BY user_id ORDER BY avg(value_1) RANGE BETWEEN
|
|
||||||
UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
1
|
|
||||||
ORDER BY
|
|
||||||
4 DESC,3 DESC,2 DESC ,1 DESC;
|
|
||||||
user_id | rank | dense_rank | cume_dist | percent_rank
|
|
||||||
---------+------+------------+-----------+--------------
|
|
||||||
6 | 1 | 1 | 1 | 0
|
|
||||||
5 | 1 | 1 | 1 | 0
|
|
||||||
4 | 1 | 1 | 1 | 0
|
|
||||||
3 | 1 | 1 | 1 | 0
|
|
||||||
2 | 1 | 1 | 1 | 0
|
|
||||||
1 | 1 | 1 | 1 | 0
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
-- test exclude supported
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
value_1,
|
|
||||||
array_agg(value_1) OVER (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
|
|
||||||
array_agg(value_1) OVER (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE CURRENT ROW)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
WHERE
|
|
||||||
user_id > 2 AND user_id < 6
|
|
||||||
ORDER BY
|
|
||||||
user_id, value_1, 3, 4;
|
|
||||||
ERROR: syntax error at or near "EXCLUDE"
|
|
||||||
LINE 5: ...ANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE CU...
|
|
||||||
^
|
|
||||||
-- test <offset> preceding and <offset> following on RANGE window
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
value_1,
|
|
||||||
array_agg(value_1) OVER range_window,
|
|
||||||
array_agg(value_1) OVER range_window_exclude
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
WHERE
|
|
||||||
user_id > 2 AND user_id < 6
|
|
||||||
WINDOW
|
|
||||||
range_window as (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
|
||||||
range_window_exclude as (PARTITION BY user_id ORDER BY value_1 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW)
|
|
||||||
ORDER BY
|
|
||||||
user_id, value_1, 3, 4;
|
|
||||||
ERROR: RANGE PRECEDING is only supported with UNBOUNDED
|
|
||||||
LINE 11: ..._window as (PARTITION BY user_id ORDER BY value_1 RANGE BETW...
|
|
||||||
^
|
|
||||||
-- test <offset> preceding and <offset> following on ROW window
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
value_1,
|
|
||||||
array_agg(value_1) OVER row_window,
|
|
||||||
array_agg(value_1) OVER row_window_exclude
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
WHERE
|
|
||||||
user_id > 2 and user_id < 6
|
|
||||||
WINDOW
|
|
||||||
row_window as (PARTITION BY user_id ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
|
||||||
row_window_exclude as (PARTITION BY user_id ORDER BY value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW)
|
|
||||||
ORDER BY
|
|
||||||
user_id, value_1, 3, 4;
|
|
||||||
ERROR: syntax error at or near "EXCLUDE"
|
|
||||||
LINE 12: ...value_1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING EXCLUDE CU...
|
|
||||||
^
|
|
||||||
-- some tests with GROUP BY, HAVING and LIMIT
|
|
||||||
SELECT
|
|
||||||
user_id, sum(event_type) OVER my_win , event_type
|
|
||||||
FROM
|
|
||||||
events_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, event_type
|
|
||||||
HAVING count(*) > 2
|
|
||||||
WINDOW my_win AS (PARTITION BY user_id, max(event_type) ORDER BY count(*) DESC)
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 3 DESC, 1 DESC
|
|
||||||
LIMIT
|
|
||||||
5;
|
|
||||||
user_id | sum | event_type
|
|
||||||
---------+-----+------------
|
|
||||||
4 | 4 | 4
|
|
||||||
3 | 4 | 4
|
|
||||||
2 | 4 | 4
|
|
||||||
1 | 4 | 4
|
|
||||||
5 | 3 | 3
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- Group by has more columns than partition by
|
|
||||||
SELECT
|
|
||||||
DISTINCT user_id, SUM(value_2) OVER (PARTITION BY user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_1, value_2
|
|
||||||
HAVING count(*) > 2
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 1
|
|
||||||
LIMIT
|
|
||||||
10;
|
|
||||||
user_id | sum
|
|
||||||
---------+-----
|
|
||||||
5 | 3
|
|
||||||
4 | 2
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
DISTINCT ON (user_id) user_id, SUM(value_2) OVER (PARTITION BY user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_1, value_2
|
|
||||||
HAVING count(*) > 2
|
|
||||||
ORDER BY
|
|
||||||
1, 2 DESC
|
|
||||||
LIMIT
|
|
||||||
10;
|
|
||||||
user_id | sum
|
|
||||||
---------+-----
|
|
||||||
4 | 2
|
|
||||||
5 | 3
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
DISTINCT ON (SUM(value_1) OVER (PARTITION BY user_id)) user_id, SUM(value_2) OVER (PARTITION BY user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_1, value_2
|
|
||||||
HAVING count(*) > 2
|
|
||||||
ORDER BY
|
|
||||||
(SUM(value_1) OVER (PARTITION BY user_id)) , 2 DESC, 1
|
|
||||||
LIMIT
|
|
||||||
10;
|
|
||||||
user_id | sum
|
|
||||||
---------+-----
|
|
||||||
5 | 3
|
|
||||||
4 | 2
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
|
|
||||||
-- not a meaningful query, with interesting syntax
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
AVG(avg(value_1)) OVER (PARTITION BY user_id, max(user_id), MIN(value_2)),
|
|
||||||
AVG(avg(user_id)) OVER (PARTITION BY user_id, min(user_id), AVG(value_1))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
1
|
|
||||||
ORDER BY
|
|
||||||
3 DESC, 2 DESC, 1 DESC;
|
|
||||||
user_id | avg | avg
|
|
||||||
---------+--------------------+------------------------
|
|
||||||
6 | 2.1000000000000000 | 6.0000000000000000
|
|
||||||
5 | 2.6538461538461538 | 5.0000000000000000
|
|
||||||
4 | 2.7391304347826087 | 4.0000000000000000
|
|
||||||
3 | 2.3529411764705882 | 3.0000000000000000
|
|
||||||
2 | 2.3333333333333333 | 2.0000000000000000
|
|
||||||
1 | 3.2857142857142857 | 1.00000000000000000000
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
SELECT coordinator_plan($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
AVG(avg(value_1)) OVER (PARTITION BY user_id, max(user_id), MIN(value_2)),
|
|
||||||
AVG(avg(user_id)) OVER (PARTITION BY user_id, min(user_id), AVG(value_1))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
1
|
|
||||||
ORDER BY
|
|
||||||
3 DESC, 2 DESC, 1 DESC;
|
|
||||||
$Q$);
|
|
||||||
coordinator_plan
|
|
||||||
------------------------------------------------------------------------------------
|
|
||||||
Sort
|
|
||||||
Sort Key: remote_scan.avg_1 DESC, remote_scan.avg DESC, remote_scan.user_id DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id
|
|
||||||
-> Custom Scan (Citus Adaptive)
|
|
||||||
Task Count: 4
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
1 + sum(value_1),
|
|
||||||
1 + AVG(value_2) OVER (partition by user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_2
|
|
||||||
ORDER BY
|
|
||||||
user_id, value_2;
|
|
||||||
user_id | ?column? | ?column?
|
|
||||||
---------+----------+--------------------
|
|
||||||
1 | 5 | 3.2500000000000000
|
|
||||||
1 | 4 | 3.2500000000000000
|
|
||||||
1 | 6 | 3.2500000000000000
|
|
||||||
1 | 12 | 3.2500000000000000
|
|
||||||
2 | 3 | 3.5000000000000000
|
|
||||||
2 | 5 | 3.5000000000000000
|
|
||||||
2 | 13 | 3.5000000000000000
|
|
||||||
2 | 6 | 3.5000000000000000
|
|
||||||
2 | 17 | 3.5000000000000000
|
|
||||||
2 | 4 | 3.5000000000000000
|
|
||||||
3 | 3 | 4.0000000000000000
|
|
||||||
3 | 13 | 4.0000000000000000
|
|
||||||
3 | 10 | 4.0000000000000000
|
|
||||||
3 | 2 | 4.0000000000000000
|
|
||||||
3 | 17 | 4.0000000000000000
|
|
||||||
4 | 4 | 3.5000000000000000
|
|
||||||
4 | 28 | 3.5000000000000000
|
|
||||||
4 | 1 | 3.5000000000000000
|
|
||||||
4 | 11 | 3.5000000000000000
|
|
||||||
4 | 17 | 3.5000000000000000
|
|
||||||
4 | 8 | 3.5000000000000000
|
|
||||||
5 | 7 | 3.5000000000000000
|
|
||||||
5 | 17 | 3.5000000000000000
|
|
||||||
5 | 24 | 3.5000000000000000
|
|
||||||
5 | 9 | 3.5000000000000000
|
|
||||||
5 | 8 | 3.5000000000000000
|
|
||||||
5 | 10 | 3.5000000000000000
|
|
||||||
6 | 6 | 3.0000000000000000
|
|
||||||
6 | 3 | 3.0000000000000000
|
|
||||||
6 | 9 | 3.0000000000000000
|
|
||||||
6 | 3 | 3.0000000000000000
|
|
||||||
6 | 5 | 3.0000000000000000
|
|
||||||
(32 rows)
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
1 + sum(value_1),
|
|
||||||
1 + AVG(value_2) OVER (partition by user_id)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY
|
|
||||||
user_id, value_2
|
|
||||||
ORDER BY
|
|
||||||
2 DESC, 1
|
|
||||||
LIMIT 5;
|
|
||||||
user_id | ?column? | ?column?
|
|
||||||
---------+----------+--------------------
|
|
||||||
4 | 28 | 3.5000000000000000
|
|
||||||
5 | 24 | 3.5000000000000000
|
|
||||||
2 | 17 | 3.5000000000000000
|
|
||||||
3 | 17 | 4.0000000000000000
|
|
||||||
4 | 17 | 3.5000000000000000
|
|
||||||
(5 rows)
|
|
||||||
|
|
||||||
-- rank and ordering in the reverse order
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by value_2)
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, value_2 DESC;
|
|
||||||
user_id | avg | rank
|
|
||||||
---------+------------------------+------
|
|
||||||
1 | 3.6666666666666667 | 4
|
|
||||||
1 | 2.5000000000000000 | 3
|
|
||||||
1 | 3.0000000000000000 | 2
|
|
||||||
1 | 4.0000000000000000 | 1
|
|
||||||
2 | 1.5000000000000000 | 6
|
|
||||||
2 | 3.2000000000000000 | 5
|
|
||||||
2 | 1.6666666666666667 | 4
|
|
||||||
2 | 3.0000000000000000 | 3
|
|
||||||
2 | 1.3333333333333333 | 2
|
|
||||||
2 | 2.0000000000000000 | 1
|
|
||||||
3 | 2.6666666666666667 | 5
|
|
||||||
3 | 1.00000000000000000000 | 4
|
|
||||||
3 | 3.0000000000000000 | 3
|
|
||||||
3 | 2.4000000000000000 | 2
|
|
||||||
3 | 1.00000000000000000000 | 1
|
|
||||||
4 | 3.5000000000000000 | 6
|
|
||||||
4 | 3.2000000000000000 | 5
|
|
||||||
4 | 3.3333333333333333 | 4
|
|
||||||
4 | 0.00000000000000000000 | 3
|
|
||||||
4 | 3.0000000000000000 | 2
|
|
||||||
4 | 1.00000000000000000000 | 1
|
|
||||||
5 | 3.0000000000000000 | 6
|
|
||||||
5 | 2.3333333333333333 | 5
|
|
||||||
5 | 1.6000000000000000 | 4
|
|
||||||
5 | 2.8750000000000000 | 3
|
|
||||||
5 | 3.2000000000000000 | 2
|
|
||||||
5 | 3.0000000000000000 | 1
|
|
||||||
6 | 1.3333333333333333 | 5
|
|
||||||
6 | 2.0000000000000000 | 4
|
|
||||||
6 | 4.0000000000000000 | 3
|
|
||||||
6 | 1.00000000000000000000 | 2
|
|
||||||
6 | 2.5000000000000000 | 1
|
|
||||||
(32 rows)
|
|
||||||
|
|
||||||
-- order by in the window function is same as avg(value_1) DESC
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC;
|
|
||||||
user_id | avg | rank
|
|
||||||
---------+------------------------+------
|
|
||||||
1 | 4.0000000000000000 | 1
|
|
||||||
1 | 3.6666666666666667 | 2
|
|
||||||
1 | 3.0000000000000000 | 3
|
|
||||||
1 | 2.5000000000000000 | 4
|
|
||||||
2 | 3.2000000000000000 | 1
|
|
||||||
2 | 3.0000000000000000 | 2
|
|
||||||
2 | 2.0000000000000000 | 3
|
|
||||||
2 | 1.6666666666666667 | 4
|
|
||||||
2 | 1.5000000000000000 | 5
|
|
||||||
2 | 1.3333333333333333 | 6
|
|
||||||
3 | 3.0000000000000000 | 1
|
|
||||||
3 | 2.6666666666666667 | 2
|
|
||||||
3 | 2.4000000000000000 | 3
|
|
||||||
3 | 1.00000000000000000000 | 4
|
|
||||||
3 | 1.00000000000000000000 | 4
|
|
||||||
4 | 3.5000000000000000 | 1
|
|
||||||
4 | 3.3333333333333333 | 2
|
|
||||||
4 | 3.2000000000000000 | 3
|
|
||||||
4 | 3.0000000000000000 | 4
|
|
||||||
4 | 1.00000000000000000000 | 5
|
|
||||||
4 | 0.00000000000000000000 | 6
|
|
||||||
5 | 3.2000000000000000 | 1
|
|
||||||
5 | 3.0000000000000000 | 2
|
|
||||||
5 | 3.0000000000000000 | 2
|
|
||||||
5 | 2.8750000000000000 | 4
|
|
||||||
5 | 2.3333333333333333 | 5
|
|
||||||
5 | 1.6000000000000000 | 6
|
|
||||||
6 | 4.0000000000000000 | 1
|
|
||||||
6 | 2.5000000000000000 | 2
|
|
||||||
6 | 2.0000000000000000 | 3
|
|
||||||
6 | 1.3333333333333333 | 4
|
|
||||||
6 | 1.00000000000000000000 | 5
|
|
||||||
(32 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC;
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Sort
|
|
||||||
Sort Key: remote_scan.user_id, (pg_catalog.sum(((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))) / pg_catalog.sum(remote_scan.rank)) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id, remote_scan.worker_column_5
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> 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
|
|
||||||
(15 rows)
|
|
||||||
|
|
||||||
-- order by in the window function is same as avg(value_1) DESC
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC;
|
|
||||||
user_id | avg | rank
|
|
||||||
---------+------------------------+------
|
|
||||||
1 | 4.0000000000000000 | 1
|
|
||||||
1 | 3.6666666666666667 | 2
|
|
||||||
1 | 3.0000000000000000 | 3
|
|
||||||
1 | 2.5000000000000000 | 4
|
|
||||||
2 | 3.2000000000000000 | 1
|
|
||||||
2 | 3.0000000000000000 | 2
|
|
||||||
2 | 2.0000000000000000 | 3
|
|
||||||
2 | 1.6666666666666667 | 4
|
|
||||||
2 | 1.5000000000000000 | 5
|
|
||||||
2 | 1.3333333333333333 | 6
|
|
||||||
3 | 3.0000000000000000 | 1
|
|
||||||
3 | 2.6666666666666667 | 2
|
|
||||||
3 | 2.4000000000000000 | 3
|
|
||||||
3 | 1.00000000000000000000 | 4
|
|
||||||
3 | 1.00000000000000000000 | 4
|
|
||||||
4 | 3.5000000000000000 | 1
|
|
||||||
4 | 3.3333333333333333 | 2
|
|
||||||
4 | 3.2000000000000000 | 3
|
|
||||||
4 | 3.0000000000000000 | 4
|
|
||||||
4 | 1.00000000000000000000 | 5
|
|
||||||
4 | 0.00000000000000000000 | 6
|
|
||||||
5 | 3.2000000000000000 | 1
|
|
||||||
5 | 3.0000000000000000 | 2
|
|
||||||
5 | 3.0000000000000000 | 2
|
|
||||||
5 | 2.8750000000000000 | 4
|
|
||||||
5 | 2.3333333333333333 | 5
|
|
||||||
5 | 1.6000000000000000 | 6
|
|
||||||
6 | 4.0000000000000000 | 1
|
|
||||||
6 | 2.5000000000000000 | 2
|
|
||||||
6 | 2.0000000000000000 | 3
|
|
||||||
6 | 1.3333333333333333 | 4
|
|
||||||
6 | 1.00000000000000000000 | 5
|
|
||||||
(32 rows)
|
|
||||||
|
|
||||||
-- limit is not pushed down to worker !!
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC
|
|
||||||
LIMIT 5;
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan.user_id, (pg_catalog.sum(((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))) / pg_catalog.sum(remote_scan.rank)) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id, remote_scan.worker_column_5
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> 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
|
|
||||||
(16 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + avg(value_1)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC
|
|
||||||
LIMIT 5;
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan.user_id, (pg_catalog.sum(((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))) / pg_catalog.sum(remote_scan.rank)) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id, remote_scan.worker_column_5
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> 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
|
|
||||||
(16 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by 1 / (1 + sum(value_2)))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC
|
|
||||||
LIMIT 5;
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan.user_id, (pg_catalog.sum(((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))) / pg_catalog.sum(remote_scan.rank)) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id, remote_scan.worker_column_5
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> 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
|
|
||||||
(16 rows)
|
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE)
|
|
||||||
SELECT
|
|
||||||
user_id,
|
|
||||||
avg(value_1),
|
|
||||||
RANK() OVER (partition by user_id order by sum(value_2))
|
|
||||||
FROM
|
|
||||||
users_table
|
|
||||||
GROUP BY user_id, value_2
|
|
||||||
ORDER BY user_id, avg(value_1) DESC
|
|
||||||
LIMIT 5;
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
Limit
|
|
||||||
-> Sort
|
|
||||||
Sort Key: remote_scan.user_id, (pg_catalog.sum(((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))) / pg_catalog.sum(remote_scan.rank)) DESC
|
|
||||||
-> HashAggregate
|
|
||||||
Group Key: remote_scan.user_id, remote_scan.worker_column_5
|
|
||||||
-> Custom Scan (Citus Real-Time)
|
|
||||||
Task Count: 4
|
|
||||||
Tasks Shown: One of 4
|
|
||||||
-> Task
|
|
||||||
Node: host=localhost port=57637 dbname=regression
|
|
||||||
-> 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
|
|
||||||
(16 rows)
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
\endif
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 20030000;
|
SET citus.next_shard_id TO 20030000;
|
||||||
|
|
||||||
CREATE USER procedureuser;
|
CREATE USER procedureuser;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@
|
||||||
-- we don't mark transactions with ANALYZE as critical anymore, and
|
-- we don't mark transactions with ANALYZE as critical anymore, and
|
||||||
-- get WARNINGs instead of ERRORs.
|
-- get WARNINGs instead of ERRORs.
|
||||||
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 12000000;
|
SET citus.next_shard_id TO 12000000;
|
||||||
|
|
||||||
SELECT citus.mitmproxy('conn.allow()');
|
SELECT citus.mitmproxy('conn.allow()');
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
-- there is foreign key relation between reference
|
-- there is foreign key relation between reference
|
||||||
-- tables and distributed tables
|
-- tables and distributed tables
|
||||||
--
|
--
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
CREATE SCHEMA test_fkey_to_ref_in_tx;
|
CREATE SCHEMA test_fkey_to_ref_in_tx;
|
||||||
SET search_path TO 'test_fkey_to_ref_in_tx';
|
SET search_path TO 'test_fkey_to_ref_in_tx';
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
--
|
--
|
||||||
-- FOREIGN_KEY_TO_REFERENCE_TABLE
|
-- FOREIGN_KEY_TO_REFERENCE_TABLE
|
||||||
--
|
--
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
CREATE SCHEMA fkey_reference_table;
|
CREATE SCHEMA fkey_reference_table;
|
||||||
SET search_path TO 'fkey_reference_table';
|
SET search_path TO 'fkey_reference_table';
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@
|
||||||
-- MULTI_CREATE_TABLE_NEW_FEATURES
|
-- MULTI_CREATE_TABLE_NEW_FEATURES
|
||||||
--
|
--
|
||||||
|
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
-- Verify that the GENERATED ... AS IDENTITY feature in PostgreSQL 10
|
-- Verify that the GENERATED ... AS IDENTITY feature in PostgreSQL 10
|
||||||
-- is forbidden in distributed tables.
|
-- is forbidden in distributed tables.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,3 @@
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 11 AS server_verion_eleven_and_above
|
|
||||||
\gset
|
|
||||||
\if :server_verion_eleven_and_above
|
|
||||||
\else
|
|
||||||
\q
|
|
||||||
\endif
|
|
||||||
--
|
--
|
||||||
-- Regression tests for deparsing ALTER/DROP PROCEDURE Queries
|
-- Regression tests for deparsing ALTER/DROP PROCEDURE Queries
|
||||||
--
|
--
|
||||||
|
|
@ -43,10 +36,6 @@ SET search_path TO procedure_tests;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET client_min_messages TO INFO;
|
SET client_min_messages TO INFO;
|
||||||
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
CREATE FUNCTION deparse_test(text)
|
CREATE FUNCTION deparse_test(text)
|
||||||
RETURNS text
|
RETURNS text
|
||||||
AS 'citus'
|
AS 'citus'
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,6 @@
|
||||||
|
|
||||||
SET citus.next_shard_id TO 570000;
|
SET citus.next_shard_id TO 570000;
|
||||||
|
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
\a\t
|
\a\t
|
||||||
|
|
||||||
RESET citus.task_executor_type;
|
RESET citus.task_executor_type;
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@
|
||||||
-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed
|
-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed
|
||||||
-- tables.
|
-- tables.
|
||||||
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- CREATE TEST TABLES
|
-- CREATE TEST TABLES
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
-- if the output of following query changes, we might need to change
|
-- if the output of following query changes, we might need to change
|
||||||
-- some heap_getattr() calls to heap_deform_tuple(). This errors out in
|
-- some heap_getattr() calls to heap_deform_tuple().
|
||||||
-- postgres versions before 11.
|
|
||||||
SELECT attrelid::regclass, attname, atthasmissing, attmissingval
|
SELECT attrelid::regclass, attname, atthasmissing, attmissingval
|
||||||
FROM pg_attribute
|
FROM pg_attribute
|
||||||
WHERE atthasmissing
|
WHERE atthasmissing
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,6 @@
|
||||||
-- Test user permissions.
|
-- Test user permissions.
|
||||||
--
|
--
|
||||||
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
SET citus.next_shard_id TO 1420000;
|
SET citus.next_shard_id TO 1420000;
|
||||||
|
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@ SET citus.next_shard_id TO 1660000;
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS server_version_above_ten;
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Distributed Partitioned Table Creation Tests
|
-- Distributed Partitioned Table Creation Tests
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
-- This test has different output per major version
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- create test functions
|
-- create test functions
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,6 @@
|
||||||
SET citus.next_shard_id TO 690000;
|
SET citus.next_shard_id TO 690000;
|
||||||
SET citus.enable_unique_job_ids TO off;
|
SET citus.enable_unique_job_ids TO off;
|
||||||
|
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET client_min_messages TO DEBUG4;
|
SET client_min_messages TO DEBUG4;
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
SET citus.task_executor_type TO 'task-tracker';
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,6 @@
|
||||||
|
|
||||||
SET citus.next_shard_id TO 710000;
|
SET citus.next_shard_id TO 710000;
|
||||||
|
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET client_min_messages TO DEBUG3;
|
SET client_min_messages TO DEBUG3;
|
||||||
SET citus.task_executor_type TO 'task-tracker';
|
SET citus.task_executor_type TO 'task-tracker';
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
SET citus.next_shard_id TO 880000;
|
SET citus.next_shard_id TO 880000;
|
||||||
|
|
||||||
-- print whether we're using version > 9 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine;
|
|
||||||
|
|
||||||
-- the function simply parses the results and returns 'shardId@worker'
|
-- the function simply parses the results and returns 'shardId@worker'
|
||||||
-- for all the explain task outputs
|
-- for all the explain task outputs
|
||||||
CREATE OR REPLACE FUNCTION parse_explain_output(in qry text, in table_name text, out r text)
|
CREATE OR REPLACE FUNCTION parse_explain_output(in qry text, in table_name text, out r text)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
SET citus.next_shard_id TO 990000;
|
SET citus.next_shard_id TO 990000;
|
||||||
-- print server version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 as version_above_ten;
|
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- test utility statement functionality
|
-- test utility statement functionality
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,6 @@
|
||||||
-- router queries, single row inserts, multi row inserts via insert
|
-- router queries, single row inserts, multi row inserts via insert
|
||||||
-- into select, multi row insert via copy commands.
|
-- into select, multi row insert via copy commands.
|
||||||
|
|
||||||
-- print whether we're using version > 10 to make version-specific tests clear
|
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int > 10 AS version_above_ten;
|
|
||||||
|
|
||||||
SELECT count(*) FROM lineitem_hash_part;
|
SELECT count(*) FROM lineitem_hash_part;
|
||||||
|
|
||||||
SELECT count(*) FROM orders_hash_part;
|
SELECT count(*) FROM orders_hash_part;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
---
|
---
|
||||||
--- tests around access tracking within transaction blocks
|
--- tests around access tracking within transaction blocks
|
||||||
---
|
---
|
||||||
SHOW server_version \gset
|
|
||||||
SELECT substring(:'server_version', '\d+')::int >= 10 AS version_ten_or_above;
|
|
||||||
|
|
||||||
CREATE SCHEMA access_tracking;
|
CREATE SCHEMA access_tracking;
|
||||||
SET search_path TO 'access_tracking';
|
SET search_path TO 'access_tracking';
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue