add a UDF to update colocation (#3623)

If two tables have the same distribution column type, we implicitly
colocate them. This is useful since colocation has a big performance
impact in most applications.

When a table is rebalanced, all of the colocated tables are also
rebalanced. If table A and table B are colocated and we want to
rebalance table A, table B will also be rebalanced. We need replica
identity so that logical replication can replicate updates and deletes
during rebalancing. If table B does not have a replica identity we
error out.

A solution to this is to introduce a UDF so that colocation can be
updated. The remaining tables in the colocation group will stay
colocated. For example if table A, B and C are colocated and after
updating table B's colocations, table A and table C stay colocated.

The "updating colocation" step does not move any data around, it only
updated pg_dist_partition and pg_dist_colocation tables. Specifically it
creates a new colocation group for the table and updates the entry in
pg_dist_partition while invalidating any cache.
pull/3635/head
SaitTalhaNisanci 2020-03-23 13:22:24 +03:00 committed by GitHub
parent 3e980c81e9
commit 3df578010e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 692 additions and 20 deletions

View File

@ -574,7 +574,7 @@ ColocationIdForNewTable(Oid relationId, Var *distributionColumn,
createdColocationGroup = true;
}
}
else if (pg_strncasecmp(colocateWithTableName, "none", NAMEDATALEN) == 0)
else if (IsColocateWithNone(colocateWithTableName))
{
colocationId = GetNextColocationId();

View File

@ -1389,6 +1389,39 @@ EnsureFunctionOwner(Oid functionId)
}
/*
* EnsureHashDistributedTable error out if the given relation is not a hash distributed table
* with the given message.
*/
void
EnsureHashDistributedTable(Oid relationId)
{
if (!IsHashDistributedTable(relationId))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("relation %s should be a "
"hash distributed table", get_rel_name(relationId))));
}
}
/*
* IsDistributedTable returns true if the given relation is
* a distributed table.
*/
bool
IsHashDistributedTable(Oid relationId)
{
CitusTableCacheEntry *sourceTableEntry = GetCitusTableCacheEntry(relationId);
if (sourceTableEntry == NULL)
{
return false;
}
char sourceDistributionMethod = sourceTableEntry->partitionMethod;
return sourceDistributionMethod == DISTRIBUTE_BY_HASH;
}
/*
* EnsureSuperUser check that the current user is a superuser and errors out if not.
*/

View File

@ -3,3 +3,4 @@
/* bump version to 9.3-1 */
#include "udfs/citus_extradata_container/9.3-1.sql"
#include "udfs/update_distributed_table_colocation/9.3-1.sql"

View File

@ -0,0 +1,6 @@
CREATE OR REPLACE FUNCTION pg_catalog.update_distributed_table_colocation(table_name regclass, colocate_with text)
RETURNS void
LANGUAGE C STRICT
AS 'MODULE_PATHNAME', $$update_distributed_table_colocation$$;
COMMENT ON FUNCTION pg_catalog.update_distributed_table_colocation(table_name regclass, colocate_with text)
IS 'updates colocation of a table';

View File

@ -0,0 +1,6 @@
CREATE OR REPLACE FUNCTION pg_catalog.update_distributed_table_colocation(table_name regclass, colocate_with text)
RETURNS void
LANGUAGE C STRICT
AS 'MODULE_PATHNAME', $$update_distributed_table_colocation$$;
COMMENT ON FUNCTION pg_catalog.update_distributed_table_colocation(table_name regclass, colocate_with text)
IS 'updates colocation of a table';

View File

@ -50,11 +50,13 @@ static int CompareShardPlacementsByNode(const void *leftElement,
static void UpdateRelationColocationGroup(Oid distributedRelationId, uint32 colocationId);
static List * ColocationGroupTableList(Oid colocationId);
static void DeleteColocationGroup(uint32 colocationId);
static uint32 CreateColocationGroupForRelation(Oid sourceRelationId);
static void BreakColocation(Oid sourceRelationId);
/* exports for SQL callable functions */
PG_FUNCTION_INFO_V1(mark_tables_colocated);
PG_FUNCTION_INFO_V1(get_colocated_shard_array);
PG_FUNCTION_INFO_V1(update_distributed_table_colocation);
/*
@ -96,6 +98,74 @@ mark_tables_colocated(PG_FUNCTION_ARGS)
}
/*
* update_distributed_table_colocation updates the colocation of a table.
* if colocate_with -> 'none' then the table is assigned a new
* colocation group.
*/
Datum
update_distributed_table_colocation(PG_FUNCTION_ARGS)
{
Oid targetRelationId = PG_GETARG_OID(0);
text *colocateWithTableNameText = PG_GETARG_TEXT_P(1);
CheckCitusVersion(ERROR);
EnsureCoordinator();
EnsureTableOwner(targetRelationId);
EnsureHashDistributedTable(targetRelationId);
char *colocateWithTableName = text_to_cstring(colocateWithTableNameText);
if (IsColocateWithNone(colocateWithTableName))
{
BreakColocation(targetRelationId);
}
else
{
Oid colocateWithTableId = ResolveRelationId(colocateWithTableNameText, false);
EnsureHashDistributedTable(colocateWithTableId);
MarkTablesColocated(colocateWithTableId, targetRelationId);
}
PG_RETURN_VOID();
}
/*
* IsColocateWithNone returns true if the given table is
* the special keyword "none".
*/
bool
IsColocateWithNone(char *colocateWithTableName)
{
return pg_strncasecmp(colocateWithTableName, "none", NAMEDATALEN) == 0;
}
/*
* BreakColocation breaks the colocations of the given relation id.
* If t1, t2 and t3 are colocated and we call this function with t2,
* t1 and t3 will stay colocated but t2 will have a new colocation id.
* Note that this function does not move any data around for the new colocation.
*/
static void
BreakColocation(Oid sourceRelationId)
{
/*
* Get an exclusive lock on the colocation system catalog. Therefore, we
* can be sure that there will no modifications on the colocation table
* until this transaction is committed.
*/
Relation pgDistColocation = heap_open(DistColocationRelationId(), ExclusiveLock);
uint32 newColocationId = GetNextColocationId();
UpdateRelationColocationGroup(sourceRelationId, newColocationId);
/* if there is not any remaining table in the colocation group, delete it */
DeleteColocationGroupIfNoTablesBelong(sourceRelationId);
heap_close(pgDistColocation, NoLock);
}
/*
* get_colocated_shards_array returns array of shards ids which are co-located with given
* shard.
@ -131,6 +201,36 @@ get_colocated_shard_array(PG_FUNCTION_ARGS)
}
/*
* CreateColocationGroupForRelation creates colocation entry in
* pg_dist_colocation and updated the colocation id in pg_dist_partition
* for the given relation.
*/
static uint32
CreateColocationGroupForRelation(Oid sourceRelationId)
{
uint32 shardCount = ShardIntervalCount(sourceRelationId);
uint32 shardReplicationFactor = TableShardReplicationFactor(sourceRelationId);
Var *sourceDistributionColumn = DistPartitionKey(sourceRelationId);
Oid sourceDistributionColumnType = InvalidOid;
Oid sourceDistributionColumnCollation = InvalidOid;
/* reference tables has NULL distribution column */
if (sourceDistributionColumn != NULL)
{
sourceDistributionColumnType = sourceDistributionColumn->vartype;
sourceDistributionColumnCollation = sourceDistributionColumn->varcollid;
}
uint32 sourceColocationId = CreateColocationGroup(shardCount, shardReplicationFactor,
sourceDistributionColumnType,
sourceDistributionColumnCollation);
UpdateRelationColocationGroup(sourceRelationId, sourceColocationId);
return sourceColocationId;
}
/*
* MarkTablesColocated puts both tables to same colocation group. If the
* source table is in INVALID_COLOCATION_ID group, then it creates a new
@ -160,24 +260,7 @@ MarkTablesColocated(Oid sourceRelationId, Oid targetRelationId)
uint32 sourceColocationId = TableColocationId(sourceRelationId);
if (sourceColocationId == INVALID_COLOCATION_ID)
{
uint32 shardCount = ShardIntervalCount(sourceRelationId);
uint32 shardReplicationFactor = TableShardReplicationFactor(sourceRelationId);
Var *sourceDistributionColumn = DistPartitionKey(sourceRelationId);
Oid sourceDistributionColumnType = InvalidOid;
Oid sourceDistributionColumnCollation = InvalidOid;
/* reference tables has NULL distribution column */
if (sourceDistributionColumn != NULL)
{
sourceDistributionColumnType = sourceDistributionColumn->vartype;
sourceDistributionColumnCollation = sourceDistributionColumn->varcollid;
}
sourceColocationId = CreateColocationGroup(shardCount, shardReplicationFactor,
sourceDistributionColumnType,
sourceDistributionColumnCollation);
UpdateRelationColocationGroup(sourceRelationId, sourceColocationId);
sourceColocationId = CreateColocationGroupForRelation(sourceRelationId);
}
uint32 targetColocationId = TableColocationId(targetRelationId);

View File

@ -30,6 +30,7 @@ uint32 ColocationId(int shardCount, int replicationFactor, Oid distributionColum
extern uint32 CreateColocationGroup(int shardCount, int replicationFactor,
Oid distributionColumnType,
Oid distributionColumnCollation);
extern bool IsColocateWithNone(char *colocateWithTableName);
extern uint32 GetNextColocationId(void);
extern void CheckReplicationModel(Oid sourceRelationId, Oid targetRelationId);
extern void CheckDistributionColumnType(Oid sourceRelationId, Oid targetRelationId);

View File

@ -148,6 +148,8 @@ extern char * TableOwner(Oid relationId);
extern void EnsureTablePermissions(Oid relationId, AclMode mode);
extern void EnsureTableOwner(Oid relationId);
extern void EnsureSchemaOwner(Oid schemaId);
extern void EnsureHashDistributedTable(Oid relationId);
extern bool IsHashDistributedTable(Oid relationId);
extern void EnsureSequenceOwner(Oid sequenceOid);
extern void EnsureFunctionOwner(Oid functionId);
extern void EnsureSuperUser(void);

View File

@ -1032,6 +1032,407 @@ SELECT create_distributed_table('table2_groupG', 'id', colocate_with => 'NONE');
SELECT mark_tables_colocated('table1_groupG', ARRAY['table2_groupG']);
ERROR: cannot colocate tables table1_groupg and table2_groupg
DETAIL: Replication models don't match for table1_groupg and table2_groupg.
CREATE TABLE d1(a int, b int);
CREATE TABLE d2(a int, b int);
CREATE TABLE d3(a int, b int);
CREATE TABLE d4(a int, b int);
CREATE TABLE different_d1(ch char);
CREATE TABLE append_table(a int, b int);
CREATE TABLE range_table(a int, b int);
-- special keyword none
CREATE TABLE none(a int, b int);
CREATE TABLE ref(a int);
CREATE TABLE local_table(a int);
SELECT create_distributed_table('d1', 'a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('d2', 'a', colocate_with => 'd1');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('d3', 'a', colocate_with => 'd2');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('d4', 'a', colocate_with => 'd3');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('none', 'a', colocate_with => 'd4');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('different_d1', 'ch');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('append_table', 'a', 'append');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('range_table', 'a', 'range');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_reference_table('ref');
create_reference_table
---------------------------------------------------------------------
(1 row)
-- check d1, d2, d3 and d4 has the same colocation id => they are colocated.
SELECT get_table_colocation_id('d1');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d2');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d3');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d4');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT tables_colocated('d1', 'd2');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d2', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d2', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d3', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
-- break colocation of d2
SELECT update_distributed_table_colocation('d2', colocate_with => 'none');
update_distributed_table_colocation
---------------------------------------------------------------------
(1 row)
-- d1 and d3 and d4 should be colocated, d2 should have a new colocation id.
SELECT get_table_colocation_id('d1');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d2');
get_table_colocation_id
---------------------------------------------------------------------
11
(1 row)
SELECT get_table_colocation_id('d3');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d4');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT tables_colocated('d1', 'd2');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d2', 'd3');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d1', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
-- break colocation of d2
-- update colocation should not error if d2 doesn't have any colocated table.
SELECT update_distributed_table_colocation('d2', colocate_with => 'none');
update_distributed_table_colocation
---------------------------------------------------------------------
(1 row)
-- d1 and d3 and d4 should be colocated, d2 should have a new colocation id.
SELECT get_table_colocation_id('d1');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d2');
get_table_colocation_id
---------------------------------------------------------------------
12
(1 row)
SELECT get_table_colocation_id('d3');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d4');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT tables_colocated('d1', 'd2');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d2', 'd3');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d1', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT update_distributed_table_colocation('d3', colocate_with => 'd2');
update_distributed_table_colocation
---------------------------------------------------------------------
(1 row)
-- d1 and d4 should be colocated, d2 and d3 should be colocated.
SELECT get_table_colocation_id('d1');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d2');
get_table_colocation_id
---------------------------------------------------------------------
12
(1 row)
SELECT get_table_colocation_id('d3');
get_table_colocation_id
---------------------------------------------------------------------
12
(1 row)
SELECT get_table_colocation_id('d4');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT tables_colocated('d1', 'd2');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d2', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd3');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d1', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
-- special case, colocate with a table named "none".
SELECT update_distributed_table_colocation('d3', colocate_with => '"none"');
update_distributed_table_colocation
---------------------------------------------------------------------
(1 row)
-- d1, d4, d3 and "none" should be colocated;
SELECT get_table_colocation_id('d1');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d2');
get_table_colocation_id
---------------------------------------------------------------------
12
(1 row)
SELECT get_table_colocation_id('d3');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('d4');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT get_table_colocation_id('none');
get_table_colocation_id
---------------------------------------------------------------------
8
(1 row)
SELECT tables_colocated('d1', 'd2');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d2', 'd3');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
SELECT tables_colocated('d1', 'd3');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'd4');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d1', 'none');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d4', 'none');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d3', 'none');
tables_colocated
---------------------------------------------------------------------
t
(1 row)
SELECT tables_colocated('d2', 'none');
tables_colocated
---------------------------------------------------------------------
f
(1 row)
-- make sure reference and local tables return an error.
SELECT update_distributed_table_colocation('ref', colocate_with => 'none');
ERROR: relation ref should be a hash distributed table
SELECT update_distributed_table_colocation('local_table', colocate_with => 'none');
ERROR: relation local_table is not distributed
-- make sure that different types cannot be colocated
SELECT update_distributed_table_colocation('different_d1', colocate_with => 'd1');
ERROR: cannot colocate tables d1 and different_d1
DETAIL: Distribution column types don't match for d1 and different_d1.
SELECT update_distributed_table_colocation('d1', colocate_with => 'different_d1');
ERROR: cannot colocate tables different_d1 and d1
DETAIL: Distribution column types don't match for different_d1 and d1.
-- make sure that append distributed tables cannot be colocated
SELECT update_distributed_table_colocation('append_table', colocate_with => 'd1');
ERROR: relation append_table should be a hash distributed table
SELECT update_distributed_table_colocation('d1', colocate_with => 'append_table');
ERROR: relation append_table should be a hash distributed table
SELECT update_distributed_table_colocation('range_table', colocate_with => 'd1');
ERROR: relation range_table should be a hash distributed table
SELECT update_distributed_table_colocation('d1', colocate_with => 'range_table');
ERROR: relation range_table should be a hash distributed table
-- drop tables to clean test space
DROP TABLE table1_groupb;
DROP TABLE table2_groupb;
@ -1055,3 +1456,13 @@ DROP TABLE table1_group_none_3;
DROP TABLE table1_group_none;
DROP TABLE table2_group_none;
DROP TABLE table1_group_default;
DROP TABLE d1;
DROP TABLE d2;
DROP TABLE d3;
DROP TABLE d4;
DROP TABLE different_d1;
DROP TABLE append_table;
DROP TABLE range_table;
DROP TABLE none;
DROP TABLE ref;
DROP TABLE local_table;

View File

@ -92,6 +92,7 @@ SELECT master_create_distributed_table('table6_append', 'id', 'append');
SELECT master_create_empty_shard('table6_append');
SELECT master_create_empty_shard('table6_append');
-- make table1_group1 and table2_group1 co-located manually
SELECT colocation_test_colocate_tables('table1_group1', 'table2_group1');
@ -430,6 +431,122 @@ SELECT create_distributed_table('table2_groupG', 'id', colocate_with => 'NONE');
SELECT mark_tables_colocated('table1_groupG', ARRAY['table2_groupG']);
CREATE TABLE d1(a int, b int);
CREATE TABLE d2(a int, b int);
CREATE TABLE d3(a int, b int);
CREATE TABLE d4(a int, b int);
CREATE TABLE different_d1(ch char);
CREATE TABLE append_table(a int, b int);
CREATE TABLE range_table(a int, b int);
-- special keyword none
CREATE TABLE none(a int, b int);
CREATE TABLE ref(a int);
CREATE TABLE local_table(a int);
SELECT create_distributed_table('d1', 'a');
SELECT create_distributed_table('d2', 'a', colocate_with => 'd1');
SELECT create_distributed_table('d3', 'a', colocate_with => 'd2');
SELECT create_distributed_table('d4', 'a', colocate_with => 'd3');
SELECT create_distributed_table('none', 'a', colocate_with => 'd4');
SELECT create_distributed_table('different_d1', 'ch');
SELECT create_distributed_table('append_table', 'a', 'append');
SELECT create_distributed_table('range_table', 'a', 'range');
SELECT create_reference_table('ref');
-- check d1, d2, d3 and d4 has the same colocation id => they are colocated.
SELECT get_table_colocation_id('d1');
SELECT get_table_colocation_id('d2');
SELECT get_table_colocation_id('d3');
SELECT get_table_colocation_id('d4');
SELECT tables_colocated('d1', 'd2');
SELECT tables_colocated('d2', 'd3');
SELECT tables_colocated('d2', 'd4');
SELECT tables_colocated('d3', 'd4');
SELECT tables_colocated('d1', 'd3');
SELECT tables_colocated('d1', 'd4');
-- break colocation of d2
SELECT update_distributed_table_colocation('d2', colocate_with => 'none');
-- d1 and d3 and d4 should be colocated, d2 should have a new colocation id.
SELECT get_table_colocation_id('d1');
SELECT get_table_colocation_id('d2');
SELECT get_table_colocation_id('d3');
SELECT get_table_colocation_id('d4');
SELECT tables_colocated('d1', 'd2');
SELECT tables_colocated('d2', 'd3');
SELECT tables_colocated('d1', 'd3');
SELECT tables_colocated('d1', 'd4');
-- break colocation of d2
-- update colocation should not error if d2 doesn't have any colocated table.
SELECT update_distributed_table_colocation('d2', colocate_with => 'none');
-- d1 and d3 and d4 should be colocated, d2 should have a new colocation id.
SELECT get_table_colocation_id('d1');
SELECT get_table_colocation_id('d2');
SELECT get_table_colocation_id('d3');
SELECT get_table_colocation_id('d4');
SELECT tables_colocated('d1', 'd2');
SELECT tables_colocated('d2', 'd3');
SELECT tables_colocated('d1', 'd3');
SELECT tables_colocated('d1', 'd4');
SELECT update_distributed_table_colocation('d3', colocate_with => 'd2');
-- d1 and d4 should be colocated, d2 and d3 should be colocated.
SELECT get_table_colocation_id('d1');
SELECT get_table_colocation_id('d2');
SELECT get_table_colocation_id('d3');
SELECT get_table_colocation_id('d4');
SELECT tables_colocated('d1', 'd2');
SELECT tables_colocated('d2', 'd3');
SELECT tables_colocated('d1', 'd3');
SELECT tables_colocated('d1', 'd4');
-- special case, colocate with a table named "none".
SELECT update_distributed_table_colocation('d3', colocate_with => '"none"');
-- d1, d4, d3 and "none" should be colocated;
SELECT get_table_colocation_id('d1');
SELECT get_table_colocation_id('d2');
SELECT get_table_colocation_id('d3');
SELECT get_table_colocation_id('d4');
SELECT get_table_colocation_id('none');
SELECT tables_colocated('d1', 'd2');
SELECT tables_colocated('d2', 'd3');
SELECT tables_colocated('d1', 'd3');
SELECT tables_colocated('d1', 'd4');
SELECT tables_colocated('d1', 'none');
SELECT tables_colocated('d4', 'none');
SELECT tables_colocated('d3', 'none');
SELECT tables_colocated('d2', 'none');
-- make sure reference and local tables return an error.
SELECT update_distributed_table_colocation('ref', colocate_with => 'none');
SELECT update_distributed_table_colocation('local_table', colocate_with => 'none');
-- make sure that different types cannot be colocated
SELECT update_distributed_table_colocation('different_d1', colocate_with => 'd1');
SELECT update_distributed_table_colocation('d1', colocate_with => 'different_d1');
-- make sure that append distributed tables cannot be colocated
SELECT update_distributed_table_colocation('append_table', colocate_with => 'd1');
SELECT update_distributed_table_colocation('d1', colocate_with => 'append_table');
SELECT update_distributed_table_colocation('range_table', colocate_with => 'd1');
SELECT update_distributed_table_colocation('d1', colocate_with => 'range_table');
-- drop tables to clean test space
DROP TABLE table1_groupb;
DROP TABLE table2_groupb;
@ -453,3 +570,15 @@ DROP TABLE table1_group_none_3;
DROP TABLE table1_group_none;
DROP TABLE table2_group_none;
DROP TABLE table1_group_default;
DROP TABLE d1;
DROP TABLE d2;
DROP TABLE d3;
DROP TABLE d4;
DROP TABLE different_d1;
DROP TABLE append_table;
DROP TABLE range_table;
DROP TABLE none;
DROP TABLE ref;
DROP TABLE local_table;