/* * RemoveRewriteRule * * Delete a rule given its name. */ void RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior, bool missing_ok) { HeapTuple tuple; Oid eventRelationOid; ObjectAddress object; /* * Find the tuple for the target rule. */ tuple = SearchSysCache(RULERELNAME, ObjectIdGetDatum(owningRel), PointerGetDatum(ruleName), 0, 0); /* * complain if no rule with such name exists */ if (!HeapTupleIsValid(tuple)) { if (!missing_ok) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("rule \"%s\" for relation \"%s\" does not exist", ruleName, get_rel_name(owningRel)))); else ereport(NOTICE, (errmsg("rule \"%s\" for relation \"%s\" does not exist, skipping", ruleName, get_rel_name(owningRel)))); return; } /* * Verify user has appropriate permissions. */ eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; Assert(eventRelationOid == owningRel); if (!pg_class_ownercheck(eventRelationOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, get_rel_name(eventRelationOid)); /* * Do the deletion */ object.classId = RewriteRelationId; object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; ReleaseSysCache(tuple); performDeletion(&object, behavior); }
/* * get_relation_constraint_oid * Find a constraint on the specified relation with the specified name. * Returns constraint's OID. */ Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok) { Relation pg_constraint; HeapTuple tuple; SysScanDesc scan; ScanKeyData skey[1]; Oid conOid = InvalidOid; /* * Fetch the constraint tuple from pg_constraint. There may be more than * one match, because constraints are not required to have unique names; * if so, error out. */ pg_constraint = heap_open(ConstraintRelationId, AccessShareLock); ScanKeyInit(&skey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relid)); scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true, NULL, 1, skey); while (HeapTupleIsValid(tuple = systable_getnext(scan))) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple); if (strcmp(NameStr(con->conname), conname) == 0) { if (OidIsValid(conOid)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("table \"%s\" has multiple constraints named \"%s\"", get_rel_name(relid), conname))); conOid = HeapTupleGetOid(tuple); } } systable_endscan(scan); /* If no such constraint exists, complain */ if (!OidIsValid(conOid) && !missing_ok) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("constraint \"%s\" for table \"%s\" does not exist", conname, get_rel_name(relid)))); heap_close(pg_constraint, AccessShareLock); return conOid; }
/* * GetStreamPaths */ void GetStreamPaths(PlannerInfo *root, RelOptInfo *baserel, Oid relid) { ForeignPath *path; Cost startup_cost; Cost total_cost; double rows; if (!IsContQueryProcess()) { PlannerInfo *parent = root; /* If the root query is continuous, we can read from streams */ while (parent->parent_root != NULL) parent = parent->parent_root; if (!parent->parse->isContinuous) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is a stream", get_rel_name(relid)), errhint("Streams can only be read by a continuous view's FROM clause."))); } } rows = Min(100, continuous_query_batch_size * 0.25); startup_cost = baserel->baserestrictcost.startup; total_cost = startup_cost + (cpu_tuple_cost * rows); path = create_foreignscan_path(root, baserel, rows, startup_cost, total_cost, NIL, NULL, NULL, NIL); add_path(baserel, (Path *) path); }
char * get_relation_name(Oid relid) { return quote_qualified_identifier( get_namespace_name(get_rel_namespace(relid)), get_rel_name(relid)); }
/* * TableShardReplicationFactor returns the current replication factor of the * given relation by looking into shard placements. It errors out if there * are different number of shard placements for different shards. It also * errors out if the table does not have any shards. */ uint32 TableShardReplicationFactor(Oid relationId) { uint32 replicationCount = 0; ListCell *shardCell = NULL; List *shardIntervalList = LoadShardIntervalList(relationId); foreach(shardCell, shardIntervalList) { ShardInterval *shardInterval = (ShardInterval *) lfirst(shardCell); uint64 shardId = shardInterval->shardId; List *shardPlacementList = ShardPlacementList(shardId); uint32 shardPlacementCount = list_length(shardPlacementList); /* * Get the replication count of the first shard in the list, and error * out if there is a shard with different replication count. */ if (replicationCount == 0) { replicationCount = shardPlacementCount; } else if (replicationCount != shardPlacementCount) { char *relationName = get_rel_name(relationId); ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot find the replication factor of the " "table %s", relationName), errdetail("The shard %ld has different shards replication " "counts from other shards.", shardId))); } }
/* * GenerateAlterTableAttachPartitionCommand returns the necessary command to * attach the given partition to its parent. */ char * GenerateAlterTableAttachPartitionCommand(Oid partitionTableId) { StringInfo createPartitionCommand = makeStringInfo(); #if (PG_VERSION_NUM >= 100000) char *partitionBoundCString = NULL; Oid parentId = InvalidOid; char *tableQualifiedName = NULL; char *parentTableQualifiedName = NULL; if (!PartitionTable(partitionTableId)) { char *relationName = get_rel_name(partitionTableId); ereport(ERROR, (errmsg("\"%s\" is not a partition", relationName))); } parentId = get_partition_parent(partitionTableId); tableQualifiedName = generate_qualified_relation_name(partitionTableId); parentTableQualifiedName = generate_qualified_relation_name(parentId); partitionBoundCString = PartitionBound(partitionTableId); appendStringInfo(createPartitionCommand, "ALTER TABLE %s ATTACH PARTITION %s %s;", parentTableQualifiedName, tableQualifiedName, partitionBoundCString); #endif return createPartitionCommand->data; }
/* * GenerateDetachPartitionCommand gets a partition table and returns * "ALTER TABLE parent_table DETACH PARTITION partitionName" command. */ char * GenerateDetachPartitionCommand(Oid partitionTableId) { StringInfo detachPartitionCommand = makeStringInfo(); #if (PG_VERSION_NUM >= 100000) Oid parentId = InvalidOid; char *tableQualifiedName = NULL; char *parentTableQualifiedName = NULL; if (!PartitionTable(partitionTableId)) { char *relationName = get_rel_name(partitionTableId); ereport(ERROR, (errmsg("\"%s\" is not a partition", relationName))); } parentId = get_partition_parent(partitionTableId); tableQualifiedName = generate_qualified_relation_name(partitionTableId); parentTableQualifiedName = generate_qualified_relation_name(parentId); appendStringInfo(detachPartitionCommand, "ALTER TABLE IF EXISTS %s DETACH PARTITION %s;", parentTableQualifiedName, tableQualifiedName); #endif return detachPartitionCommand->data; }
/* * Takes a parent relation and returns Oid list of its partitions. The * function errors out if the given relation is not a parent. */ List * PartitionList(Oid parentRelationId) { Relation rel = heap_open(parentRelationId, AccessShareLock); List *partitionList = NIL; #if (PG_VERSION_NUM >= 100000) int partitionIndex = 0; int partitionCount = 0; if (!PartitionedTable(parentRelationId)) { char *relationName = get_rel_name(parentRelationId); ereport(ERROR, (errmsg("\"%s\" is not a parent table", relationName))); } Assert(rel->rd_partdesc != NULL); partitionCount = rel->rd_partdesc->nparts; for (partitionIndex = 0; partitionIndex < partitionCount; ++partitionIndex) { partitionList = lappend_oid(partitionList, rel->rd_partdesc->oids[partitionIndex]); } #endif /* keep the lock */ heap_close(rel, NoLock); return partitionList; }
/* * Auto-stats employs this sub-routine to issue an analyze on a specific relation. */ static void autostats_issue_analyze(Oid relationOid) { VacuumStmt *analyzeStmt = NULL; RangeVar *relation = NULL; /* * If this user does not own the table, then auto-stats will not issue the * analyze. */ if (!(pg_class_ownercheck(relationOid, GetUserId()) || (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !IsSharedRelation(relationOid)))) { elog(DEBUG3, "Auto-stats did not issue ANALYZE on tableoid %d since the user does not have table-owner level permissions.", relationOid); return; } relation = makeRangeVar(get_namespace_name(get_rel_namespace(relationOid)), get_rel_name(relationOid), -1); analyzeStmt = makeNode(VacuumStmt); /* Set up command parameters */ analyzeStmt->vacuum = false; analyzeStmt->full = false; analyzeStmt->analyze = true; analyzeStmt->freeze_min_age = -1; analyzeStmt->verbose = false; analyzeStmt->rootonly = false; analyzeStmt->relation = relation; /* not used since we pass relids list */ analyzeStmt->va_cols = NIL; vacuum(analyzeStmt, NIL, NULL, false, false); pfree(analyzeStmt); }
finish_sync_worker(void) { /* * Commit any outstanding transaction. This is the usual case, unless * there was nothing to do for the table. */ if (IsTransactionState()) { CommitTransactionCommand(); pgstat_report_stat(false); } /* And flush all writes. */ XLogFlush(GetXLogWriteRecPtr()); StartTransactionCommand(); ereport(LOG, (errmsg("logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished", MySubscription->name, get_rel_name(MyLogicalRepWorker->relid)))); CommitTransactionCommand(); /* Find the main apply worker and signal it. */ logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid); /* Stop gracefully */ proc_exit(0); }
/* * CreateReferenceTable creates a distributed table with the given relationId. The * created table has one shard and replication factor is set to the active worker * count. In fact, the above is the definition of a reference table in Citus. */ Datum create_reference_table(PG_FUNCTION_ARGS) { Oid relationId = PG_GETARG_OID(0); Relation relation = NULL; char *colocateWithTableName = NULL; List *workerNodeList = NIL; int workerCount = 0; Var *distributionColumn = NULL; bool viaDeprecatedAPI = false; EnsureCoordinator(); CheckCitusVersion(ERROR); /* * Ensure schema exists on each worker node. We can not run this function * transactionally, since we may create shards over separate sessions and * shard creation depends on the schema being present and visible from all * sessions. */ EnsureSchemaExistsOnAllNodes(relationId); /* * Lock target relation with an exclusive lock - there's no way to make * sense of this table until we've committed, and we don't want multiple * backends manipulating this relation. */ relation = relation_open(relationId, ExclusiveLock); /* * We should do this check here since the codes in the following lines rely * on this relation to have a supported relation kind. More extensive checks * will be performed in CreateDistributedTable. */ EnsureRelationKindSupported(relationId); workerNodeList = ActivePrimaryNodeList(); workerCount = list_length(workerNodeList); /* if there are no workers, error out */ if (workerCount == 0) { char *relationName = get_rel_name(relationId); ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot create reference table \"%s\"", relationName), errdetail("There are no active worker nodes."))); } CreateDistributedTable(relationId, distributionColumn, DISTRIBUTE_BY_NONE, colocateWithTableName, viaDeprecatedAPI); relation_close(relation, NoLock); PG_RETURN_VOID(); }
Datum pg_relation_size(PG_FUNCTION_ARGS) { Oid relOid = PG_GETARG_OID(0); text *forkName = PG_GETARG_TEXT_P(1); Relation rel; int64 size = 0; /** * This function is peculiar in that it does its own dispatching. * It does not work on entry db since we do not support dispatching * from entry-db currently. */ if (Gp_role == GP_ROLE_EXECUTE && Gp_segment == -1) elog(ERROR, "This query is not currently supported by GPDB."); rel = try_relation_open(relOid, AccessShareLock, false); /* * While we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for * already-dropped tables than throw an error and abort the whole query. */ if (!RelationIsValid(rel)) PG_RETURN_NULL(); if (relOid == 0 || rel->rd_node.relNode == 0) size = 0; else size = calculate_relation_size(rel, forkname_to_number(text_to_cstring(forkName))); if (Gp_role == GP_ROLE_DISPATCH) { StringInfoData buffer; char *schemaName; char *relName; schemaName = get_namespace_name(get_rel_namespace(relOid)); if (schemaName == NULL) elog(ERROR, "Cannot find schema for oid %d", relOid); relName = get_rel_name(relOid); if (relName == NULL) elog(ERROR, "Cannot find relation for oid %d", relOid); initStringInfo(&buffer); appendStringInfo(&buffer, "select sum(pg_relation_size('%s.%s'))::int8 from gp_dist_random('gp_id');", quote_identifier(schemaName), quote_identifier(relName)); size += get_size_from_segDBs(buffer.data); } relation_close(rel, AccessShareLock); PG_RETURN_INT64(size); }
/* * SetCombinerDestReceiverParams * * Set parameters for a CombinerDestReceiver */ void SetCombinerDestReceiverParams(DestReceiver *self, ContExecutor *exec, ContQuery *query) { CombinerState *c = (CombinerState *) self; char *relname = get_rel_name(query->relid); c->cont_exec = exec; c->cont_query = query; c->name_hash = MurmurHash3_64(relname, strlen(relname), MURMUR_SEED); pfree(relname); }
/* * Get the catalog entry for an exttable relation (from pg_exttable) */ ExtTableEntry* GetExtTableEntry(Oid relid) { ExtTableEntry *extentry; extentry = GetExtTableEntryIfExists(relid); if (!extentry) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("missing pg_exttable entry for relation \"%s\"", get_rel_name(relid)))); return extentry; }
/* Gpmon helpers. */ char * GetScanRelNameGpmon(Oid relid, char schema_rel_name[SCAN_REL_NAME_BUF_SIZE]) { if (relid > 0) { char *relname = get_rel_name(relid); char *schemaname = get_namespace_name(get_rel_namespace(relid)); snprintf(schema_rel_name, SCAN_REL_NAME_BUF_SIZE, "%s.%s", schemaname, relname); if (relname) pfree(relname); if (schemaname) pfree(schemaname); } return schema_rel_name; }
/* * RenameConstraintById * Rename a constraint. * * Note: this isn't intended to be a user-exposed function; it doesn't check * permissions etc. Currently this is only invoked when renaming an index * that is associated with a constraint, but it's made a little more general * than that with the expectation of someday having ALTER TABLE RENAME * CONSTRAINT. */ void RenameConstraintById(Oid conId, const char *newname) { Relation conDesc; HeapTuple tuple; Form_pg_constraint con; conDesc = heap_open(ConstraintRelationId, RowExclusiveLock); tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for constraint %u", conId); con = (Form_pg_constraint) GETSTRUCT(tuple); /* * We need to check whether the name is already in use --- note that there * currently is not a unique index that would catch this. */ if (OidIsValid(con->conrelid) && ConstraintNameIsUsed(CONSTRAINT_RELATION, con->conrelid, con->connamespace, newname)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("constraint \"%s\" for relation \"%s\" already exists", newname, get_rel_name(con->conrelid)))); if (OidIsValid(con->contypid) && ConstraintNameIsUsed(CONSTRAINT_DOMAIN, con->contypid, con->connamespace, newname)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("constraint \"%s\" for domain %s already exists", newname, format_type_be(con->contypid)))); /* OK, do the rename --- tuple is a copy, so OK to scribble on it */ namestrcpy(&(con->conname), newname); simple_heap_update(conDesc, &tuple->t_self, tuple); /* update the system catalog indexes */ CatalogUpdateIndexes(conDesc, tuple); InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0); heap_freetuple(tuple); heap_close(conDesc, RowExclusiveLock); }
static char * get_relation_name(Oid relid) { Oid nsp = get_rel_namespace(relid); char *nspname; /* Qualify the name if not visible in search path */ if (RelationIsVisible(relid)) nspname = NULL; else nspname = get_namespace_name(nsp); return quote_qualified_identifier(nspname, get_rel_name(relid)); }
static char * get_relation_name(Oid relid) { Oid nsp = get_rel_namespace(relid); char *nspname; char *strver; int ver; /* Get the version of the running server (PG_VERSION_NUM would return * the version we compiled the extension with) */ strver = GetConfigOptionByName("server_version_num", NULL #if PG_VERSION_NUM >= 90600 , false /* missing_ok */ #endif ); ver = atoi(strver); pfree(strver); /* * Relation names given by PostgreSQL core are always * qualified since some minor releases. Note that this change * wasn't introduced in PostgreSQL 9.2 and 9.1 releases. */ if ((ver >= 100000 && ver < 100003) || (ver >= 90600 && ver < 90608) || (ver >= 90500 && ver < 90512) || (ver >= 90400 && ver < 90417) || (ver >= 90300 && ver < 90322) || (ver >= 90200 && ver < 90300) || (ver >= 90100 && ver < 90200)) { /* Qualify the name if not visible in search path */ if (RelationIsVisible(relid)) nspname = NULL; else nspname = get_namespace_name(nsp); } else { /* Always qualify the name */ if (OidIsValid(nsp)) nspname = get_namespace_name(nsp); else nspname = NULL; } return quote_qualified_identifier(nspname, get_rel_name(relid)); }
/* * CheckTableSchemaNameForDrop errors out if the current user does not * have permission to undistribute the given relation, taking into * account that it may be called from the drop trigger. If the table exists, * the function rewrites the given table and schema name. */ void CheckTableSchemaNameForDrop(Oid relationId, char **schemaName, char **tableName) { char *tempTableName = get_rel_name(relationId); if (tempTableName != NULL) { /* ensure proper values are used if the table exists */ Oid schemaId = get_rel_namespace(relationId); (*schemaName) = get_namespace_name(schemaId); (*tableName) = tempTableName; EnsureTableOwner(relationId); } }
/* * sepgsql_relation_relabel * * It checks privileges to relabel the supplied relation by the `seclabel'. */ void sepgsql_relation_relabel(Oid relOid, const char *seclabel) { char *scontext = sepgsql_get_client_label(); char *tcontext; char *audit_name; char relkind; uint16_t tclass = 0; relkind = get_rel_relkind(relOid); if (relkind == RELKIND_RELATION) tclass = SEPG_CLASS_DB_TABLE; else if (relkind == RELKIND_SEQUENCE) tclass = SEPG_CLASS_DB_SEQUENCE; else if (relkind == RELKIND_VIEW) tclass = SEPG_CLASS_DB_VIEW; else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot set security labels on relations except " "for tables, sequences or views"))); audit_name = get_rel_name(relOid); /* * check db_xxx:{setattr relabelfrom} permission */ tcontext = sepgsql_get_label(RelationRelationId, relOid, 0); sepgsql_check_perms(scontext, tcontext, tclass, SEPG_DB_TABLE__SETATTR | SEPG_DB_TABLE__RELABELFROM, audit_name, true); pfree(tcontext); /* * check db_xxx:{relabelto} permission */ sepgsql_check_perms(scontext, seclabel, tclass, SEPG_DB_TABLE__RELABELTO, audit_name, true); }
void initGpmonPktForIndexScan(Plan *planNode, gpmon_packet_t *gpmon_pkt, EState *estate) { Assert(planNode != NULL && gpmon_pkt != NULL && IsA(planNode, IndexScan)); { char *relname = get_rel_name(((IndexScan *)planNode)->indexid); Assert(GPMON_INDEXSCAN_TOTAL <= (int) GPMON_QEXEC_M_COUNT); InitPlanNodeGpmonPkt(planNode, gpmon_pkt, estate, PMNT_IndexScan, (int64)planNode->plan_rows, relname); if (relname) pfree(relname); } }
void initGpmonPktForBitmapIndexScan(Plan *planNode, gpmon_packet_t *gpmon_pkt, EState *estate) { Assert(NULL != planNode && NULL != gpmon_pkt && IsA(planNode, BitmapIndexScan)); { char *relname = get_rel_name(((BitmapIndexScan *)planNode)->indexid); Assert(GPMON_BITMAPINDEXSCAN_TOTAL <= (int)GPMON_QEXEC_M_COUNT); InitPlanNodeGpmonPkt(planNode, gpmon_pkt, estate, PMNT_BitmapIndexScan, (int64)planNode->plan_rows, relname); if (NULL != relname) { pfree(relname); } } }
/* * truncate relation */ void TruncateTable(Oid relid) { TruncateStmt stmt; RangeVar *heap; Assert(OidIsValid(relid)); heap = makeRangeVar(get_namespace_name(get_rel_namespace(relid)), get_rel_name(relid), -1); memset(&stmt, 0, sizeof(stmt)); stmt.type = T_TruncateStmt; stmt.relations = list_make1(heap); stmt.behavior = DROP_RESTRICT; ExecuteTruncate(&stmt); CommandCounterIncrement(); }
/* * create_reference_table accepts a table and then it creates a distributed * table which has one shard and replication factor is set to * shard_replication_factor configuration value. */ Datum create_reference_table(PG_FUNCTION_ARGS) { Oid relationId = PG_GETARG_OID(0); int shardCount = 1; AttrNumber firstColumnAttrNumber = 1; char *firstColumnName = get_attname(relationId, firstColumnAttrNumber); if (firstColumnName == NULL) { char *relationName = get_rel_name(relationId); ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("reference table candidate %s needs to have at" "least one column", relationName))); } CreateHashDistributedTable(relationId, firstColumnName, shardCount, ShardReplicationFactor); PG_RETURN_VOID(); }
/* * infer_tupledesc * * Given a stream, infer a TupleDesc based on the supertype of all * the casted types for each of the stream's columns */ static void infer_tupledesc(StreamTargetsEntry *stream) { HASH_SEQ_STATUS status; StreamColumnsEntry *entry; List *names = NIL; List *types = NIL; List *mods = NIL; List *collations = NIL; Const *preferred = makeConst(NUMERIC_OID, -1, 0, -1, 0, false, false); hash_seq_init(&status, stream->colstotypes); while ((entry = (StreamColumnsEntry *) hash_seq_search(&status)) != NULL) { char err[128]; Oid supertype; char category; bool typispreferred; Oid t = exprType(linitial(entry->types)); /* * If there are any numeric types in our target types, we prepend a float8 * to the list of types to select from, as that is our preferred type when * there is any ambiguity about how to interpret numeric types. */ get_type_category_preferred(t, &category, &typispreferred); if (category == TYPCATEGORY_NUMERIC) entry->types = lcons(preferred, entry->types); sprintf(err, "type conflict with stream \"%s\":", get_rel_name(stream->relid)); supertype = select_common_type(NULL, entry->types, err, NULL); names = lappend(names, makeString(entry->name)); types = lappend_int(types, supertype); mods = lappend_int(mods, -1); collations = lappend_int(collations, 0); } stream->desc = BuildDescFromLists(names, types, mods, collations); }
Bitmapset * GetStreamReaders(Oid relid) { Bitmapset *targets; char *name = get_rel_name(relid);; if (!continuous_queries_enabled) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot insert into stream %s since continuous queries are disabled", name), errhint("Enable continuous queries using the \"continuous_queries_enabled\" parameter."))); targets = GetLocalStreamReaders(relid); if (targets == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("no continuous views are currently reading from stream %s", name), errhint("Use CREATE CONTINUOUS VIEW to create a continuous view that includes %s in its FROM clause.", name))); return targets; }
/* * sepgsql_attribute_relabel * * It checks privileges to relabel the supplied column * by the `seclabel'. */ void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, const char *seclabel) { char *scontext = sepgsql_get_client_label(); char *tcontext; char audit_name[NAMEDATALEN * 2 + 10]; if (get_rel_relkind(relOid) != RELKIND_RELATION) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot set security label on non-regular columns"))); snprintf(audit_name, sizeof(audit_name), "%s.%s", get_rel_name(relOid), get_attname(relOid, attnum)); /* * check db_column:{setattr relabelfrom} permission */ tcontext = sepgsql_get_label(RelationRelationId, relOid, attnum); sepgsql_check_perms(scontext, tcontext, SEPG_CLASS_DB_COLUMN, SEPG_DB_COLUMN__SETATTR | SEPG_DB_COLUMN__RELABELFROM, audit_name, true); pfree(tcontext); /* * check db_column:{relabelto} permission */ sepgsql_check_perms(scontext, seclabel, SEPG_CLASS_DB_COLUMN, SEPG_DB_PROCEDURE__RELABELTO, audit_name, true); }
/* * Find rule oid. * * If missing_ok is false, throw an error if rule name not found. If * true, just return INVALID_OID. */ oid_t get_rewrite_oid(oid_t relid, const char *rulename, bool missing_ok) { struct heap_tuple* tuple; oid_t ruleoid; /* Find the rule's pg_rewrite tuple, get its OID */ tuple = search_syscache2(RULERELNAME, OID_TO_D(relid), PTR_TO_D(rulename)); if (!HT_VALID(tuple)) { if (missing_ok) return INVALID_OID; ereport(ERROR, ( errcode(E_UNDEFINED_OBJECT), errmsg("rule \"%s\" for relation \"%s\" does not exist", rulename, get_rel_name(relid)))); } ASSERT(relid == ((Form_pg_rewrite) GET_STRUCT(tuple))->ev_class); ruleoid = HEAPTUP_OID(tuple); release_syscache(tuple); return ruleoid; }
/* * GenereatePartitioningInformation returns the partitioning type and partition column * for the given parent table in the form of "PARTITION TYPE (partitioning column(s)/expression(s))". */ char * GeneratePartitioningInformation(Oid parentTableId) { char *partitionBoundCString = ""; #if (PG_VERSION_NUM >= 100000) Datum partitionBoundDatum = 0; if (!PartitionedTable(parentTableId)) { char *relationName = get_rel_name(parentTableId); ereport(ERROR, (errmsg("\"%s\" is not a parent table", relationName))); } partitionBoundDatum = DirectFunctionCall1(pg_get_partkeydef, ObjectIdGetDatum(parentTableId)); partitionBoundCString = TextDatumGetCString(partitionBoundDatum); #endif return partitionBoundCString; }
/* * Find rule oid. * * If missing_ok is false, throw an error if rule name not found. If * true, just return InvalidOid. */ Oid get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok) { HeapTuple tuple; Oid ruleoid; /* Find the rule's pg_rewrite tuple, get its OID */ tuple = SearchSysCache2(RULERELNAME, ObjectIdGetDatum(relid), PointerGetDatum(rulename)); if (!HeapTupleIsValid(tuple)) { if (missing_ok) return InvalidOid; ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("rule \"%s\" for relation \"%s\" does not exist", rulename, get_rel_name(relid)))); } Assert(relid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class); ruleoid = HeapTupleGetOid(tuple); ReleaseSysCache(tuple); return ruleoid; }