Esempio n. 1
0
/*
 * Test whether given name is currently used as a constraint name
 * for the given object (relation or domain).
 *
 * This is used to decide whether to accept a user-specified constraint name.
 * It is deliberately not the same test as ChooseConstraintName uses to decide
 * whether an auto-generated name is OK: here, we will allow it unless there
 * is an identical constraint name in use *on the same object*.
 *
 * NB: Caller should hold exclusive lock on the given object, else
 * this test can be fooled by concurrent additions.
 */
bool
ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
					 Oid objNamespace, const char *conname)
{
	bool		found;
	Relation	conDesc;
	SysScanDesc conscan;
	ScanKeyData skey[2];
	HeapTuple	tup;

	conDesc = heap_open(ConstraintRelationId, AccessShareLock);

	found = false;

	ScanKeyInit(&skey[0],
				Anum_pg_constraint_conname,
				BTEqualStrategyNumber, F_NAMEEQ,
				CStringGetDatum(conname));

	ScanKeyInit(&skey[1],
				Anum_pg_constraint_connamespace,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(objNamespace));

	conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
								 NULL, 2, skey);

	while (HeapTupleIsValid(tup = systable_getnext(conscan)))
	{
		Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);

		if (conCat == CONSTRAINT_RELATION && con->conrelid == objId)
		{
			found = true;
			break;
		}
		else if (conCat == CONSTRAINT_DOMAIN && con->contypid == objId)
		{
			found = true;
			break;
		}
	}

	systable_endscan(conscan);
	heap_close(conDesc, AccessShareLock);

	return found;
}
Esempio n. 2
0
/*
 * Collect a list of OIDs of all sequences owned by the specified relation.
 */
List *
getOwnedSequences(Oid relid)
{
	List	   *result = NIL;
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, AccessShareLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_refclassid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(RelationRelationId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_refobjid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(relid));

	scan = systable_beginscan(depRel, DependReferenceIndexId, true,
							  NULL, 2, key);

	while (HeapTupleIsValid(tup = systable_getnext(scan)))
	{
		Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);

		/*
		 * We assume any auto dependency of a sequence on a column must be
		 * what we are looking for.  (We need the relkind test because indexes
		 * can also have auto dependencies on columns.)
		 */
		if (deprec->classid == RelationRelationId &&
			deprec->objsubid == 0 &&
			deprec->refobjsubid != 0 &&
			deprec->deptype == DEPENDENCY_AUTO &&
			get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
		{
			result = lappend_oid(result, deprec->objid);
		}
	}

	systable_endscan(scan);

	heap_close(depRel, AccessShareLock);

	return result;
}
Esempio n. 3
0
/*
 * pg_get_sequencedef_string returns the definition of a given sequence. This
 * definition includes explicit values for all CREATE SEQUENCE options.
 */
char *
pg_get_sequencedef_string(Oid sequenceRelationId)
{
	char *qualifiedSequenceName = NULL;
	char *sequenceDef = NULL;
	Form_pg_sequence pgSequenceForm = NULL;
	Relation sequenceRel = NULL;
	AclResult permissionCheck = ACLCHECK_NO_PRIV;
	SysScanDesc scanDescriptor = NULL;
	HeapTuple heapTuple = NULL;

	/* open and lock sequence */
	sequenceRel = heap_open(sequenceRelationId, AccessShareLock);

	/* check permissions to read sequence attributes */
	permissionCheck = pg_class_aclcheck(sequenceRelationId, GetUserId(),
										ACL_SELECT | ACL_USAGE);
	if (permissionCheck != ACLCHECK_OK)
	{
		ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
						errmsg("permission denied for sequence %s",
							   RelationGetRelationName(sequenceRel))));
	}

	/* retrieve attributes from first tuple */
	scanDescriptor = systable_beginscan(sequenceRel, InvalidOid, false, NULL, 0, NULL);
	heapTuple = systable_getnext(scanDescriptor);
	if (!HeapTupleIsValid(heapTuple))
	{
		ereport(ERROR, (errmsg("could not find specified sequence")));
	}

	pgSequenceForm = (Form_pg_sequence) GETSTRUCT(heapTuple);

	/* build our DDL command */
	qualifiedSequenceName = generate_relation_name(sequenceRelationId, NIL);
	sequenceDef = psprintf(CREATE_SEQUENCE_COMMAND, qualifiedSequenceName,
						   pgSequenceForm->increment_by, pgSequenceForm->min_value,
						   pgSequenceForm->max_value, pgSequenceForm->cache_value,
						   pgSequenceForm->is_cycled ? "" : "NO ");

	systable_endscan(scanDescriptor);

	heap_close(sequenceRel, AccessShareLock);

	return sequenceDef;
}
Esempio n. 4
0
/* ---------------------
 * lookupProcCallback() - Find a specified callback for a specified function
 *
 * Parameters:
 *    profnoid    - oid of the function that has a callback
 *    promethod   - which callback to find
 * ---------------------
 */
Oid  
lookupProcCallback(Oid profnoid, char promethod)
{
	Relation	rel;
	ScanKeyData skey[2];
	SysScanDesc scan;
	HeapTuple	tup;
	Oid         result;

	Insist(OidIsValid(profnoid));

	/* open pg_proc_callback */
	rel = heap_open(ProcCallbackRelationId, AccessShareLock);

	/* Lookup (profnoid, promethod) from index */
	/* (profnoid, promethod) is guaranteed unique by the index */
	ScanKeyInit(&skey[0],
				Anum_pg_proc_callback_profnoid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(profnoid));
	ScanKeyInit(&skey[1],
				Anum_pg_proc_callback_promethod,
				BTEqualStrategyNumber, F_CHAREQ,
				CharGetDatum(promethod));
	scan = systable_beginscan(rel, ProcCallbackProfnoidPromethodIndexId, true,
							  SnapshotNow, 2, skey);
	tup = systable_getnext(scan);
	if (HeapTupleIsValid(tup))
	{
		Datum		d;
		bool		isnull;

		d = heap_getattr(tup, Anum_pg_proc_callback_procallback,
						 RelationGetDescr(rel), &isnull);
		Assert(!isnull);

		result = DatumGetObjectId(d);
	}
	else
		result = InvalidOid;

	systable_endscan(scan);
	heap_close(rel, AccessShareLock);

	return result;
}
/*
 * Get all relations for subscription that are not in a ready state.
 *
 * Returned list is palloc'ed in current memory context.
 */
List *
GetSubscriptionNotReadyRelations(Oid subid)
{
	List	   *res = NIL;
	Relation	rel;
	HeapTuple	tup;
	int			nkeys = 0;
	ScanKeyData skey[2];
	SysScanDesc scan;

	rel = table_open(SubscriptionRelRelationId, AccessShareLock);

	ScanKeyInit(&skey[nkeys++],
				Anum_pg_subscription_rel_srsubid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(subid));

	ScanKeyInit(&skey[nkeys++],
				Anum_pg_subscription_rel_srsubstate,
				BTEqualStrategyNumber, F_CHARNE,
				CharGetDatum(SUBREL_STATE_READY));

	scan = systable_beginscan(rel, InvalidOid, false,
							  NULL, nkeys, skey);

	while (HeapTupleIsValid(tup = systable_getnext(scan)))
	{
		Form_pg_subscription_rel subrel;
		SubscriptionRelState *relstate;

		subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);

		relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
		relstate->relid = subrel->srrelid;
		relstate->state = subrel->srsubstate;
		relstate->lsn = subrel->srsublsn;

		res = lappend(res, relstate);
	}

	/* Cleanup */
	systable_endscan(scan);
	table_close(rel, AccessShareLock);

	return res;
}
Esempio n. 6
0
/*
 * DeleteComments -- remove comments for an object
 *
 * If subid is nonzero then only comments matching it will be removed.
 * If subid is zero, all comments matching the oid/classoid will be removed
 * (this corresponds to deleting a whole object).
 */
void
DeleteComments(Oid oid, Oid classoid, int32 subid)
{
	Relation	description;
	ScanKeyData skey[3];
	int			nkeys;
	SysScanDesc sd;
	HeapTuple	oldtuple;

	/* Use the index to search for all matching old tuples */

	ScanKeyInit(&skey[0],
				Anum_pg_description_objoid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(oid));
	ScanKeyInit(&skey[1],
				Anum_pg_description_classoid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(classoid));

	if (subid != 0)
	{
		ScanKeyInit(&skey[2],
					Anum_pg_description_objsubid,
					BTEqualStrategyNumber, F_INT4EQ,
					Int32GetDatum(subid));
		nkeys = 3;
	}
	else
		nkeys = 2;

	description = heap_open(DescriptionRelationId, RowExclusiveLock);

	sd = systable_beginscan(description, DescriptionObjIndexId, true,
							SnapshotNow, nkeys, skey);

	while ((oldtuple = systable_getnext(sd)) != NULL)
		simple_heap_delete(description, &oldtuple->t_self);

	/* Done */

	systable_endscan(sd);
	heap_close(description, RowExclusiveLock);
}
/*
 * Scan pg_db_role_setting looking for applicable settings, and load them on
 * the current process.
 *
 * relsetting is pg_db_role_setting, already opened and locked.
 *
 * Note: we only consider setting for the exact databaseid/roleid combination.
 * This probably needs to be called more than once, with InvalidOid passed as
 * databaseid/roleid.
 */
void
ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
			 Relation relsetting, GucSource source)
{
	SysScanDesc scan;
	ScanKeyData keys[2];
	HeapTuple	tup;

	ScanKeyInit(&keys[0],
				Anum_pg_db_role_setting_setdatabase,
				BTEqualStrategyNumber,
				F_OIDEQ,
				ObjectIdGetDatum(databaseid));
	ScanKeyInit(&keys[1],
				Anum_pg_db_role_setting_setrole,
				BTEqualStrategyNumber,
				F_OIDEQ,
				ObjectIdGetDatum(roleid));

	scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
							  snapshot, 2, keys);
	while (HeapTupleIsValid(tup = systable_getnext(scan)))
	{
		bool		isnull;
		Datum		datum;

		datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
							 RelationGetDescr(relsetting), &isnull);
		if (!isnull)
		{
			ArrayType  *a = DatumGetArrayTypeP(datum);

			/*
			 * We process all the options at SUSET level.  We assume that the
			 * right to insert an option into pg_db_role_setting was checked
			 * when it was inserted.
			 */
			ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
		}
	}

	systable_endscan(scan);
}
Esempio n. 8
0
/*
 * Detect whether a sequence is marked as "owned" by a column
 *
 * An ownership marker is an AUTO dependency from the sequence to the
 * column.  If we find one, store the identity of the owning column
 * into *tableId and *colId and return TRUE; else return FALSE.
 *
 * Note: if there's more than one such pg_depend entry then you get
 * a random one of them returned into the out parameters.  This should
 * not happen, though.
 */
bool
sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
{
	bool		ret = false;
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, AccessShareLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_classid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(RelationRelationId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_objid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(seqId));

	scan = systable_beginscan(depRel, DependDependerIndexId, true,
							  NULL, 2, key);

	while (HeapTupleIsValid((tup = systable_getnext(scan))))
	{
		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);

		if (depform->refclassid == RelationRelationId &&
			depform->deptype == DEPENDENCY_AUTO)
		{
			*tableId = depform->refobjid;
			*colId = depform->refobjsubid;
			ret = true;
			break;				/* no need to keep scanning */
		}
	}

	systable_endscan(scan);

	heap_close(depRel, AccessShareLock);

	return ret;
}
Esempio n. 9
0
/*
 * GetDatabaseTuple -- fetch the pg_database row for a database
 *
 * This is used during backend startup when we don't yet have any access to
 * system catalogs in general.	In the worst case, we can seqscan pg_database
 * using nothing but the hard-wired descriptor that relcache.c creates for
 * pg_database.  In more typical cases, relcache.c was able to load
 * descriptors for both pg_database and its indexes from the shared relcache
 * cache file, and so we can do an indexscan.  criticalSharedRelcachesBuilt
 * tells whether we got the cached descriptors.
 */
static struct heap_tuple*
GetDatabaseTuple(const char *dbname)
{
	struct heap_tuple *tuple;
	struct relation *relation;
	struct sys_scan *scan;
	struct scankey key[1];

	/*
	 * form a scan key
	 */
	scankey_init(&key[0],
		Anum_pg_database_datname,
		BT_EQ_STRAT_NR,
		F_NAMEEQ,
		CSTRING_TO_D(dbname));

	/*
	 * Open pg_database and fetch a tuple.	Force heap scan if we haven't yet
	 * built the critical shared relcache entries (i.e., we're starting up
	 * without a shared relcache cache file).
	 */
	relation = heap_open(DatabaseRelationId, ACCESS_SHR_LOCK);
	scan = systable_beginscan(
			relation,
			DatabaseNameIndexId,
			criticalSharedRelcachesBuilt,
			snap_now,
			1,
			key);

	tuple = systable_getnext(scan);

	/* Must copy tuple before releasing buffer */
	if (HT_VALID(tuple))
		tuple = heap_dup_tuple(tuple);

	/* all done */
	systable_endscan(scan);
	heap_close(relation, ACCESS_SHR_LOCK);

	return tuple;
}
Esempio n. 10
0
/*
 * deleteDependencyRecordsForClass -- delete all records with given depender
 * classId/objectId, dependee classId, and deptype.
 * Returns the number of records deleted.
 *
 * This is a variant of deleteDependencyRecordsFor, useful when revoking
 * an object property that is expressed by a dependency record (such as
 * extension membership).
 */
long
deleteDependencyRecordsForClass(Oid classId, Oid objectId,
								Oid refclassId, char deptype)
{
	long		count = 0;
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, RowExclusiveLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_classid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(classId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_objid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(objectId));

	scan = systable_beginscan(depRel, DependDependerIndexId, true,
							  NULL, 2, key);

	while (HeapTupleIsValid(tup = systable_getnext(scan)))
	{
		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);

		if (depform->refclassid == refclassId && depform->deptype == deptype)
		{
			simple_heap_delete(depRel, &tup->t_self);
			count++;
		}
	}

	systable_endscan(scan);

	heap_close(depRel, RowExclusiveLock);

	return count;
}
Esempio n. 11
0
/*
 * Find the extension containing the specified object, if any
 *
 * Returns the OID of the extension, or InvalidOid if the object does not
 * belong to any extension.
 *
 * Extension membership is marked by an EXTENSION dependency from the object
 * to the extension.  Note that the result will be indeterminate if pg_depend
 * contains links from this object to more than one extension ... but that
 * should never happen.
 */
Oid
getExtensionOfObject(Oid classId, Oid objectId)
{
	Oid			result = InvalidOid;
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, AccessShareLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_classid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(classId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_objid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(objectId));

	scan = systable_beginscan(depRel, DependDependerIndexId, true,
							  NULL, 2, key);

	while (HeapTupleIsValid((tup = systable_getnext(scan))))
	{
		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);

		if (depform->refclassid == ExtensionRelationId &&
			depform->deptype == DEPENDENCY_EXTENSION)
		{
			result = depform->refobjid;
			break;				/* no need to keep scanning */
		}
	}

	systable_endscan(scan);

	heap_close(depRel, AccessShareLock);

	return result;
}
Esempio n. 12
0
/*
 * GetParquetTotalBytes
 *
 * Get the total bytes for a specific parquet table from the pg_aoseg table on master.
 *
 * In hawq, master keep all segfile info in pg_aoseg table,
 * therefore it get the whole table size.
 */
int64 GetParquetTotalBytes(Relation parentrel, Snapshot parquetMetaDataSnapshot)
{

	Relation		pg_paqseg_rel;
	TupleDesc		pg_paqseg_dsc;
	HeapTuple		tuple;
	SysScanDesc		parquetscan;
	int64		  	result;
	Datum			eof;
	bool			isNull;
	AppendOnlyEntry 	*aoEntry = NULL;

	aoEntry = GetAppendOnlyEntry(RelationGetRelid(parentrel), parquetMetaDataSnapshot);

	result = 0;

	pg_paqseg_rel = heap_open(aoEntry->segrelid, AccessShareLock);
	pg_paqseg_dsc = RelationGetDescr(pg_paqseg_rel);

	Assert (Gp_role != GP_ROLE_EXECUTE);

	parquetscan = systable_beginscan(pg_paqseg_rel, InvalidOid, FALSE,
			parquetMetaDataSnapshot, 0, NULL);

	while (HeapTupleIsValid(tuple = systable_getnext(parquetscan)))
	{
		eof = fastgetattr(tuple, Anum_pg_parquetseg_eof, pg_paqseg_dsc, &isNull);
		Assert(!isNull);

		result += (int64)DatumGetFloat8(eof);

		CHECK_FOR_INTERRUPTS();
	}

	systable_endscan(parquetscan);
	heap_close(pg_paqseg_rel, AccessShareLock);

	pfree(aoEntry);

	return result;
}
Esempio n. 13
0
/*
 * Same as pg_largeobject.c's large_obj_exists(), except snapshot to
 * read with can be specified.
 */
static bool
mylo_exists(oid_t loid, struct snap* snapshot)
{
	struct relation* pg_lo_meta;
	struct scankey skey[1];
	struct sys_scan* sd;
	struct heap_tuple* tuple;
	bool retval = false;

	scankey_init(&skey[0], OID_ATTR_NR, BT_EQ_STRAT_NR, F_OIDEQ, OID_TO_D(loid));
	pg_lo_meta = heap_open(LargeObjectMetadataRelationId, ACCESS_SHR_LOCK);
	sd = systable_beginscan(pg_lo_meta, LO_METADATA_OID_INDEX_ID, true, snapshot, 1, skey);
	tuple = systable_getnext(sd);
	if (HT_VALID(tuple))
		retval = true;

	systable_endscan(sd);
	heap_close(pg_lo_meta, ACCESS_SHR_LOCK);

	return retval;
}
Esempio n. 14
0
/*
 * ConstraintIsAForeignKey returns true if the given constraint name
 * is a foreign key to defined on the relation.
 */
bool
ConstraintIsAForeignKey(char *constraintNameInput, Oid relationId)
{
	Relation pgConstraint = NULL;
	SysScanDesc scanDescriptor = NULL;
	ScanKeyData scanKey[1];
	int scanKeyCount = 1;
	HeapTuple heapTuple = NULL;

	pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);

	ScanKeyInit(&scanKey[0], Anum_pg_constraint_contype, BTEqualStrategyNumber, F_CHAREQ,
				CharGetDatum(CONSTRAINT_FOREIGN));
	scanDescriptor = systable_beginscan(pgConstraint, InvalidOid, false,
										NULL, scanKeyCount, scanKey);

	heapTuple = systable_getnext(scanDescriptor);
	while (HeapTupleIsValid(heapTuple))
	{
		Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
		char *constraintName = (constraintForm->conname).data;

		if (strncmp(constraintName, constraintNameInput, NAMEDATALEN) == 0 &&
			constraintForm->conrelid == relationId)
		{
			systable_endscan(scanDescriptor);
			heap_close(pgConstraint, AccessShareLock);

			return true;
		}

		heapTuple = systable_getnext(scanDescriptor);
	}

	/* clean up scan and close system catalog */
	systable_endscan(scanDescriptor);
	heap_close(pgConstraint, AccessShareLock);

	return false;
}
Esempio n. 15
0
/*
 * IsChildTable returns true if the table is inherited. Note that
 * partition tables inherites by default. However, this function
 * returns false if the given table is a partition.
 */
bool
IsChildTable(Oid relationId)
{
	Relation pgInherits = NULL;
	SysScanDesc scan = NULL;
	ScanKeyData key[1];
	HeapTuple inheritsTuple = NULL;
	bool tableInherits = false;

	pgInherits = heap_open(InheritsRelationId, AccessShareLock);

	ScanKeyInit(&key[0], Anum_pg_inherits_inhrelid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(relationId));

	scan = systable_beginscan(pgInherits, InvalidOid, false,
							  NULL, 1, key);

	while ((inheritsTuple = systable_getnext(scan)) != NULL)
	{
		Oid inheritedRelationId =
			((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;

		if (relationId == inheritedRelationId)
		{
			tableInherits = true;
			break;
		}
	}

	systable_endscan(scan);
	heap_close(pgInherits, AccessShareLock);

	if (tableInherits && PartitionTable(relationId))
	{
		tableInherits = false;
	}

	return tableInherits;
}
Esempio n. 16
0
/*
 * isObjectPinned()
 *
 * Test if an object is required for basic database functionality.
 * Caller must already have opened pg_depend.
 *
 * The passed subId, if any, is ignored; we assume that only whole objects
 * are pinned (and that this implies pinning their components).
 */
static bool
isObjectPinned(const ObjectAddress *object, Relation rel)
{
	bool		ret = false;
	SysScanDesc scan;
	HeapTuple	tup;
	ScanKeyData key[2];

	ScanKeyInit(&key[0],
				Anum_pg_depend_refclassid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(object->classId));

	ScanKeyInit(&key[1],
				Anum_pg_depend_refobjid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(object->objectId));

	scan = systable_beginscan(rel, DependReferenceIndexId, true,
							  NULL, 2, key);

	/*
	 * Since we won't generate additional pg_depend entries for pinned
	 * objects, there can be at most one entry referencing a pinned object.
	 * Hence, it's sufficient to look at the first returned tuple; we don't
	 * need to loop.
	 */
	tup = systable_getnext(scan);
	if (HeapTupleIsValid(tup))
	{
		Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);

		if (foundDep->deptype == DEPENDENCY_PIN)
			ret = true;
	}

	systable_endscan(scan);

	return ret;
}
Esempio n. 17
0
/*
 * deleteDependencyRecordsFor -- delete all records with given depender
 * classId/objectId.  Returns the number of records deleted.
 *
 * This is used when redefining an existing object.  Links leading to the
 * object do not change, and links leading from it will be recreated
 * (possibly with some differences from before).
 *
 * If skipExtensionDeps is true, we do not delete any dependencies that
 * show that the given object is a member of an extension.  This avoids
 * needing a lot of extra logic to fetch and recreate that dependency.
 */
long
deleteDependencyRecordsFor(Oid classId, Oid objectId,
						   bool skipExtensionDeps)
{
	long		count = 0;
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, RowExclusiveLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_classid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(classId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_objid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(objectId));

	scan = systable_beginscan(depRel, DependDependerIndexId, true,
							  NULL, 2, key);

	while (HeapTupleIsValid(tup = systable_getnext(scan)))
	{
		if (skipExtensionDeps &&
		  ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
			continue;

		simple_heap_delete(depRel, &tup->t_self);
		count++;
	}

	systable_endscan(scan);

	heap_close(depRel, RowExclusiveLock);

	return count;
}
Esempio n. 18
0
/*
 * TableReferencing function checks whether given table is referencing by another table
 * via foreign constraints. If it is referencing, this function returns true. To check
 * that, this function searches given relation at pg_constraints system catalog. However
 * since there is no index for the column we searched, this function performs sequential
 * search, therefore call this function with caution.
 */
bool
TableReferencing(Oid relationId)
{
	Relation pgConstraint = NULL;
	HeapTuple heapTuple = NULL;
	SysScanDesc scanDescriptor = NULL;
	ScanKeyData scanKey[1];
	int scanKeyCount = 1;
	Oid scanIndexId = InvalidOid;
	bool useIndex = false;

	pgConstraint = heap_open(ConstraintRelationId, AccessShareLock);

	ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ,
				relationId);
	scanDescriptor = systable_beginscan(pgConstraint, scanIndexId, useIndex, NULL,
										scanKeyCount, scanKey);

	heapTuple = systable_getnext(scanDescriptor);
	while (HeapTupleIsValid(heapTuple))
	{
		Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);

		if (constraintForm->contype == CONSTRAINT_FOREIGN)
		{
			systable_endscan(scanDescriptor);
			heap_close(pgConstraint, NoLock);

			return true;
		}

		heapTuple = systable_getnext(scanDescriptor);
	}

	systable_endscan(scanDescriptor);
	heap_close(pgConstraint, NoLock);

	return false;
}
/*
* GetRoleTupleByOid -- as above, but search by role OID
*/
static HeapTuple
GetRoleTupleByName(const char * rolename)
{
	HeapTuple tuple;
	Relation relation;
	SysScanDesc scan;
	ScanKeyData key[1];

	/*
	* form a scan key
	*/
	ScanKeyInit(&key[0],
				Anum_pg_authid_rolname,
				BTEqualStrategyNumber, F_NAMEEQ,
				CStringGetDatum(rolename));

	/*
	* Open pg_authid and fetch a tuple. Force heap scan if we haven't yet
	* built the critical shared relcache entries (i.e., we're starting up
	* without a shared relcache cache file).
	*/
	relation = heap_open(AuthIdRelationId, AccessShareLock);
	scan = systable_beginscan(relation, AuthIdRolnameIndexId,
							criticalSharedRelcachesBuilt,
							SNAPSHOT,
							1, key);

	tuple = systable_getnext(scan);

	/* Must copy tuple before releasing buffer */
	if (HeapTupleIsValid(tuple))
		tuple = heap_copytuple(tuple);

	/* all done */
	systable_endscan(scan);
	heap_close(relation, AccessShareLock);

	return tuple;
}
Esempio n. 20
0
/*
 * GetNewOidWithIndex
 *		Guts of GetNewOid: use the supplied index
 *
 * This is exported separately because there are cases where we want to use
 * an index that will not be recognized by RelationGetOidIndex: TOAST tables
 * have indexes that are usable, but have multiple columns and are on
 * ordinary columns rather than a true OID column.  This code will work
 * anyway, so long as the OID is the index's first column.  The caller must
 * pass in the actual heap attnum of the OID column, however.
 *
 * Caller must have a suitable lock on the relation.
 */
Oid
GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
{
	Oid			newOid;
	SysScanDesc scan;
	ScanKeyData key;
	bool		collides;

	/*
	 * We should never be asked to generate a new pg_type OID during
	 * pg_upgrade; doing so would risk collisions with the OIDs it wants to
	 * assign.  Hitting this assert means there's some path where we failed to
	 * ensure that a type OID is determined by commands in the dump script.
	 */
	Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);

	/* Generate new OIDs until we find one not in the table */
	do
	{
		CHECK_FOR_INTERRUPTS();

		newOid = GetNewObjectId();

		ScanKeyInit(&key,
					oidcolumn,
					BTEqualStrategyNumber, F_OIDEQ,
					ObjectIdGetDatum(newOid));

		/* see notes above about using SnapshotAny */
		scan = systable_beginscan(relation, indexId, true,
								  SnapshotAny, 1, &key);

		collides = HeapTupleIsValid(systable_getnext(scan));

		systable_endscan(scan);
	} while (collides);

	return newOid;
}
Esempio n. 21
0
/*
 * GetDatabaseTupleByOid -- as above, but search by database OID
 */
static HeapTuple
GetDatabaseTupleByOid(Oid dboid)
{
    HeapTuple	tuple;
    Relation	relation;
    SysScanDesc scan;
    ScanKeyData key[1];

    /*
     * form a scan key
     */
    ScanKeyInit(&key[0],
                ObjectIdAttributeNumber,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(dboid));

    /*
     * Open pg_database and fetch a tuple.  Force heap scan if we haven't yet
     * built the critical shared relcache entries (i.e., we're starting up
     * without a shared relcache cache file).
     */
    relation = heap_open(DatabaseRelationId, AccessShareLock);
    scan = systable_beginscan(relation, DatabaseOidIndexId,
                              criticalSharedRelcachesBuilt,
                              NULL,
                              1, key);

    tuple = systable_getnext(scan);

    /* Must copy tuple before releasing buffer */
    if (HeapTupleIsValid(tuple))
        tuple = heap_copytuple(tuple);

    /* all done */
    systable_endscan(scan);
    heap_close(relation, AccessShareLock);

    return tuple;
}
Esempio n. 22
0
void
ParquetFetchSegFileInfo(AppendOnlyEntry *aoEntry, List *segfileinfos, Snapshot parquetMetaDataSnapshot)
{
	Relation pg_parquetseg_rel;
	TupleDesc pg_parquetseg_dsc;
	HeapTuple tuple;
	SysScanDesc parquetscan;

	/*
	 * Since this function is called for insert operation,
	 * here we use RowExclusiveLock.
	 */
	pg_parquetseg_rel = heap_open(aoEntry->segrelid, RowExclusiveLock);
	pg_parquetseg_dsc = RelationGetDescr(pg_parquetseg_rel);
	parquetscan = systable_beginscan(pg_parquetseg_rel, InvalidOid, FALSE,
									parquetMetaDataSnapshot, 0, NULL);

	while (HeapTupleIsValid(tuple = systable_getnext(parquetscan)))
	{
		ListCell *lc;
		int segno = DatumGetInt32(fastgetattr(tuple, Anum_pg_parquetseg_segno, pg_parquetseg_dsc, NULL));
		foreach (lc, segfileinfos)
		{
			ResultRelSegFileInfo *segfileinfo = (ResultRelSegFileInfo *)lfirst(lc);
			Assert(segfileinfo != NULL);
			if (segfileinfo->segno == segno)
			{
				segfileinfo->numfiles = 1;
				segfileinfo->tupcount = (int64)DatumGetFloat8(fastgetattr(tuple, Anum_pg_parquetseg_tupcount, pg_parquetseg_dsc, NULL));
				segfileinfo->varblock = 0;
				segfileinfo->eof = (int64 *)palloc(sizeof(int64));
				segfileinfo->eof[0] = (int64)DatumGetFloat8(fastgetattr(tuple, Anum_pg_parquetseg_eof, pg_parquetseg_dsc, NULL));
				segfileinfo->uncompressed_eof = (int64 *)palloc(sizeof(int64));
				segfileinfo->uncompressed_eof[0] = (int64)DatumGetFloat8(fastgetattr(tuple, Anum_pg_parquetseg_eofuncompressed, pg_parquetseg_dsc, NULL));
				break;
			}
		}
	}
Esempio n. 23
0
/*
 * RemoveExtTableEntry
 * 
 * Remove an external table entry from pg_exttable. Caller's 
 * responsibility to ensure that the relation has such an entry.
 */
void
RemoveExtTableEntry(Oid relid)
{
	Relation	pg_exttable_rel;
	ScanKeyData skey;
	SysScanDesc scan;
	HeapTuple	tuple;

	/*
	 * now remove the pg_exttable entry
	 */
	pg_exttable_rel = heap_open(ExtTableRelationId, RowExclusiveLock);

	ScanKeyInit(&skey,
				Anum_pg_exttable_reloid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(relid));

	scan = systable_beginscan(pg_exttable_rel, ExtTableReloidIndexId, true,
							  SnapshotNow, 1, &skey);
	tuple = systable_getnext(scan);
	if (!HeapTupleIsValid(tuple))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("external table object id \"%d\" does not exist",
						relid)));

	/*
	 * Delete the external table entry from the catalog (pg_exttable).
	 */
	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
		simple_heap_delete(pg_exttable_rel, &tuple->t_self);

	/* Finish up scan and close exttable catalog. */
	systable_endscan(scan);
	heap_close(pg_exttable_rel, NoLock);
}
Esempio n. 24
0
/* MPP-6923: 
 * GetResourceTypeByName: find the named resource in pg_resourcetype
 *
 * Input: name of resource
 * Output: resourcetypid (int2), oid of entry
 *
 * updates output and returns true if named resource found
 *
*/
static bool
GetResourceTypeByName(char *pNameIn, int *pTypeOut, Oid *pOidOut)
{
	Relation	pg_resourcetype;
	ScanKeyData scankey;
	SysScanDesc sscan;
	HeapTuple	tuple;
	bool		bStat = false;

	/*
	 * SELECT * FROM pg_resourcetype WHERE resname = :1 FOR UPDATE
	 *
	 * XXX XXX: maybe should be share lock, ie remove FOR UPDATE ?
	 * XXX XXX: only one
	 */
	pg_resourcetype = heap_open(ResourceTypeRelationId, RowExclusiveLock);

	ScanKeyInit(&scankey,
				Anum_pg_resourcetype_resname,
				BTEqualStrategyNumber, F_NAMEEQ,
				CStringGetDatum(pNameIn));
	sscan = systable_beginscan(pg_resourcetype, ResourceTypeResnameIndexId, true,
							   SnapshotNow, 1, &scankey);

	tuple = systable_getnext(sscan);
	if (HeapTupleIsValid(tuple))
	{
		*pOidOut = HeapTupleGetOid(tuple);
		*pTypeOut =
				((Form_pg_resourcetype) GETSTRUCT(tuple))->restypid;
		bStat = true;
	}
	systable_endscan(sscan);
	heap_close(pg_resourcetype, RowExclusiveLock);

	return (bStat);
} /* end GetResourceTypeByName */
/*
 * Remove any existing "owned" markers for the specified sequence.
 *
 * Note: we don't provide a special function to install an "owned"
 * marker; just use recordDependencyOn().
 */
void
markSequenceUnowned(Oid seqId)
{
	Relation	depRel;
	ScanKeyData key[2];
	SysScanDesc scan;
	HeapTuple	tup;

	depRel = heap_open(DependRelationId, RowExclusiveLock);

	ScanKeyInit(&key[0],
				Anum_pg_depend_classid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(RelationRelationId));
	ScanKeyInit(&key[1],
				Anum_pg_depend_objid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(seqId));

	scan = systable_beginscan(depRel, DependDependerIndexId, true,
							  SnapshotNow, 2, key);

	while (HeapTupleIsValid((tup = systable_getnext(scan))))
	{
		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);

		if (depform->refclassid == RelationRelationId &&
			depform->deptype == DEPENDENCY_AUTO)
		{
			simple_heap_delete(depRel, &tup->t_self);
		}
	}

	systable_endscan(scan);

	heap_close(depRel, RowExclusiveLock);
}
Esempio n. 26
0
/*
 * Same as LookupExtProtocolFunction but returns the actual
 * protocol Oid.
 */
Oid
LookupExtProtocolOid(const char *prot_name, bool missing_ok)
{
	Oid			protOid = InvalidOid;
	Relation	rel;
	ScanKeyData skey;
	SysScanDesc scan;
	HeapTuple	tup;

	rel = heap_open(ExtprotocolRelationId, AccessShareLock);

	/*
	 * Check the pg_extprotocol relation to be certain the protocol
	 * is there.
	 */
	ScanKeyInit(&skey,
				Anum_pg_extprotocol_ptcname,
				BTEqualStrategyNumber, F_NAMEEQ,
				CStringGetDatum(prot_name));
	scan = systable_beginscan(rel, ExtprotocolPtcnameIndexId, true,
							  SnapshotNow, 1, &skey);
	tup = systable_getnext(scan);

	if (HeapTupleIsValid(tup))
		protOid = HeapTupleGetOid(tup);
	else if (!missing_ok)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("protocol \"%s\" does not exist",
						prot_name)));

	systable_endscan(scan);
	heap_close(rel, AccessShareLock);

	return protOid;

}
Esempio n. 27
0
/*
 * regtypein		- converts "typename" to type OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_type entry.
 *
 * In bootstrap mode the name must just equal some existing name in pg_type.
 * In normal mode the type name can be specified using the full type syntax
 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
 * work and be translated to the correct type names.  (We ignore any typmod
 * info generated by the parser, however.)
 */
Datum
regtypein(PG_FUNCTION_ARGS)
{
	char	   *typ_name_or_oid = PG_GETARG_CSTRING(0);
	Oid			result = InvalidOid;
	int32		typmod;

	/* '-' ? */
	if (strcmp(typ_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (typ_name_or_oid[0] >= '0' &&
		typ_name_or_oid[0] <= '9' &&
		strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										  CStringGetDatum(typ_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/* Else it's a type name, possibly schema-qualified or decorated */

	/*
	 * In bootstrap mode we assume the given name is not schema-qualified, and
	 * just search pg_type for a match.  This is needed for initializing other
	 * system catalogs (pg_namespace may not exist yet, and certainly there
	 * are no schemas other than pg_catalog).
	 */
	if (IsBootstrapProcessingMode())
	{
		Relation	hdesc;
		ScanKeyData skey[1];
		SysScanDesc sysscan;
		HeapTuple	tuple;

		ScanKeyInit(&skey[0],
					Anum_pg_type_typname,
					BTEqualStrategyNumber, F_NAMEEQ,
					CStringGetDatum(typ_name_or_oid));

		hdesc = heap_open(TypeRelationId, AccessShareLock);
		sysscan = systable_beginscan(hdesc, TypeNameNspIndexId, true,
									 NULL, 1, skey);

		if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
			result = HeapTupleGetOid(tuple);
		else
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("type \"%s\" does not exist", typ_name_or_oid)));

		/* We assume there can be only one match */

		systable_endscan(sysscan);
		heap_close(hdesc, AccessShareLock);

		PG_RETURN_OID(result);
	}

	/*
	 * Normal case: invoke the full parser to deal with special cases such as
	 * array syntax.
	 */
	parseTypeString(typ_name_or_oid, &result, &typmod);

	PG_RETURN_OID(result);
}
Esempio n. 28
0
/*
 * regprocin		- converts "proname" to proc OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_proc entry.
 */
Datum
regprocin(PG_FUNCTION_ARGS)
{
	char	   *pro_name_or_oid = PG_GETARG_CSTRING(0);
	RegProcedure result = InvalidOid;
	List	   *names;
	FuncCandidateList clist;

	/* '-' ? */
	if (strcmp(pro_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (pro_name_or_oid[0] >= '0' &&
		pro_name_or_oid[0] <= '9' &&
		strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										  CStringGetDatum(pro_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/* Else it's a name, possibly schema-qualified */

	/*
	 * In bootstrap mode we assume the given name is not schema-qualified, and
	 * just search pg_proc for a unique match.	This is needed for
	 * initializing other system catalogs (pg_namespace may not exist yet, and
	 * certainly there are no schemas other than pg_catalog).
	 */
	if (IsBootstrapProcessingMode())
	{
		int			matches = 0;
		Relation	hdesc;
		ScanKeyData skey[1];
		SysScanDesc sysscan;
		HeapTuple	tuple;

		ScanKeyInit(&skey[0],
					Anum_pg_proc_proname,
					BTEqualStrategyNumber, F_NAMEEQ,
					CStringGetDatum(pro_name_or_oid));

		hdesc = heap_open(ProcedureRelationId, AccessShareLock);
		sysscan = systable_beginscan(hdesc, ProcedureNameArgsNspIndexId, true,
									 NULL, 1, skey);

		while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
		{
			result = (RegProcedure) HeapTupleGetOid(tuple);
			if (++matches > 1)
				break;
		}

		systable_endscan(sysscan);
		heap_close(hdesc, AccessShareLock);

		if (matches == 0)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));

		else if (matches > 1)
			ereport(ERROR,
					(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
					 errmsg("more than one function named \"%s\"",
							pro_name_or_oid)));

		PG_RETURN_OID(result);
	}

	/*
	 * Normal case: parse the name into components and see if it matches any
	 * pg_proc entries in the current search path.
	 */
	names = stringToQualifiedNameList(pro_name_or_oid);
	clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);

	if (clist == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_FUNCTION),
				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
	else if (clist->next != NULL)
		ereport(ERROR,
				(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
				 errmsg("more than one function named \"%s\"",
						pro_name_or_oid)));

	result = clist->oid;

	PG_RETURN_OID(result);
}
Esempio n. 29
0
/*
 * regclassin		- converts "classname" to class OID
 *
 * We also accept a numeric OID, for symmetry with the output routine.
 *
 * '-' signifies unknown (OID 0).  In all other cases, the input must
 * match an existing pg_class entry.
 */
Datum
regclassin(PG_FUNCTION_ARGS)
{
	char	   *class_name_or_oid = PG_GETARG_CSTRING(0);
	Oid			result = InvalidOid;
	List	   *names;

	/* '-' ? */
	if (strcmp(class_name_or_oid, "-") == 0)
		PG_RETURN_OID(InvalidOid);

	/* Numeric OID? */
	if (class_name_or_oid[0] >= '0' &&
		class_name_or_oid[0] <= '9' &&
		strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
	{
		result = DatumGetObjectId(DirectFunctionCall1(oidin,
										CStringGetDatum(class_name_or_oid)));
		PG_RETURN_OID(result);
	}

	/* Else it's a name, possibly schema-qualified */

	/*
	 * In bootstrap mode we assume the given name is not schema-qualified, and
	 * just search pg_class for a match.  This is needed for initializing
	 * other system catalogs (pg_namespace may not exist yet, and certainly
	 * there are no schemas other than pg_catalog).
	 */
	if (IsBootstrapProcessingMode())
	{
		Relation	hdesc;
		ScanKeyData skey[1];
		SysScanDesc sysscan;
		HeapTuple	tuple;

		ScanKeyInit(&skey[0],
					Anum_pg_class_relname,
					BTEqualStrategyNumber, F_NAMEEQ,
					CStringGetDatum(class_name_or_oid));

		hdesc = heap_open(RelationRelationId, AccessShareLock);
		sysscan = systable_beginscan(hdesc, ClassNameNspIndexId, true,
									 NULL, 1, skey);

		if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
			result = HeapTupleGetOid(tuple);
		else
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_TABLE),
			   errmsg("relation \"%s\" does not exist", class_name_or_oid)));

		/* We assume there can be only one match */

		systable_endscan(sysscan);
		heap_close(hdesc, AccessShareLock);

		PG_RETURN_OID(result);
	}

	/*
	 * Normal case: parse the name into components and see if it matches any
	 * pg_class entries in the current search path.
	 */
	names = stringToQualifiedNameList(class_name_or_oid);

	/* We might not even have permissions on this relation; don't lock it. */
	result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, false);

	PG_RETURN_OID(result);
}
Esempio n. 30
0
Datum
gp_inject_fault(PG_FUNCTION_ARGS)
{
	char	   *faultName = TextDatumGetCString(PG_GETARG_DATUM(0));
	char	   *type = TextDatumGetCString(PG_GETARG_DATUM(1));
	char	   *ddlStatement = TextDatumGetCString(PG_GETARG_DATUM(2));
	char	   *databaseName = TextDatumGetCString(PG_GETARG_DATUM(3));
	char	   *tableName = TextDatumGetCString(PG_GETARG_DATUM(4));
	int			numOccurrences = PG_GETARG_INT32(5);
	int			sleepTimeSeconds = PG_GETARG_INT32(6);
	int         dbid = PG_GETARG_INT32(7);
	StringInfo  faultmsg = makeStringInfo();

	/* Fast path if injecting fault in our postmaster. */
	if (GpIdentity.dbid == dbid)
	{
		appendStringInfo(faultmsg, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
						 faultName, type, ddlStatement, databaseName,
						 tableName, numOccurrences, sleepTimeSeconds);
		int offset = 0;
		char *response =
			processTransitionRequest_faultInject(
				faultmsg->data, &offset, faultmsg->len);
		if (!response)
			elog(ERROR, "failed to inject fault locally (dbid %d)", dbid);
		if (strncmp(response, "Success:",  strlen("Success:")) != 0)
			elog(ERROR, "%s", response);

		elog(NOTICE, "%s", response);
		PG_RETURN_DATUM(true);
	}

	/* Obtain host and port of the requested dbid */
	HeapTuple tuple;
	Relation rel = heap_open(GpSegmentConfigRelationId, AccessShareLock);
	ScanKeyData scankey;
	SysScanDesc sscan;
	ScanKeyInit(&scankey,
				Anum_gp_segment_configuration_dbid,
				BTEqualStrategyNumber, F_INT2EQ,
				Int16GetDatum((int16) dbid));
	sscan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
							   GetTransactionSnapshot(), 1, &scankey);
	tuple = systable_getnext(sscan);

	if (!HeapTupleIsValid(tuple))
		elog(ERROR, "cannot find dbid %d", dbid);

	bool isnull;
	Datum datum = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
							   RelationGetDescr(rel), &isnull);
	char *hostname;
	if (!isnull)
		hostname =
				DatumGetCString(DirectFunctionCall1(textout, datum));
	else
		elog(ERROR, "hostname is null for dbid %d", dbid);
	int port = DatumGetInt32(heap_getattr(tuple,
										  Anum_gp_segment_configuration_port,
										  RelationGetDescr(rel), &isnull));
	systable_endscan(sscan);
	heap_close(rel, NoLock);

	struct addrinfo *addrList = NULL;
	struct addrinfo hint;
	int			ret;

	/* Initialize hint structure */
	MemSet(&hint, 0, sizeof(hint));
	hint.ai_socktype = SOCK_STREAM;
	hint.ai_family = AF_UNSPEC;

	char portStr[100];
	if (snprintf(portStr, sizeof(portStr), "%d", port) >= sizeof(portStr))
		elog(ERROR, "port number too long for dbid %d", dbid);

	/* Use pg_getaddrinfo_all() to resolve the address */
	ret = pg_getaddrinfo_all(hostname, portStr, &hint, &addrList);
	if (ret || !addrList)
	{
		if (addrList)
			pg_freeaddrinfo_all(hint.ai_family, addrList);
		elog(ERROR, "could not translate host name \"%s\" to address: %s\n",
			 hostname, gai_strerror(ret));
	}

	PrimaryMirrorTransitionClientInfo client;
	client.receivedDataCallbackFn = transitionReceivedDataFn;
	client.errorLogFn = transitionErrorLogFn;
	client.checkForNeedToExitFn = checkForNeedToExitFn;
	transitionMsgErrors = makeStringInfo();

	appendStringInfo(faultmsg, "%s\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
					 "faultInject",	faultName, type, ddlStatement,
					 databaseName, tableName, numOccurrences,
					 sleepTimeSeconds);

	if (sendTransitionMessage(&client, addrList, faultmsg->data, faultmsg->len,
							  1 /* retries */, 60 /* timeout */) !=
		TRANS_ERRCODE_SUCCESS)
	{
		pg_freeaddrinfo_all(hint.ai_family, addrList);
		ereport(ERROR, (errmsg("failed to inject %s fault in dbid %d",
							   faultName, dbid),
						errdetail("%s", transitionMsgErrors->data)));
	}

	pg_freeaddrinfo_all(hint.ai_family, addrList);
	PG_RETURN_DATUM(BoolGetDatum(true));
}