/* * worker_cleanup_job_schema_cache walks over all schemas in the database, and * removes schemas whose names start with the job schema prefix. Note that this * function does not perform any locking; we expect it to be called at process * start-up time before any merge tasks are run. Further note that this function * runs within the scope of a particular database (template1, postgres) and can * only delete schemas within that database. */ Datum worker_cleanup_job_schema_cache(PG_FUNCTION_ARGS) { Relation pgNamespace = NULL; HeapScanDesc scanDescriptor = NULL; ScanKey scanKey = NULL; int scanKeyCount = 0; HeapTuple heapTuple = NULL; pgNamespace = heap_open(NamespaceRelationId, AccessExclusiveLock); scanDescriptor = heap_beginscan_catalog(pgNamespace, scanKeyCount, scanKey); heapTuple = heap_getnext(scanDescriptor, ForwardScanDirection); while (HeapTupleIsValid(heapTuple)) { Form_pg_namespace schemaForm = (Form_pg_namespace) GETSTRUCT(heapTuple); char *schemaName = NameStr(schemaForm->nspname); char *jobSchemaFound = strstr(schemaName, JOB_SCHEMA_PREFIX); if (jobSchemaFound != NULL) { StringInfo jobSchemaName = makeStringInfo(); appendStringInfoString(jobSchemaName, schemaName); RemoveJobSchema(jobSchemaName); } heapTuple = heap_getnext(scanDescriptor, ForwardScanDirection); } heap_endscan(scanDescriptor); heap_close(pgNamespace, AccessExclusiveLock); PG_RETURN_VOID(); }
/* * calculate size of database in all tablespaces */ static int64 calculate_database_size(Oid dbOid) { int64 totalsize = 0; char pathname[MAXPGPATH]; Relation rel; HeapScanDesc scandesc; HeapTuple tuple; AclResult aclresult; Assert(Gp_role != GP_ROLE_EXECUTE); if (dbOid == HcatalogDbOid) ereport(ERROR, (ERRCODE_UNDEFINED_DATABASE, errmsg("database hcatalog (OID 6120) is reserved"))); /* User must have connect privilege for target database */ aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT); if (aclresult != ACLCHECK_OK) { aclcheck_error(aclresult, ACL_KIND_DATABASE, get_database_name(dbOid)); } /* Scan through all tablespaces */ rel = heap_open(TableSpaceRelationId, AccessShareLock); scandesc = heap_beginscan(rel, SnapshotNow, 0, NULL); tuple = heap_getnext(scandesc, ForwardScanDirection); while (HeapTupleIsValid(tuple)) { char *filespace; Oid tsOid; tsOid = HeapTupleGetOid(tuple); /* Don't include shared relations */ if (tsOid != GLOBALTABLESPACE_OID) { /* Find the filespace path for this tablespace */ /* Master access its own database first. */ PersistentTablespace_GetFilespacePath(tsOid, FALSE, &filespace); /* Build the path for this database in this tablespace */ FormDatabasePath(pathname, filespace, tsOid, dbOid); totalsize += db_dir_size(pathname); } tuple = heap_getnext(scandesc, ForwardScanDirection); } heap_endscan(scandesc); heap_close(rel, AccessShareLock); /* Complain if we found no trace of the DB at all */ if (totalsize == 0) ereport(ERROR, (ERRCODE_UNDEFINED_DATABASE, errmsg("database with OID %u does not exist", dbOid))); return totalsize; }
/* * Gets list of all relation published by FOR ALL TABLES publication(s). */ List * GetAllTablesPublicationRelations(void) { Relation classRel; ScanKeyData key[1]; HeapScanDesc scan; HeapTuple tuple; List *result = NIL; classRel = heap_open(RelationRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_class_relkind, BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_RELATION)); scan = heap_beginscan_catalog(classRel, 1, key); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple); Oid relid = relForm->oid; if (is_publishable_class(relid, relForm)) result = lappend_oid(result, relid); } heap_endscan(scan); heap_close(classRel, AccessShareLock); return result; }
/* * RemoveConversionById * * Remove a tuple from pg_conversion by Oid. This function is solely * called inside catalog/dependency.c */ void RemoveConversionById(Oid conversionOid) { Relation rel; HeapTuple tuple; HeapScanDesc scan; ScanKeyData scanKeyData; ScanKeyInit(&scanKeyData, ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(conversionOid)); /* open pg_conversion */ rel = heap_open(ConversionRelationId, RowExclusiveLock); scan = heap_beginscan_catalog(rel, 1, &scanKeyData); /* search for the target tuple */ if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection))) simple_heap_delete(rel, &tuple->t_self); else elog(ERROR, "could not find tuple for conversion %u", conversionOid); heap_endscan(scan); heap_close(rel, RowExclusiveLock); }
/** * @brief Get the pg class tuple * @param tuple relevant tuple if it exists, NULL otherwise */ HeapTuple Bridge::GetPGClassTupleForRelationName(const char *relation_name) { LOG_WARN("Do not use bridge function(%s) in Peloton !!! ", __func__); Relation pg_class_rel; HeapTuple tuple = NULL; HeapScanDesc scan; // Open pg_class table pg_class_rel = heap_open(RelationRelationId, AccessShareLock); // Search the pg_class table with given relation name scan = heap_beginscan_catalog(pg_class_rel, 0, NULL); while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection))) { Form_pg_class pgclass = (Form_pg_class)GETSTRUCT(tuple); if (pgclass->relnamespace == PG_PUBLIC_NAMESPACE) { if (strcmp(NameStr(pgclass->relname), relation_name) == 0) { // We need to end scan and close heap break; } } } heap_endscan(scan); heap_close(pg_class_rel, AccessShareLock); return tuple; }
/* *-------------------------------------------------------------- * Async_UnlistenAll * * Unlisten all relations for this backend. * * This is invoked by UNLISTEN "*" command, and also at backend exit. * * Results: * XXX * * Side effects: * pg_listener is updated. * *-------------------------------------------------------------- */ static void Async_UnlistenAll(void) { Relation lRel; TupleDesc tdesc; HeapScanDesc scan; HeapTuple lTuple; ScanKeyData key[1]; if (Trace_notify) elog(DEBUG1, "Async_UnlistenAll"); lRel = heap_open(ListenerRelationId, ExclusiveLock); tdesc = RelationGetDescr(lRel); /* Find and delete all entries with my listenerPID */ ScanKeyInit(&key[0], Anum_pg_listener_pid, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(MyProcPid)); scan = heap_beginscan(lRel, SnapshotNow, 1, key); while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) simple_heap_delete(lRel, &lTuple->t_self); heap_endscan(scan); heap_close(lRel, ExclusiveLock); }
bool PersistentStore_GetNext( PersistentStoreScan *storeScan, Datum *values, ItemPointer persistentTid, int64 *persistentSerialNum) { ItemPointerData previousFreeTid; storeScan->tuple = heap_getnext(storeScan->scan, ForwardScanDirection); if (storeScan->tuple == NULL) return false; PersistentStore_DeformTuple( storeScan->storeData, storeScan->persistentRel->rd_att, storeScan->tuple, values); PersistentStore_ExtractOurTupleData( storeScan->storeData, values, persistentSerialNum, &previousFreeTid); *persistentTid = storeScan->tuple->t_self; return true; }
/* * get_next_id * * Gets the smallest possible id to assign to the next continuous view. * We keep this minimal so that we can minimize the size of bitmaps used * to tag stream buffer events with. */ static int32 get_next_id(Relation rel) { HeapScanDesc scandesc; HeapTuple tup; int32 id = 1; List *idsList = NIL; ListCell *lc; scandesc = heap_beginscan_catalog(rel, 0, NULL); while ((tup = heap_getnext(scandesc, ForwardScanDirection)) != NULL) { Form_pipeline_query row = (Form_pipeline_query) GETSTRUCT(tup); idsList = lappend_int(idsList, row->id); } heap_endscan(scandesc); if (idsList != NIL) { int32 ids[idsList->length]; int i = 0; foreach(lc, idsList) { ids[i] = lfirst_int(lc); i++; }
/* * get_all_brokers * * Return a list of all brokers in pipeline_kafka_brokers */ static List * get_all_brokers(void) { HeapTuple tup = NULL; HeapScanDesc scan; Relation brokers = open_pipeline_kafka_brokers(); TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(brokers)); List *result = NIL; scan = heap_beginscan(brokers, GetTransactionSnapshot(), 0, NULL); while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) { char *host; Datum d; bool isnull; ExecStoreTuple(tup, slot, InvalidBuffer, false); d = slot_getattr(slot, BROKER_ATTR_HOST, &isnull); host = TextDatumGetCString(d); result = lappend(result, host); } ExecDropSingleTupleTableSlot(slot); heap_endscan(scan); heap_close(brokers, NoLock); return result; }
/* * Returns true if the relation has no tuples. Prepare phase of * compaction invokes this function on each QE. * * Examples of empty tables: * 1. parent of a partitioned table * 2. table that is created but no tuples have been inserted yet * 3. table from which all existing tuples are deleted and the table * is vacuumed. This is a special case in which pg_aoseg_<oid> has * non-zero number of rows but tupcount value is zero for all rows. */ bool AppendOnlyCompaction_IsRelationEmpty(Relation aorel) { AppendOnlyEntry *aoEntry; Relation pg_aoseg_rel; TupleDesc pg_aoseg_dsc; HeapTuple tuple; HeapScanDesc aoscan; int Anum_tupcount; bool empty = true; Assert(RelationIsAoRows(aorel) || RelationIsAoCols(aorel)); aoEntry = GetAppendOnlyEntry(RelationGetRelid(aorel), SnapshotNow); pg_aoseg_rel = heap_open(aoEntry->segrelid, AccessShareLock); pg_aoseg_dsc = RelationGetDescr(pg_aoseg_rel); aoscan = heap_beginscan(pg_aoseg_rel, SnapshotNow, 0, NULL); Anum_tupcount = RelationIsAoRows(aorel)? Anum_pg_aoseg_tupcount: Anum_pg_aocs_tupcount; while ((tuple = heap_getnext(aoscan, ForwardScanDirection)) != NULL && empty) { if (0 < fastgetattr(tuple, Anum_tupcount, pg_aoseg_dsc, NULL)) empty = false; } heap_endscan(aoscan); heap_close(pg_aoseg_rel, AccessShareLock); return empty; }
/* * get_tablespace_name - given a tablespace OID, look up the name * * Returns a palloc'd string, or NULL if no such tablespace. */ char * get_tablespace_name(Oid spc_oid) { char *result; Relation rel; HeapScanDesc scandesc; HeapTuple tuple; ScanKeyData entry[1]; /* Search pg_tablespace */ rel = heap_open(TableSpaceRelationId, AccessShareLock); ScanKeyInit(&entry[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(spc_oid)); scandesc = heap_beginscan(rel, SnapshotNow, 1, entry); tuple = heap_getnext(scandesc, ForwardScanDirection); /* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(tuple)) result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname)); else result = NULL; heap_endscan(scandesc); heap_close(rel, AccessShareLock); return result; }
/* * get_tablespace_oid - given a tablespace name, look up the OID * * Returns InvalidOid if tablespace name not found. */ Oid get_tablespace_oid(const char *tablespacename) { Oid result; Relation rel; HeapScanDesc scandesc; HeapTuple tuple; ScanKeyData entry[1]; /* Search pg_tablespace */ rel = heap_open(TableSpaceRelationId, AccessShareLock); ScanKeyInit(&entry[0], Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(tablespacename)); scandesc = heap_beginscan(rel, SnapshotNow, 1, entry); tuple = heap_getnext(scandesc, ForwardScanDirection); if (HeapTupleIsValid(tuple)) result = HeapTupleGetOid(tuple); else result = InvalidOid; heap_endscan(scandesc); heap_close(rel, AccessShareLock); return result; }
/* * get_database_oids * * Returns a list of all database OIDs found in pg_database. */ static List * get_database_list(void) { List *dbs = NIL; Relation rel; HeapScanDesc scan; HeapTuple tup; MemoryContext resultcxt; /* This is the context that we will allocate our output data in */ resultcxt = CurrentMemoryContext; /* * Start a transaction so we can access pg_database, and get a snapshot. * We don't have a use for the snapshot itself, but we're interested in * the secondary effect that it sets RecentGlobalXmin. (This is critical * for anything that reads heap pages, because HOT may decide to prune * them even if the process doesn't attempt to modify any tuples.) */ StartTransactionCommand(); (void) GetTransactionSnapshot(); /* We take a AccessExclusiveLock so we don't conflict with any DATABASE commands */ rel = heap_open(DatabaseRelationId, AccessExclusiveLock); scan = heap_beginscan_catalog(rel, 0, NULL); while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) { MemoryContext oldcxt; Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup); DatabaseEntry *db_entry; /* Ignore template databases or ones that don't allow connections. */ if (pgdatabase->datistemplate || !pgdatabase->datallowconn) continue; /* * Allocate our results in the caller's context, not the * transaction's. We do this inside the loop, and restore the original * context at the end, so that leaky things like heap_getnext() are * not called in a potentially long-lived context. */ oldcxt = MemoryContextSwitchTo(resultcxt); db_entry = palloc0(sizeof(DatabaseEntry)); db_entry->oid = HeapTupleGetOid(tup); StrNCpy(NameStr(db_entry->name), NameStr(pgdatabase->datname), NAMEDATALEN); dbs = lappend(dbs, db_entry); MemoryContextSwitchTo(oldcxt); } heap_endscan(scan); heap_close(rel, AccessExclusiveLock); CommitTransactionCommand(); return dbs; }
/* * Find rule oid, given only a rule name but no rel OID. * * If there's more than one, it's an error. If there aren't any, that's an * error, too. In general, this should be avoided - it is provided to support * syntax that is compatible with pre-7.3 versions of PG, where rule names * were unique across the entire database. */ Oid get_rewrite_oid_without_relid(const char *rulename, Oid *reloid, bool missing_ok) { Relation RewriteRelation; HeapScanDesc scanDesc; ScanKeyData scanKeyData; HeapTuple htup; Oid ruleoid; /* Search pg_rewrite for such a rule */ ScanKeyInit(&scanKeyData, Anum_pg_rewrite_rulename, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(rulename)); RewriteRelation = heap_open(RewriteRelationId, AccessShareLock); scanDesc = heap_beginscan(RewriteRelation, SnapshotNow, 1, &scanKeyData); htup = heap_getnext(scanDesc, ForwardScanDirection); if (!HeapTupleIsValid(htup)) { if (!missing_ok) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("rule \"%s\" does not exist", rulename))); ruleoid = InvalidOid; } else { ruleoid = HeapTupleGetOid(htup); if (reloid != NULL) *reloid = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class; htup = heap_getnext(scanDesc, ForwardScanDirection); if (HeapTupleIsValid(htup)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("there are multiple rules named \"%s\"", rulename), errhint("Specify a relation name as well as a rule name."))); } heap_endscan(scanDesc); heap_close(RewriteRelation, AccessShareLock); return ruleoid; }
/* * Load the list of subscriptions. * * Only the fields interesting for worker start/stop functions are filled for * each subscription. */ static List * get_subscription_list(void) { List *res = NIL; Relation rel; TableScanDesc scan; HeapTuple tup; MemoryContext resultcxt; /* This is the context that we will allocate our output data in */ resultcxt = CurrentMemoryContext; /* * Start a transaction so we can access pg_database, and get a snapshot. * We don't have a use for the snapshot itself, but we're interested in * the secondary effect that it sets RecentGlobalXmin. (This is critical * for anything that reads heap pages, because HOT may decide to prune * them even if the process doesn't attempt to modify any tuples.) */ StartTransactionCommand(); (void) GetTransactionSnapshot(); rel = table_open(SubscriptionRelationId, AccessShareLock); scan = table_beginscan_catalog(rel, 0, NULL); while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) { Form_pg_subscription subform = (Form_pg_subscription) GETSTRUCT(tup); Subscription *sub; MemoryContext oldcxt; /* * Allocate our results in the caller's context, not the * transaction's. We do this inside the loop, and restore the original * context at the end, so that leaky things like heap_getnext() are * not called in a potentially long-lived context. */ oldcxt = MemoryContextSwitchTo(resultcxt); sub = (Subscription *) palloc0(sizeof(Subscription)); sub->oid = subform->oid; sub->dbid = subform->subdbid; sub->owner = subform->subowner; sub->enabled = subform->subenabled; sub->name = pstrdup(NameStr(subform->subname)); /* We don't fill fields we are not interested in. */ res = lappend(res, sub); MemoryContextSwitchTo(oldcxt); } table_endscan(scan); table_close(rel, AccessShareLock); CommitTransactionCommand(); return res; }
Datum gp_persistent_set_relation_bufpool_kind_all(PG_FUNCTION_ARGS) { Relation pg_database; HeapScanDesc scan; HeapTuple tuple; if (!gp_upgrade_mode) ereport(ERROR, (errcode(ERRCODE_GP_FEATURE_NOT_SUPPORTED), errmsg("function is not supported"), errOmitLocation(true))); // UNDONE: Verify we are in some sort of single-user mode. /* * Special call here to scan the persistent meta-data structures so we are open for * business and then we can add information. */ PersistentFileSysObj_BuildInitScan(); pg_database = heap_open( DatabaseRelationId, AccessShareLock); scan = heap_beginscan(pg_database, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_database form_pg_database = (Form_pg_database)GETSTRUCT(tuple); Oid dbOid; Oid dattablespace; dbOid = HeapTupleGetOid(tuple); dattablespace = form_pg_database->dattablespace; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "gp_persistent_set_relation_bufpool_kind_all: dbOid %u", dbOid); PersistentBuild_SetRelationBufpoolKind( dattablespace, dbOid); } heap_endscan(scan); heap_close(pg_database, AccessShareLock); PG_RETURN_INT32(1); }
/* ---------------------------------------------------------------- * SeqNext * * This is a workhorse for ExecSeqScan * ---------------------------------------------------------------- */ static TupleTableSlot * SeqNext(SeqScanState *node) { HeapTuple tuple; HeapScanDesc scandesc; EState *estate; ScanDirection direction; TupleTableSlot *slot; /* * get information from the estate and scan state */ scandesc = node->ss.ss_currentScanDesc; estate = node->ss.ps.state; direction = estate->es_direction; slot = node->ss.ss_ScanTupleSlot; if (scandesc == NULL) { /* * We reach here if the scan is not parallel, or if we're executing a * scan that was intended to be parallel serially. */ scandesc = heap_beginscan(node->ss.ss_currentRelation, estate->es_snapshot, 0, NULL); node->ss.ss_currentScanDesc = scandesc; } /* * get the next tuple from the table */ tuple = heap_getnext(scandesc, direction); /* * save the tuple and the buffer returned to us by the access methods in * our scan tuple slot and return the slot. Note: we pass 'false' because * tuples returned by heap_getnext() are pointers onto disk pages and were * not created with palloc() and so should not be pfree()'d. Note also * that ExecStoreTuple will increment the refcount of the buffer; the * refcount will not be dropped until the tuple table slot is cleared. */ if (tuple) ExecStoreTuple(tuple, /* tuple to store */ slot, /* slot to store in */ scandesc->rs_cbuf, /* buffer associated with this * tuple */ false); /* don't pfree this pointer */ else ExecClearTuple(slot); return slot; }
/* * load_consumer_offsets * * Load all offsets for all of this consumer's partitions */ static void load_consumer_offsets(KafkaConsumer *consumer, struct rd_kafka_metadata_topic *meta, int64_t offset) { MemoryContext old; ScanKeyData skey[1]; HeapTuple tup = NULL; HeapScanDesc scan; Relation offsets = open_pipeline_kafka_offsets(); TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(offsets)); int i; ScanKeyInit(&skey[0], OFFSETS_ATTR_CONSUMER, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(consumer->id)); scan = heap_beginscan(offsets, GetTransactionSnapshot(), 1, skey); old = MemoryContextSwitchTo(CacheMemoryContext); consumer->offsets = palloc0(meta->partition_cnt * sizeof(int64_t)); MemoryContextSwitchTo(old); /* by default, begin consuming from the end of a stream */ for (i = 0; i < meta->partition_cnt; i++) consumer->offsets[i] = offset; consumer->num_partitions = meta->partition_cnt; while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) { Datum d; bool isnull; int partition; ExecStoreTuple(tup, slot, InvalidBuffer, false); d = slot_getattr(slot, OFFSETS_ATTR_PARTITION, &isnull); partition = DatumGetInt32(d); if(partition > consumer->num_partitions) elog(ERROR, "invalid partition id: %d", partition); if (offset == RD_KAFKA_OFFSET_NULL) { d = slot_getattr(slot, OFFSETS_ATTR_OFFSET, &isnull); if (isnull) offset = RD_KAFKA_OFFSET_END; else offset = DatumGetInt64(d); } consumer->offsets[partition] = DatumGetInt64(offset); } ExecDropSingleTupleTableSlot(slot); heap_endscan(scan); heap_close(offsets, RowExclusiveLock); }
/* * systable_getnext --- get next tuple in a heap-or-index scan * * Returns NULL if no more tuples available. * * Note that returned tuple is a reference to data in a disk buffer; * it must not be modified, and should be presumed inaccessible after * next getnext() or endscan() call. */ HeapTuple systable_getnext(SysScanDesc sysscan) { HeapTuple htup; if (sysscan->irel) htup = index_getnext(sysscan->iscan, ForwardScanDirection); else htup = heap_getnext(sysscan->scan, ForwardScanDirection); return htup; }
static void DatabaseInfo_CollectGpRelationNode( DatabaseInfo *info, HTAB *dbInfoRelHashTable) { HeapScanDesc scan; Relation gp_relation_node_rel; HeapTuple tuple; gp_relation_node_rel = DirectOpen_GpRelationNodeOpen( info->defaultTablespace, info->database); scan = heap_beginscan(gp_relation_node_rel, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { bool nulls[Natts_gp_relation_node]; Datum values[Natts_gp_relation_node]; Oid relfilenode; int32 segmentFileNum; int64 createMirrorDataLossTrackingSessionNum; ItemPointerData persistentTid; int64 persistentSerialNum; heap_deform_tuple(tuple, RelationGetDescr(gp_relation_node_rel), values, nulls); GpRelationNode_GetValues( values, &relfilenode, &segmentFileNum, &createMirrorDataLossTrackingSessionNum, &persistentTid, &persistentSerialNum); if (!DatabaseInfo_AddGpRelationNode( info, dbInfoRelHashTable, relfilenode, segmentFileNum, &persistentTid, persistentSerialNum, &tuple->t_self)) { elog(WARNING, "Did not find matching pg_class entry for gp_relation_node entry relfilenode %u (parentless!!!)", relfilenode); } } heap_endscan(scan); DirectOpen_GpRelationNodeClose(gp_relation_node_rel); }
/* * Set mirror for all relation files. */ void PersistentRelation_AddMirrorAll(int16 pridbid, int16 mirdbid) { Relation rel; HeapScanDesc scandesc; HeapTuple tuple; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); rel = heap_open(GpPersistentRelationNodeRelationId, AccessExclusiveLock); scandesc = heap_beginscan(rel, SnapshotNow, 0, NULL); WRITE_PERSISTENT_STATE_ORDERED_LOCK; while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL) { Form_gp_persistent_relation_node form = (Form_gp_persistent_relation_node)GETSTRUCT(tuple); Oid tblspcoid = form->tablespace_oid; Oid dboid = form->database_oid; Oid relfilenode_oid = form->relfilenode_oid; int32 segment_file_num = form->segment_file_num; int64 serial = form->persistent_serial_num; PersistentFileSysObjName fsObjName; RelFileNode node; node.spcNode = tblspcoid; node.dbNode = dboid; node.relNode = relfilenode_oid; PersistentFileSysObjName_SetRelationFile(&fsObjName, &node, segment_file_num); PersistentFileSysObj_AddMirror(&fsObjName, &tuple->t_self, serial, pridbid, mirdbid, NULL, true, /* flushToXlog */ false); } WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; heap_endscan(scandesc); heap_close(rel, NoLock); }
/* * Returns true if at least one role is defined in this database cluster. */ static bool ThereIsAtLeastOneRole(void) { struct relation* pg_authid_rel; struct heap_scan* scan; bool result; pg_authid_rel = heap_open(AuthIdRelationId, ACCESS_SHR_LOCK); scan = heap_beginscan(pg_authid_rel, snap_now, 0, NULL); result = (heap_getnext(scan, FORWARD_SCANDIR) != NULL); heap_endscan(scan); heap_close(pg_authid_rel, ACCESS_SHR_LOCK); return result; }
/* * Find rule oid, given only a rule name but no rel OID. * * If there's more than one, it's an error. If there aren't any, that's an * error, too. In general, this should be avoided - it is provided to support * syntax that is compatible with pre-7.3 versions of PG, where rule names * were unique across the entire database. */ oid_t get_rewrite_oid_without_relid(const char *rulename, oid_t* reloid) { struct relation* RewriteRelation; struct heap_scan* scanDesc; struct scankey scanKeyData; struct heap_tuple* htup; oid_t ruleoid; /* Search pg_rewrite for such a rule */ scankey_init(&scanKeyData, Anum_pg_rewrite_rulename, BT_EQ_STRAT_NR, F_NAMEEQ, CSTRING_TO_D(rulename)); RewriteRelation = heap_open(RewriteRelationId, ACCESS_SHR_LOCK); scanDesc = heap_beginscan(RewriteRelation, snap_now, 1, &scanKeyData); htup = heap_getnext(scanDesc, FORWARD_SCANDIR); if (!HT_VALID(htup)) { ereport(ERROR, ( errcode(E_UNDEFINED_OBJECT), errmsg("rule \"%s\" does not exist", rulename))); } ruleoid = HEAPTUP_OID(htup); if (reloid != NULL) *reloid = ((Form_pg_rewrite) GET_STRUCT(htup))->ev_class; if (HT_VALID(htup = heap_getnext(scanDesc, FORWARD_SCANDIR))) { ereport(ERROR, ( errcode(E_DUPLICATE_OBJECT), errmsg("there are multiple rules named \"%s\"", rulename), errhint("Specify a relation name as well as a rule name."))); } heap_endscan(scanDesc); heap_close(RewriteRelation, ACCESS_SHR_LOCK); return ruleoid; }
static Segment * IterateSegmentConfiguration(SegmentConfigurationIterator *iterator) { HeapTuple gp_seg_config_tuple; while (HeapTupleIsValid(gp_seg_config_tuple = heap_getnext(iterator->gp_seg_config_scan, ForwardScanDirection))) { return ParseSegmentConfigurationRow(iterator, gp_seg_config_tuple); } /* No more data. */ heap_endscan(iterator->gp_seg_config_scan); heap_close(iterator->gp_seg_config_rel, AccessShareLock); return NULL; }
/* * Returns true if at least one role is defined in this database cluster. */ static bool ThereIsAtLeastOneRole(void) { Relation pg_authid_rel; HeapScanDesc scan; bool result; pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock); scan = heap_beginscan_catalog(pg_authid_rel, 0, NULL); result = (heap_getnext(scan, ForwardScanDirection) != NULL); heap_endscan(scan); heap_close(pg_authid_rel, AccessShareLock); return result; }
/* *-------------------------------------------------------------- * Async_Unlisten * * This is executed by the SQL unlisten command. * * Remove the current backend from the list of listening backends * for the specified relation. * * Side effects: * pg_listener is updated. * *-------------------------------------------------------------- */ void Async_Unlisten(const char *relname) { Relation lRel; HeapScanDesc scan; HeapTuple tuple; /* Handle specially the `unlisten "*"' command */ if ((!relname) || (*relname == '\0') || (strcmp(relname, "*") == 0)) { Async_UnlistenAll(); return; } if (Trace_notify) elog(DEBUG1, "Async_Unlisten(%s,%d)", relname, MyProcPid); lRel = heap_open(ListenerRelationId, ExclusiveLock); scan = heap_beginscan(lRel, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(tuple); if (listener->listenerpid == MyProcPid && strncmp(NameStr(listener->relname), relname, NAMEDATALEN) == 0) { /* Found the matching tuple, delete it */ simple_heap_delete(lRel, &tuple->t_self); /* * We assume there can be only one match, so no need to scan the * rest of the table */ break; } } heap_endscan(scan); heap_close(lRel, ExclusiveLock); /* * We do not complain about unlistening something not being listened; * should we? */ }
Datum pg_dirtyread(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; MemoryContext oldcontext; pg_dirtyread_ctx *usr_ctx; Oid relid; HeapTuple tuplein, tupleout; TupleDesc tupdesc; if (SRF_IS_FIRSTCALL()) { relid = PG_GETARG_OID(0); if (OidIsValid(relid)) { funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); usr_ctx = (pg_dirtyread_ctx *) palloc(sizeof(pg_dirtyread_ctx)); usr_ctx->rel = heap_open(relid, AccessShareLock); usr_ctx->reltupdesc = RelationGetDescr(usr_ctx->rel); get_call_result_type(fcinfo, NULL, &tupdesc); funcctx->tuple_desc = BlessTupleDesc(tupdesc); usr_ctx->map = convert_tuples_by_position(usr_ctx->reltupdesc, funcctx->tuple_desc, "Error converting tuple descriptors!"); usr_ctx->scan = heap_beginscan(usr_ctx->rel, SnapshotAny, 0, NULL); funcctx->user_fctx = (void *) usr_ctx; MemoryContextSwitchTo(oldcontext); } } funcctx = SRF_PERCALL_SETUP(); usr_ctx = (pg_dirtyread_ctx *) funcctx->user_fctx; if ((tuplein = heap_getnext(usr_ctx->scan, ForwardScanDirection)) != NULL) { tupleout = do_convert_tuple(tuplein, usr_ctx->map); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tupleout)); } else { heap_endscan(usr_ctx->scan); heap_close(usr_ctx->rel, AccessShareLock); SRF_RETURN_DONE(funcctx); } }
/* * Get a superuser name; return in malloc()ed buffer. */ static char * getDBSuperuserName(const char *errPrefix) { char *suser = NULL; Relation auth_rel; HeapTuple auth_tup; HeapScanDesc auth_scan; ScanKeyData key[2]; bool isNull; ScanKeyInit(&key[0], Anum_pg_authid_rolsuper, BTEqualStrategyNumber, F_BOOLEQ, BoolGetDatum(true)); ScanKeyInit(&key[1], Anum_pg_authid_rolcanlogin, BTEqualStrategyNumber, F_BOOLEQ, BoolGetDatum(true)); auth_rel = heap_open(AuthIdRelationId, AccessShareLock); auth_scan = heap_beginscan(auth_rel, SnapshotNow, 2, key); while (HeapTupleIsValid(auth_tup = heap_getnext(auth_scan, ForwardScanDirection))) { Datum attrName; Datum validuntil; validuntil = heap_getattr(auth_tup, Anum_pg_authid_rolvaliduntil, auth_rel->rd_att, &isNull); /* we actually want it to be NULL, that means always valid */ if (!isNull) continue; attrName = heap_getattr(auth_tup, Anum_pg_authid_rolname, auth_rel->rd_att, &isNull); Assert(!isNull); suser = strdup(DatumGetCString(attrName)); } heap_endscan(auth_scan); heap_close(auth_rel, AccessShareLock); return suser; }
/* * Returns true if at least one user is defined in this database cluster. */ static bool ThereIsAtLeastOneUser(void) { Relation pg_shadow_rel; TupleDesc pg_shadow_dsc; HeapScanDesc scan; bool result; pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL); result = (heap_getnext(scan, ForwardScanDirection) != NULL); heap_endscan(scan); heap_close(pg_shadow_rel, AccessExclusiveLock); return result; }
/** * @brief Print all databases using catalog table pg_database */ void Bridge::GetDatabaseList(void) { LOG_WARN("Do not use bridge function(%s) in Peloton !!! ", __func__); Relation pg_database_rel; HeapScanDesc scan; HeapTuple tup; // Scan pg database table pg_database_rel = heap_open(DatabaseRelationId, AccessShareLock); scan = heap_beginscan_catalog(pg_database_rel, 0, NULL); while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) { Form_pg_database pg_database = (Form_pg_database)GETSTRUCT(tup); Oid database_oid = HeapTupleHeaderGetOid(tup->t_data); elog(LOG, "pgdatabase->datname :: %s oid %d ", NameStr(pg_database->datname), (int)database_oid); } heap_endscan(scan); heap_close(pg_database_rel, AccessShareLock); }