/* * ShardStorageType returns the shard storage type according to relation type. */ char ShardStorageType(Oid relationId) { char shardStorageType = 0; char relationType = get_rel_relkind(relationId); if (RegularTable(relationId)) { shardStorageType = SHARD_STORAGE_TABLE; } else if (relationType == RELKIND_FOREIGN_TABLE) { bool cstoreTable = CStoreTable(relationId); if (cstoreTable) { shardStorageType = SHARD_STORAGE_COLUMNAR; } else { shardStorageType = SHARD_STORAGE_FOREIGN; } } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("unexpected relation type: %c", relationType))); } return shardStorageType; }
/* * CreateDistributedTable creates distributed table in the given configuration. * This functions contains all necessary logic to create distributed tables. It * perform necessary checks to ensure distributing the table is safe. If it is * safe to distribute the table, this function creates distributed table metadata, * creates shards and copies local data to shards. This function also handles * partitioned tables by distributing its partitions as well. * * viaDeprecatedAPI boolean flag is not optimal way to implement this function, * but it helps reducing code duplication a lot. We hope to remove that flag one * day, once we deprecate master_create_distribute_table completely. */ void CreateDistributedTable(Oid relationId, Var *distributionColumn, char distributionMethod, char *colocateWithTableName, bool viaDeprecatedAPI) { char replicationModel = REPLICATION_MODEL_INVALID; uint32 colocationId = INVALID_COLOCATION_ID; Oid colocatedTableId = InvalidOid; bool localTableEmpty = false; Relation colocatedRelation = NULL; replicationModel = AppropriateReplicationModel(distributionMethod, viaDeprecatedAPI); /* * ColocationIdForNewTable assumes caller acquires lock on relationId. In our case, * our caller already acquired lock on relationId. */ colocationId = ColocationIdForNewTable(relationId, distributionColumn, distributionMethod, replicationModel, colocateWithTableName, viaDeprecatedAPI); EnsureRelationCanBeDistributed(relationId, distributionColumn, distributionMethod, colocationId, replicationModel, viaDeprecatedAPI); /* we need to calculate these variables before creating distributed metadata */ localTableEmpty = LocalTableEmpty(relationId); colocatedTableId = ColocatedTableId(colocationId); /* create an entry for distributed table in pg_dist_partition */ InsertIntoPgDistPartition(relationId, distributionMethod, distributionColumn, colocationId, replicationModel); /* foreign tables does not support TRUNCATE trigger */ if (RegularTable(relationId)) { CreateTruncateTrigger(relationId); } /* * If we are using master_create_distributed_table, we don't need to continue, * because deprecated API does not supports the following features. */ if (viaDeprecatedAPI) { /* * We exit early but there is no need to close colocatedRelation. Because * if viaDeprecatedAPI is true, we never open colocatedRelation in the first * place. */ Assert(colocatedRelation == NULL); return; } /* create shards for hash distributed and reference tables */ if (distributionMethod == DISTRIBUTE_BY_HASH) { CreateHashDistributedTableShards(relationId, colocatedTableId, localTableEmpty); } else if (distributionMethod == DISTRIBUTE_BY_NONE) { CreateReferenceTableShard(relationId); } if (ShouldSyncTableMetadata(relationId)) { CreateTableMetadataOnWorkers(relationId); } /* * We've a custom way of foreign key graph invalidation, * see InvalidateForeignKeyGraph(). */ if (TableReferenced(relationId) || TableReferencing(relationId)) { InvalidateForeignKeyGraph(); } /* if this table is partitioned table, distribute its partitions too */ if (PartitionedTable(relationId)) { List *partitionList = PartitionList(relationId); ListCell *partitionCell = NULL; foreach(partitionCell, partitionList) { Oid partitionRelationId = lfirst_oid(partitionCell); CreateDistributedTable(partitionRelationId, distributionColumn, distributionMethod, colocateWithTableName, viaDeprecatedAPI); } }