Ejemplo n.º 1
0
/*
 * TypeRename
 *		This renames a type
 *
 * Note: any associated array type is *not* renamed; caller must make
 * another call to handle that case.  Currently this is only used for
 * renaming types associated with tables, for which there are no arrays.
 */
void
TypeRename(Oid typeOid, const char *newTypeName)
{
	Relation		pg_type_desc;
	HeapTuple		tuple;
	Form_pg_type	form;
	cqContext	   *pcqCtx;
	cqContext		cqc, cqc2;

	pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);

	pcqCtx = caql_addrel(cqclr(&cqc), pg_type_desc);

	tuple = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_type "
				" WHERE oid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(typeOid)));

	if (!HeapTupleIsValid(tuple))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("type with OID \"%d\" does not exist", typeOid)));

	form = (Form_pg_type) GETSTRUCT(tuple);
	if (namestrcmp(&(form->typname), newTypeName))
	{
		if (caql_getcount(
					caql_addrel(cqclr(&cqc2), pg_type_desc),
					cql("SELECT COUNT(*) FROM pg_type "
						" WHERE typname = :1 "
						" AND typnamespace = :2 ",
						CStringGetDatum((char *) newTypeName),
						ObjectIdGetDatum(form->typnamespace))))
		{
			ereport(ERROR,
					(errcode(ERRCODE_DUPLICATE_OBJECT),
					 errmsg("type \"%s\" already exists", newTypeName)));
		}

		namestrcpy(&(form->typname), newTypeName);

		caql_update_current(pcqCtx, tuple);
		/* update the system catalog indexes (implicit) */
	}

	heap_freetuple(tuple);
	heap_close(pg_type_desc, RowExclusiveLock);
}
Ejemplo n.º 2
0
/*
 * Removes the policy of a table from the gp_distribution_policy table

 * Does nothing if the policy doesn't exist.
 */
void
GpPolicyRemove(Oid tbloid)
{
	Relation	gp_policy_rel;
	cqContext	cqc;

    /*
     * Open and lock the gp_distribution_policy catalog.
     */
	gp_policy_rel = heap_open(GpPolicyRelationId, RowExclusiveLock);

	/* Delete the policy entry from the catalog. */
	(void) caql_getcount(
		caql_addrel(cqclr(&cqc), gp_policy_rel),
		cql("DELETE FROM gp_distribution_policy "
			" WHERE localoid = :1 ",
			ObjectIdGetDatum(tbloid)));

	/*
     * Close the gp_distribution_policy relcache entry without unlocking.
     * We have updated the catalog: consequently the lock must be held until
     * end of transaction.
     */
    heap_close(gp_policy_rel, NoLock);
}                               /* GpPolicyRemove */
Ejemplo n.º 3
0
/*
 * Remove the master standby.
 *
 * gp_remove_master_standby()
 *
 * Returns:
 *  true upon success otherwise false
 */
Datum
gp_remove_master_standby(PG_FUNCTION_ARGS)
{
	int numDel;
	cqContext	cqc;

	mirroring_sanity_check(SUPERUSER | MASTER_ONLY | UTILITY_MODE,
						   "gp_remove_master_standby");

	if (!standby_exists())
		elog(ERROR, "no master standby defined");

	Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock);
	numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel),
				cql("DELETE FROM gp_segment_configuration "
					" WHERE role = :1",
					CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG)));

	elog(LOG, "Remove standby, count : %d.", numDel);

	heap_close(rel, NoLock);

	update_gp_master_mirroring("Not Configured");

	PG_RETURN_BOOL(true);
}
Ejemplo n.º 4
0
/*
 * Activate a standby. To do this, we need to change
 *
 * 1. Check that we're actually the standby
 * 2. Remove standby from gp_segment_configuration.
 *
 * gp_activate_standby()
 *
 * Returns:
 *  true upon success, otherwise throws error.
 */
Datum
gp_activate_standby(PG_FUNCTION_ARGS)
{
	cqContext cqc;
	int numDel;
	mirroring_sanity_check(SUPERUSER | UTILITY_MODE | STANDBY_ONLY,
						   PG_FUNCNAME_MACRO);

	if (!AmIStandby())
		elog(ERROR, "%s must be run on the standby master",
			 PG_FUNCNAME_MACRO);

	/* remove standby from gp_segment_configuration */
	Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock);
	numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel),
				cql("DELETE FROM gp_segment_configuration "
					" WHERE role = :1",
					CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG)));

	elog(LOG, "Remove standby while activating it, count : %d.", numDel);

	heap_close(rel, NoLock);

	/* done */
	PG_RETURN_BOOL(true);
}
Ejemplo n.º 5
0
/*
 * Removes the policy of a table from the gp_distribution_policy table
 *
 * Callers must check that there actually *is* a policy for the relation.
 */
void
GpPolicyRemove(Oid tbloid)
{
	Relation	gp_policy_rel;
	cqContext	cqc;

    /*
     * Open and lock the gp_distribution_policy catalog.
     */
	gp_policy_rel = heap_open(GpPolicyRelationId, RowExclusiveLock);

	/* Delete the policy entry from the catalog. */
	if (0 == caql_getcount(
				caql_addrel(cqclr(&cqc), gp_policy_rel),
				cql("DELETE FROM gp_distribution_policy "
					" WHERE localoid = :1 ",
					ObjectIdGetDatum(tbloid))))
	{
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("distribution policy for relation \"%d\" does not exist",
						tbloid)));
	}

	/*
     * Close the gp_distribution_policy relcache entry without unlocking.
     * We have updated the catalog: consequently the lock must be held until
     * end of transaction.
     */
    heap_close(gp_policy_rel, NoLock);
}                               /* GpPolicyRemove */
Ejemplo n.º 6
0
void update_segment_status_by_id(uint32_t id, char status)
{
	/* we use AccessExclusiveLock to prevent races */
	Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock);
	HeapTuple tuple;
	cqContext	cqc;
	cqContext  *pcqCtx;

	Assert(status == 'u' || status == 'd');

	pcqCtx = caql_beginscan(caql_addrel(cqclr(&cqc), rel),
						cql("SELECT * FROM gp_segment_configuration "
							" WHERE registration_order = :1 "
							" FOR UPDATE ",
							Int32GetDatum(id)));

	tuple = caql_getnext(pcqCtx);

	if (tuple != NULL) {
		if (((Form_gp_segment_configuration)GETSTRUCT(tuple))->status != status) {
			((Form_gp_segment_configuration)GETSTRUCT(tuple))->status = status;
			caql_update_current(pcqCtx, tuple);
		}
	} else {
		elog(LOG, "Can not find segment id: %d when update its status", id);
	}

	caql_endscan(pcqCtx);

	heap_close(rel, NoLock);
}
Ejemplo n.º 7
0
/*
 * GetFastSequences
 *
 * Get a list of consecutive sequence numbers. The starting sequence
 * number is the maximal value between 'lastsequence' + 1 and minSequence.
 * The length of the list is given.
 *
 * If there is not such an entry for objid in the table, create
 * one here.
 *
 * The existing entry for objid in the table is updated with a new
 * lastsequence value.
 */
int64 GetFastSequences(Oid objid, int64 objmod,
					   int64 minSequence, int64 numSequences)
{
	Relation gp_fastsequence_rel;
	TupleDesc tupleDesc;
	HeapTuple tuple;
	cqContext	 cqc;
	int64 firstSequence = minSequence;
	Datum lastSequenceDatum;
	int64 newLastSequence;

	gp_fastsequence_rel = heap_open(FastSequenceRelationId, RowExclusiveLock);
	tupleDesc = RelationGetDescr(gp_fastsequence_rel);
	
	tuple = caql_getfirst(
			caql_addrel(cqclr(&cqc), gp_fastsequence_rel),
			cql("SELECT * FROM gp_fastsequence "
				" WHERE objid = :1 "
				" AND objmod = :2 "
				" FOR UPDATE ",
				ObjectIdGetDatum(objid),
				Int64GetDatum(objmod)));

	if (!HeapTupleIsValid(tuple))
	{
		newLastSequence = firstSequence + numSequences - 1;
	}
	else
	{
		bool isNull;

		lastSequenceDatum = heap_getattr(tuple, Anum_gp_fastsequence_last_sequence,
										tupleDesc, &isNull);
		
		if (isNull)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("got an invalid lastsequence number: NULL")));
		
		if (DatumGetInt64(lastSequenceDatum) + 1 > firstSequence)
			firstSequence = DatumGetInt64(lastSequenceDatum) + 1;
		newLastSequence = firstSequence + numSequences - 1;
	}
	
	update_fastsequence(gp_fastsequence_rel, tuple, tupleDesc,
						objid, objmod, newLastSequence);

	if (HeapTupleIsValid(tuple))
	{
		heap_freetuple(tuple);
	}
		
	/* Refer to the comment at the end of InsertFastSequenceEntry. */
	heap_close(gp_fastsequence_rel, RowExclusiveLock);

	return firstSequence;
}
Ejemplo n.º 8
0
/*
 * Add a master standby.
 *
 * gp_add_master_standby(hostname, address)
 *
 * Args:
 *  hostname - as above
 *  address - as above
 *
 * Returns:
 *  dbid of the new standby
 */
Datum
gp_add_master_standby(PG_FUNCTION_ARGS)
{
	CdbComponentDatabaseInfo *master = NULL;
	Relation	gprel;
	Datum values[Natts_gp_segment_configuration];
	bool nulls[Natts_gp_segment_configuration];
	HeapTuple tuple;
	cqContext	cqc;
	cqContext  *pcqCtx = NULL;

	if (PG_ARGISNULL(0))
		elog(ERROR, "host name cannot be NULL");
	if (PG_ARGISNULL(1))
		elog(ERROR, "address cannot be NULL");

	mirroring_sanity_check(MASTER_ONLY | UTILITY_MODE,
						   "gp_add_master_standby");

	if (standby_exists())
		elog(ERROR, "only a single master standby may be defined");

	/* master */
	master = registration_order_get_dbinfo(MASTER_ORDER_ID);

	/* Lock exclusively to avoid concurrent changes */
	gprel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock);

	pcqCtx = caql_beginscan(
				caql_addrel(cqclr(&cqc), gprel),
				cql("INSERT INTO gp_segment_configuration ", NULL));

	MemSet(nulls, false, sizeof(nulls));

	values[Anum_gp_segment_configuration_registration_order - 1] = Int32GetDatum(STANDBY_ORDER_ID);
	values[Anum_gp_segment_configuration_role - 1] = CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG);
	values[Anum_gp_segment_configuration_status - 1] = CharGetDatum('u');
	values[Anum_gp_segment_configuration_port - 1] = Int32GetDatum(master->port);
	values[Anum_gp_segment_configuration_hostname - 1] = PG_GETARG_DATUM(0);
	values[Anum_gp_segment_configuration_address - 1] = PG_GETARG_DATUM(1);
	nulls[Anum_gp_segment_configuration_description - 1] = true;

	tuple = caql_form_tuple(pcqCtx, values, nulls);

	/* insert a new tuple */
	caql_insert(pcqCtx, tuple); /* implicit update of index as well */

	caql_endscan(pcqCtx);

	if(master)
		pfree(master);

	heap_close(gprel, NoLock);

	PG_RETURN_INT16(1);
}
/*
 * This tests if non-equal predicates also use index scan.
 */
void
test__caql_switch5(void **state)
{
	const char		   *query = "SELECT * FROM pg_attribute "
								"WHERE attrelid = :1 and attnum > :2";
	struct caql_hash_cookie *hash_cookie;
	cqContext			context = {0}, *pCtx;
	Datum				keys[] = {ObjectIdGetDatum(ProcedureRelationId),
								  Int16GetDatum(0)};
	cq_list			   *pcql = CaQL(query, 2, keys);
	RelationData		dummyrel;
	SysScanDescData		dummydesc;

	dummyrel.rd_id = AttributeRelationId;

	hash_cookie = cq_lookup(query, strlen(query), pcql);

	/*
	 * Add explicit relation, and set indexOK = true and syscache = false.
	 */
	pCtx = caql_addrel(cqclr(&context), &dummyrel);
	pCtx = caql_indexOK(pCtx, true);
	pCtx = caql_syscache(pCtx, false);

	/* setup ScanKeyInit */
	expect__ScanKeyInit(NULL, false,
						Anum_pg_attribute_attrelid, true,
						BTEqualStrategyNumber, true,
						F_OIDEQ, true,
						NULL, false);

	/* setup ScanKeyInit */
	expect__ScanKeyInit(NULL, false,
						Anum_pg_attribute_attnum, true,
						BTGreaterStrategyNumber, true,
						F_INT2GT, true,
						NULL, false);

	/* setup systable_beginscan */
	expect__systable_beginscan(&dummyrel, true,
							   AttributeRelidNumIndexId, true,
							   true, true,
							   SnapshotNow, true,
							   2, true,
							   NULL, false,
							   &dummydesc);

	pCtx = caql_switch(hash_cookie, pCtx, pcql);

	assert_true(pCtx != NULL);
	assert_true(pCtx->cq_sysScan == &dummydesc);
	assert_true(pCtx->cq_heap_rel == &dummyrel);
	assert_false(pCtx->cq_usesyscache);
	assert_true(pCtx->cq_useidxOK);
}
Ejemplo n.º 10
0
/*
 * SetRelationRuleStatus
 *		Set the value of the relation's relhasrules field in pg_class;
 *		if the relation is becoming a view, also adjust its relkind.
 *
 * NOTE: caller must be holding an appropriate lock on the relation.
 *
 * NOTE: an important side-effect of this operation is that an SI invalidation
 * message is sent out to all backends --- including me --- causing relcache
 * entries to be flushed or updated with the new set of rules for the table.
 * This must happen even if we find that no change is needed in the pg_class
 * row.
 */
void
SetRelationRuleStatus(Oid relationId, bool relHasRules,
					  bool relIsBecomingView)
{
	Relation	relationRelation;
	HeapTuple	tuple;
	Form_pg_class classForm;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/*
	 * Find the tuple to update in pg_class, using syscache for the lookup.
	 */
	relationRelation = heap_open(RelationRelationId, RowExclusiveLock);

	pcqCtx = caql_addrel(cqclr(&cqc), relationRelation);

	tuple = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_class "
				" WHERE oid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(relationId)));

	if (!HeapTupleIsValid(tuple))
		elog(ERROR, "cache lookup failed for relation %u", relationId);
	classForm = (Form_pg_class) GETSTRUCT(tuple);

	if (classForm->relhasrules != relHasRules ||
		(relIsBecomingView && classForm->relkind != RELKIND_VIEW))
	{
		/* Do the update */
		classForm->relhasrules = relHasRules;
		if (relIsBecomingView)
		{
			classForm->relkind = RELKIND_VIEW;
			classForm->relstorage = RELSTORAGE_VIRTUAL;
		}

		caql_update_current(pcqCtx, tuple); /* implicit update of index  */
	}
	else
	{
		/* no need to change tuple, but force relcache rebuild anyway */
		CacheInvalidateRelcacheByTuple(tuple);
	}

	heap_freetuple(tuple);
	heap_close(relationRelation, RowExclusiveLock);
}
Ejemplo n.º 11
0
/*
 * IsErrorTable
 *
 * Returns true if relid is used as an error table, which has dependent object
 * that is an external table.  Though it's not great we didn't have a clear
 * definition of Error Table, it satisfies the current requirements.
 */
bool
IsErrorTable(Relation rel)
{
	cqContext	   *pcqCtx, *pcqCtxExt, ctxExt;
	HeapTuple		tup;
	Relation		extrel;
	bool			result = false;

	/* fast path to quick check */
	if (!RelationIsHeap(rel))
		return false;

	/*
	 * Otherwise, go deeper and play with pg_depend...
	 */
	pcqCtx = caql_beginscan(NULL,
							cql("SELECT * FROM pg_depend "
								" WHERE refclassid = :1 "
								" AND refobjid = :2 "
								" AND refobjsubid = :3 ",
								ObjectIdGetDatum(RelationRelationId),
								ObjectIdGetDatum(RelationGetRelid(rel)),
								Int32GetDatum(0)));

	extrel = relation_open(ExtTableRelationId, AccessShareLock);
	pcqCtxExt = caql_addrel(cqclr(&ctxExt), extrel);

	while (HeapTupleIsValid(tup = caql_getnext(pcqCtx)))
	{
		Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(tup);
		Oid				fmterrtbl;

		fmterrtbl = caql_getoid(pcqCtxExt,
								cql("SELECT fmterrtbl FROM pg_exttable "
									" WHERE reloid = :1",
									ObjectIdGetDatum(dep->objid)));
		if (RelationGetRelid(rel) == fmterrtbl)
		{
			result = true;
			break;
		}
	}

	relation_close(extrel, AccessShareLock);

	caql_endscan(pcqCtx);

	return result;
}
/*
 * Get datum representations of the attoptions field in pg_attribute_encoding
 * for the given relation.
 */
Datum *
get_rel_attoptions(Oid relid, AttrNumber max_attno)
{
	Form_pg_attribute attform;
	HeapTuple		tuple;
	cqContext		cqc;
	cqContext	   *pcqCtx;
	Datum		   *dats;
	Relation 		pgae = heap_open(AttributeEncodingRelationId,
									 AccessShareLock);

	/* used for attbyval and len below */
	attform = pgae->rd_att->attrs[Anum_pg_attribute_encoding_attoptions - 1];

	dats = palloc0(max_attno * sizeof(Datum));

	pcqCtx = caql_beginscan(
			caql_addrel(cqclr(&cqc), pgae),
			cql("SELECT * FROM pg_attribute_encoding "
				" WHERE attrelid = :1 ",
				ObjectIdGetDatum(relid)));

	while (HeapTupleIsValid(tuple = caql_getnext(pcqCtx)))
	{
		Form_pg_attribute_encoding a = 
			(Form_pg_attribute_encoding)GETSTRUCT(tuple);
		int16 attnum = a->attnum;
		Datum attoptions;
		bool isnull;

		Insist(attnum > 0 && attnum <= max_attno);

		attoptions = heap_getattr(tuple, Anum_pg_attribute_encoding_attoptions,
								  RelationGetDescr(pgae), &isnull);
		Insist(!isnull);

		dats[attnum - 1] = datumCopy(attoptions,
									 attform->attbyval,
									 attform->attlen);
	}

	caql_endscan(pcqCtx);

	heap_close(pgae, AccessShareLock);

	return dats;

}
Ejemplo n.º 13
0
/* convert schema type from old dboid to newdboid */
bool convert_schema_type(char *schema, Oid oldDboid, Oid newDboid)
{
	Assert(NSPDBOID_CURRENT == oldDboid || NSPDBOID_CURRENT == newDboid);
	Assert(HcatalogDbOid == oldDboid || HcatalogDbOid == newDboid);
	Assert(newDboid != oldDboid);

	/* create tuples for pg_class table */
	HeapTuple nsptup = NULL;
	HeapTuple copytup = NULL;
	cqContext	cqc;

	Assert(Gp_role != GP_ROLE_EXECUTE);

	Relation rel = heap_open(NamespaceRelationId, RowExclusiveLock);

	cqContext *pcqCtx = caql_addrel(cqclr(&cqc), rel);
	nsptup =  caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_namespace "
				" WHERE nspname = :1 and nspdboid = :2",
				CStringGetDatum(schema), ObjectIdGetDatum(oldDboid)));


	if (!HeapTupleIsValid(nsptup))
	{
		heap_close(rel, NoLock);
		return false;
	}

	Datum values[Natts_pg_namespace];
	bool nulls[Natts_pg_namespace];
	bool replaces[Natts_pg_namespace];
	
	MemSet(values, 0, sizeof(values));
	MemSet(nulls, false, sizeof(nulls));
	MemSet(replaces, false, sizeof(replaces));
	
	replaces[Anum_pg_namespace_nspdboid - 1] = true;
	values[Anum_pg_namespace_nspdboid - 1] = newDboid;
	copytup = caql_modify_current(pcqCtx, values, nulls, replaces);

	caql_update_current(pcqCtx, copytup);
	heap_close(rel, NoLock);

	heap_freetuple(copytup);
	
	return true;
}
Ejemplo n.º 14
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;
	HeapTuple	tup;
	cqContext  *pcqCtx;
	cqContext	cqc;

	conDesc = heap_open(ConstraintRelationId, AccessShareLock);

	found = false;

	pcqCtx = caql_beginscan(
			caql_addrel(cqclr(&cqc), conDesc),
			cql("SELECT * FROM pg_constraint "
				" WHERE conname = :1 "
				" AND connamespace = :2 ",
				CStringGetDatum((char *) conname),
				ObjectIdGetDatum(objNamespace)));

	while (HeapTupleIsValid(tup = caql_getnext(pcqCtx)))
	{
		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;
		}
	}

	caql_endscan(pcqCtx);
	heap_close(conDesc, AccessShareLock);

	return found;
}
Ejemplo n.º 15
0
/* ----------------------------------------------------------------
 * caql_begin_CacheList()
 * Return a catclist
 *
 * In general, catquery will choose the syscache when the cql
 * statement contains an equality predicate on *all* of the syscache
 * primary key index columns, eg:
 *
 *   cql("SELECT * FROM pg_amop WHERE amopopr = :1 and amopclaid = :2 ")
 *
 * will use the AMOPOPID syscache with index
 * AccessMethodOperatorIndexId.  However, the cql statement for a
 * list-search requires an equality predicate on a subset of the
 * initial columns of the index, with *all* of the index columns
 * specified in an ORDER BY clause, eg:
 *
 *   cql("SELECT * FROM pg_amop WHERE amopopr = :1 "
 *       " ORDER BY amopopr, amopclaid ")
 *
 * will use a syscache list-search if this cql statement is an
 * argument to caql_begin_CacheList().  However, the syscache will
 * *not* be used for this statement if it is supplied for
 * caql_beginscan(), since SearchSysCache() can only return (at most)
 * a single tuple.
 *
 * NOTE: caql_begin_CacheList() will assert (Insist!) at runtime if
 * the cql statement does not map to a syscache lookup.
 * NOTE: it may be possible to "collapse" this API into the existing
 * beginscan/getnext/endscan.
 * ----------------------------------------------------------------
 */
struct catclist *
caql_begin_CacheList(cqContext *pCtx0,
					 cq_list *pcql)
{
	const char*				 caql_str = pcql->caqlStr;
	const char*				 filenam  = pcql->filename;
	int						 lineno	  = pcql->lineno;
	struct caql_hash_cookie	*pchn	  = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext				*pCtx;
	cqContext				 cqc;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d",
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */
	Assert(!pchn->bUpdate); /* UPDATE not allowed */
	Assert(!pchn->bDelete); /* DELETE not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	/* NOTE: for case of cache list search, we must use syscache */
	pCtx->cq_bCacheList = true;

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */

	/* NOTE: must use the SysCache */
	Insist (pCtx->cq_usesyscache);

	caql_heapclose(pCtx);

	return SearchSysCacheKeyArrayList(pCtx->cq_cacheId,
									  pCtx->cq_NumKeys,
									  pCtx->cq_cacheKeys);
}
Ejemplo n.º 16
0
/*
 * Master function to remove a segment from all catalogs
 */
static void
remove_segment(int16 order)
{
	cqContext cqc;
	int numDel;

	if(order == MASTER_ORDER_ID || order == STANDBY_ORDER_ID)
		return;

	/* remove this segment from gp_segment_configuration */
	Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock);
	numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel),
				cql("DELETE FROM gp_segment_configuration "
					" WHERE registration_order = :1",
					Int16GetDatum(order)));

	elog(LOG, "Remove segment successfully! Count : %d. Registration order : %d",
			  numDel,
			  order);

	heap_close(rel, NoLock);
}
Ejemplo n.º 17
0
void
ExtProtocolDeleteByOid(Oid	protOid)
{		
	Relation	rel;
	cqContext	cqc;

	/*
	 * Search pg_extprotocol.  We use a heapscan here even though there is an
	 * index on oid, on the theory that pg_extprotocol will usually have just a
	 * few entries and so an indexed lookup is a waste of effort.
	 */
	rel = heap_open(ExtprotocolRelationId, RowExclusiveLock);

	if (0 == caql_getcount(
				caql_addrel(cqclr(&cqc), rel),
				cql("DELETE FROM pg_extprotocol "
					" WHERE oid = :1 ",
					ObjectIdGetDatum(protOid))))
	{
		elog(ERROR, "protocol %u could not be found", protOid);
	}
	heap_close(rel, NoLock);
}
Ejemplo n.º 18
0
/*
 * Sets the policy of a table into the gp_distribution_policy table
 * from a GpPolicy structure.
 *
 */
void
GpPolicyReplace(Oid tbloid, const GpPolicy *policy)
{
	Relation	gp_policy_rel;
	HeapTuple	gp_policy_tuple = NULL;
	cqContext	cqc;
	cqContext  *pcqCtx;

	ArrayType  *attrnums;

	bool		nulls[2];
	Datum		values[2];
	bool		repl[2];

	Insist(policy->ptype == POLICYTYPE_PARTITIONED);

    /*
     * Open and lock the gp_distribution_policy catalog.
     */
	gp_policy_rel = heap_open(GpPolicyRelationId, RowExclusiveLock);

	pcqCtx = caql_addrel(cqclr(&cqc), gp_policy_rel);

	/*
	 * Convert C arrays into Postgres arrays.
	 */
	if (policy->nattrs > 0)
	{
		int			i;
		Datum	   *akey;

		akey = (Datum *) palloc(policy->nattrs * sizeof(Datum));
		for (i = 0; i < policy->nattrs; i++)
			akey[i] = Int16GetDatum(policy->attrs[i]);
		attrnums = construct_array(akey, policy->nattrs,
								   INT2OID, 2, true, 's');
	}
	else
	{
		attrnums = NULL;
	}

	nulls[0] = false;
	nulls[1] = false;
	values[0] = ObjectIdGetDatum(tbloid);

	if (attrnums)
		values[1] = PointerGetDatum(attrnums);
	else
		nulls[1] = true;
		
	repl[0] = false;
	repl[1] = true;


	/*
	 * Select by value of the localoid field
	 */
	gp_policy_tuple = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM gp_distribution_policy "
				" WHERE localoid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(tbloid)));

	/*
	 * Read first (and only ) tuple
	 */

	if (HeapTupleIsValid(gp_policy_tuple))
	{
		
		HeapTuple newtuple = caql_modify_current(pcqCtx, values,
												 nulls, repl);
								
		caql_update_current(pcqCtx, newtuple); 
		/* and Update indexes (implicit) */

		heap_freetuple(newtuple);
	}
	else
	{
		gp_policy_tuple = caql_form_tuple(pcqCtx, values, nulls);
		caql_insert(pcqCtx, gp_policy_tuple);
		/* and Update indexes (implicit) */
	}
	
	/*
     * Close the gp_distribution_policy relcache entry without unlocking.
     * We have updated the catalog: consequently the lock must be held until
     * end of transaction.
     */
    heap_close(gp_policy_rel, NoLock);
}                               /* GpPolicyReplace */
Ejemplo n.º 19
0
/*
 * get dbinfo by role
 * There should be only one master in gp_segment_configuration table, one standby at most.
 */
CdbComponentDatabaseInfo *
role_get_dbinfo(char role)
{
	HeapTuple tuple;
	Relation rel;
	cqContext	cqc;
	bool bOnly;
	CdbComponentDatabaseInfo *i = NULL;

	Assert(role == SEGMENT_ROLE_PRIMARY ||
		   role == SEGMENT_ROLE_MASTER_CONFIG ||
		   role == SEGMENT_ROLE_STANDBY_CONFIG);
	/*
	 * Can only run on a master node, this restriction is due to the reliance
	 * on the gp_segment_configuration table.  This may be able to be relaxed
	 * by switching to a different method of checking.
	 */
	if (!AmActiveMaster() && !AmStandbyMaster())
		elog(ERROR, "role_get_dbinfo() executed on execution segment");

	rel = heap_open(GpSegmentConfigRelationId, AccessShareLock);

	tuple = caql_getfirst_only(
			caql_addrel(cqclr(&cqc), rel),
			&bOnly,
			cql("SELECT * FROM gp_segment_configuration "
				" WHERE role = :1 ",
				CharGetDatum(role)));

	if (HeapTupleIsValid(tuple))
	{
		Datum attr;
		bool isNull;

		i = palloc(sizeof(CdbComponentDatabaseInfo));

		/*
		 * role
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_role,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->role = DatumGetChar(attr);

		/*
		 * status
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_status,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->status = DatumGetChar(attr);

		/*
		 * hostname
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->hostname = TextDatumGetCString(attr);

		/*
		 * address
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_address,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->address = TextDatumGetCString(attr);

		/*
		 * port
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->port = DatumGetInt32(attr);

	}
	else
	{
		elog(ERROR, "could not find configuration entry for role %c", role);
	}

	heap_close(rel, NoLock);

	return i;
}
Ejemplo n.º 20
0
CdbComponentDatabaseInfo *
dbid_get_dbinfo(int16 dbid)
{
	HeapTuple tuple;
	Relation rel;
	cqContext	cqc;
	bool bOnly;
	CdbComponentDatabaseInfo *i = NULL;

	/*
	 * Can only run on a master node, this restriction is due to the reliance
	 * on the gp_segment_configuration table.  This may be able to be relaxed
	 * by switching to a different method of checking.
	 */
	if (GpIdentity.segindex != MASTER_CONTENT_ID)
		elog(ERROR, "dbid_get_dbinfo() executed on execution segment");

	rel = heap_open(GpSegmentConfigRelationId, AccessShareLock);

	tuple = caql_getfirst_only(
			caql_addrel(cqclr(&cqc), rel),
			&bOnly,
			cql("SELECT * FROM gp_segment_configuration "
				" WHERE dbid = :1 ",
				Int16GetDatum(dbid)));

	if (HeapTupleIsValid(tuple))
	{
		Datum attr;
		bool isNull;

		i = palloc(sizeof(CdbComponentDatabaseInfo));

		/*
		 * dbid
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_dbid,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->dbid = DatumGetInt16(attr);

		/*
		 * content
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_content,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->segindex = DatumGetInt16(attr);

		/*
		 * role
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_role,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->role = DatumGetChar(attr);

		/*
		 * preferred-role
		 */
		attr = heap_getattr(tuple,
							Anum_gp_segment_configuration_preferred_role,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->preferred_role = DatumGetChar(attr);

		/*
		 * mode
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_mode,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->mode = DatumGetChar(attr);

		/*
		 * status
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_status,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->status = DatumGetChar(attr);

		/*
		 * hostname
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->hostname = TextDatumGetCString(attr);

		/*
		 * address
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_address,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->address = TextDatumGetCString(attr);
		
		/*
		 * port
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->port = DatumGetInt32(attr);

		/*
		 * Filerep_port
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_replication_port,
							RelationGetDescr(rel), &isNull);
		if (!isNull)
			i->filerep_port = DatumGetInt32(attr);
		else
			i->filerep_port = -1;

		Assert(bOnly); /* should be only 1 */
	}
	else
	{
		elog(ERROR, "could not find configuration entry for dbid %i", dbid);
	}

	heap_close(rel, NoLock);

	return i;
}
Ejemplo n.º 21
0
/*
 * get dbinfo by registration_order
 */
CdbComponentDatabaseInfo *
registration_order_get_dbinfo(int32 order)
{
	HeapTuple tuple;
	Relation rel;
	bool bOnly;
	CdbComponentDatabaseInfo *i = NULL;
	cqContext	cqc;

	if (!AmActiveMaster() && !AmStandbyMaster())
		elog(ERROR, "registration_order_get_dbinfo() executed on execution segment");

	rel = heap_open(GpSegmentConfigRelationId, AccessShareLock);

	tuple = caql_getfirst_only(
			caql_addrel(cqclr(&cqc), rel),
			&bOnly,
			cql("SELECT * FROM gp_segment_configuration "
				" WHERE registration_order = :1 ",
				Int32GetDatum(order)));

	if (HeapTupleIsValid(tuple))
	{
		Datum attr;
		bool isNull;

		i = palloc(sizeof(CdbComponentDatabaseInfo));

		/*
		 * role
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_role,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->role = DatumGetChar(attr);

		/*
		 * status
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_status,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->status = DatumGetChar(attr);

		/*
		 * hostname
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->hostname = TextDatumGetCString(attr);

		/*
		 * address
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_address,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->address = TextDatumGetCString(attr);

		/*
		 * port
		 */
		attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
							RelationGetDescr(rel), &isNull);
		Assert(!isNull);
		i->port = DatumGetInt32(attr);

	}
	else
	{
		heap_close(rel, NoLock);
		elog(ERROR, "could not find configuration entry for registration_order %c",
				order);
	}

	heap_close(rel, NoLock);

	return i;
}
Ejemplo n.º 22
0
/* ----------------------------------------------------------------
 * caql_getcount()
 * Perform COUNT(*) or DELETE
 * ----------------------------------------------------------------
 */
int caql_getcount(cqContext *pCtx0, cq_list *pcql)
{
	const char*				 caql_str = pcql->caqlStr;
	const char*				 filenam  = pcql->filename;
	int						 lineno	  = pcql->lineno;
	struct caql_hash_cookie	*pchn	  = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext				*pCtx;
	cqContext				 cqc;
	HeapTuple				 tuple;
	Relation				 rel;
	int						 ii		  = 0;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", 
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */
	rel  = pCtx->cq_heap_rel;

	/* use the SysCache */
	if (pCtx->cq_usesyscache)
	{
		tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, 
									   pCtx->cq_NumKeys, 
									   pCtx->cq_cacheKeys);

		if (HeapTupleIsValid(tuple))
		{
			ii++;
			pCtx->cq_lasttup = tuple;
			if (pchn->bDelete)
				simple_heap_delete(rel, &tuple->t_self);

			ReleaseSysCache(tuple);
			/* only one */
		}
		caql_heapclose(pCtx);
		return (ii);
	}

	while (HeapTupleIsValid(tuple = systable_getnext(pCtx->cq_sysScan)))
	{
		if (HeapTupleIsValid(tuple) && pchn->bDelete)
		{
			pCtx->cq_lasttup = tuple;
			if (pchn->bDelete)
				simple_heap_delete(rel, &tuple->t_self);
		}

		ii++;
	}
	systable_endscan(pCtx->cq_sysScan); 
	caql_heapclose(pCtx);

	return (ii);
}
Ejemplo n.º 23
0
/* ----------------------------------------------------------------
 * caql_getfirst_only()
 * Return a copy the first tuple, pallocd in the current memory context,
 * and end the scan.  Clients should heap_freetuple() as necessary.
 * If pbOnly is not NULL, return TRUE if a second tuple is not found,
 * else return FALSE
 * NOTE: this function will return NULL if no tuples satisfy the
 * caql predicate -- use HeapTupleIsValid() to detect this condition.
 * ----------------------------------------------------------------
 */
HeapTuple caql_getfirst_only(cqContext *pCtx0, bool *pbOnly, cq_list *pcql)
{
	const char*				 caql_str = pcql->caqlStr;
	const char*				 filenam  = pcql->filename;
	int						 lineno	  = pcql->lineno;
	struct caql_hash_cookie	*pchn	  = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext				*pCtx;
	cqContext				 cqc;
	HeapTuple				 tuple, newTup = NULL;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", 
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */

	if (pbOnly) *pbOnly = true;

	/* use the SysCache */
	if (pCtx->cq_usesyscache)
	{
		tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, 
									   pCtx->cq_NumKeys, 
									   pCtx->cq_cacheKeys);

		if (HeapTupleIsValid(tuple))
		{
			newTup = heap_copytuple(tuple);
			ReleaseSysCache(tuple);
			/* only one */
		}
		caql_heapclose(pCtx);

		pCtx->cq_lasttup = newTup; /* need this for update/delete */

		return (newTup);
	}

	if (HeapTupleIsValid(tuple = systable_getnext(pCtx->cq_sysScan)))
	{
		/* always copy the tuple, because the endscan releases tup memory */
		newTup = heap_copytuple(tuple);
 
		if (pbOnly)
		{
			*pbOnly = 
				!(HeapTupleIsValid(systable_getnext(pCtx->cq_sysScan)));
		}
	}
	systable_endscan(pCtx->cq_sysScan); 
	caql_heapclose(pCtx);

	pCtx->cq_lasttup = newTup; /* need this for update/delete */
	return (newTup);
}
Ejemplo n.º 24
0
/* ----------------------------------------------------------------
 * caql_getoid_only()
 * Return the oid of the first tuple and end the scan
 * If pbOnly is not NULL, return TRUE if a second tuple is not found,
 * else return FALSE
 * ----------------------------------------------------------------
 */
Oid caql_getoid_only(cqContext *pCtx0, bool *pbOnly, cq_list *pcql)
{
	const char *caql_str = pcql->caqlStr;
	const char *filenam = pcql->filename;
	int			lineno = pcql->lineno;
	struct caql_hash_cookie	*pchn = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext  *pCtx;
	cqContext	cqc;
	HeapTuple	tuple;
	Oid			result = InvalidOid;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", 
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */

	if (pbOnly)
		*pbOnly = true;

	/* use the SysCache */
	if (pCtx->cq_usesyscache)
	{
		tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, 
									   pCtx->cq_NumKeys, 
									   pCtx->cq_cacheKeys);
		if (HeapTupleIsValid(tuple))
		{
			result = HeapTupleGetOid(tuple);
			ReleaseSysCache(tuple);
			/* only one */
		}
		caql_heapclose(pCtx);

		return (result);
	}

	if (HeapTupleIsValid(tuple = systable_getnext(pCtx->cq_sysScan)))
	{
		result = HeapTupleGetOid(tuple);

		if (pbOnly)
		{
			*pbOnly = 
				!(HeapTupleIsValid(tuple = 
								   systable_getnext(pCtx->cq_sysScan)));
		}
	}
	systable_endscan(pCtx->cq_sysScan); 
	caql_heapclose(pCtx);
	return (result);
}
Ejemplo n.º 25
0
/* ----------------------------------------------------------------
 * caql_getcstring_plus()
 * Return a cstring column from the first tuple and end the scan.
 * ----------------------------------------------------------------
 */
char *caql_getcstring_plus(cqContext *pCtx0, int *pFetchcount,
						   bool *pbIsNull, cq_list *pcql)
{
	const char *caql_str = pcql->caqlStr;
	const char *filenam = pcql->filename;
	int			lineno = pcql->lineno;
	struct caql_hash_cookie	*pchn = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext  *pCtx;
	cqContext   cqc;
	HeapTuple   tuple;
	char	   *result = NULL;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", 
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */

	if (pFetchcount)
		*pFetchcount = 0;
	if (pbIsNull)
		*pbIsNull = true;

	/* use the SysCache */
	if (pCtx->cq_usesyscache)
	{
		tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, 
									   pCtx->cq_NumKeys, 
									   pCtx->cq_cacheKeys);
	}
	else
	{
		tuple = systable_getnext(pCtx->cq_sysScan);
	}

	if (HeapTupleIsValid(tuple))
	{
		bool		isnull;
		Datum		d;

		if (pFetchcount)
			*pFetchcount = 1;

		d = caql_getattr_internal(pCtx, tuple, pchn->attnum, &isnull);

		if (!isnull)
		{
			switch (pchn->atttype)
			{
				case NAMEOID:
					result = DatumGetCString(DirectFunctionCall1(nameout, d));
					break;

				case TEXTOID:
					result = DatumGetCString(DirectFunctionCall1(textout, d));
					break;

				default:
					elog(ERROR, "column not a cstring: %s\nfile: %s, line %d", 
						 caql_str, filenam, lineno);
			}
		}
		if (pbIsNull)
			*pbIsNull = isnull;
	} /* end HeapTupleIsValid */

	if (pCtx->cq_usesyscache)
	{  
		if (HeapTupleIsValid(tuple))
			ReleaseSysCache(tuple);
	}
	else
	{	
		if (pFetchcount && HeapTupleIsValid(tuple))
		{				
			if (HeapTupleIsValid(systable_getnext(pCtx->cq_sysScan)))
			{
				*pFetchcount = 2;	
			}
		}
		systable_endscan(pCtx->cq_sysScan); 
	}		
	caql_heapclose(pCtx);

	return (result);
} /* end caql_getcstring_plus */
Ejemplo n.º 26
0
/* ----------------------------------------------------------------
 * caql_getoid_plus()
 * Return an oid column from the first tuple and end the scan.
 * Note: this works for regproc columns as well, but you should cast
 * the output as RegProcedure.
 * ----------------------------------------------------------------
 */
Oid caql_getoid_plus(cqContext *pCtx0, int *pFetchcount,
					 bool *pbIsNull, cq_list *pcql)
{
	const char *caql_str = pcql->caqlStr;
	const char *filenam = pcql->filename;
	int			lineno = pcql->lineno;
	struct caql_hash_cookie	*pchn = cq_lookup(caql_str, strlen(caql_str), pcql);
	cqContext  *pCtx;
	cqContext	cqc;
	HeapTuple	tuple;
	Oid			result = InvalidOid;

	if (NULL == pchn)
		elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", 
			 caql_str, filenam, lineno);

	Assert(!pchn->bInsert); /* INSERT not allowed */

	/* use the provided context, or provide a clean local ctx  */
	if (pCtx0)
		pCtx = pCtx0;
	else
		pCtx = cqclr(&cqc);

	pCtx = caql_switch(pchn, pCtx, pcql);
	/* NOTE: caql_switch frees the pcql */

	if (pFetchcount)
		*pFetchcount = 0;
	if (pbIsNull)
		*pbIsNull = true;

	/* use the SysCache */
	if (pCtx->cq_usesyscache)
	{
		tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, 
									   pCtx->cq_NumKeys, 
									   pCtx->cq_cacheKeys);
	}
	else
	{
		tuple = systable_getnext(pCtx->cq_sysScan);
	}

	if (HeapTupleIsValid(tuple))
	{
		if (pFetchcount)
			*pFetchcount = 1;
		
		/* if attnum not set, (InvalidAttrNumber == 0)
		 * use tuple oid, else extract oid from column 
		 * (includes ObjectIdAttributeNumber == -2) 
		 */
		if (pchn->attnum <= InvalidAttrNumber) 
		{
			if (pbIsNull)
				*pbIsNull = false;
			result = HeapTupleGetOid(tuple);
		}
		else /* find oid column */
		{
			bool		isnull;
			Datum		d = caql_getattr_internal(pCtx, tuple, pchn->attnum,
												  &isnull);

			if (!isnull)
			{
				switch (pchn->atttype)
				{
					case OIDOID:
					case REGPROCOID:
						result = DatumGetObjectId(d);
						break;

					default:
						elog(ERROR, "column not an oid: %s\nfile: %s, line %d", 
							 caql_str, filenam, lineno);
				}
			}
			if (pbIsNull)
				*pbIsNull = isnull;
		}
	} /* end HeapTupleIsValid */

	if (pCtx->cq_usesyscache)
	{  
		if (HeapTupleIsValid(tuple))
			ReleaseSysCache(tuple);
	}
	else
	{	
		if (pFetchcount && HeapTupleIsValid(tuple))
		{				
			if (HeapTupleIsValid(systable_getnext(pCtx->cq_sysScan)))
			{
				*pFetchcount = 2;	
			}
		}
		systable_endscan(pCtx->cq_sysScan); 
	}		
	caql_heapclose(pCtx);

	return (result);
} /* end caql_getoid_plus */
Ejemplo n.º 27
0
Archivo: queue.c Proyecto: AnLingm/gpdb
/* MPP-6923: */				  
static
List *
AlterResqueueCapabilityEntry(
								  List			*stmtOptIdList,
								  Oid			 queueid,
								  ListCell		*initcell,
								  bool			 bCreate)
{
	ListCell	*lc;
	List		*elems	   = NIL;
	List		*dropelems = NIL;
	List		*dupcheck  = NIL;
	HeapTuple	 tuple;
	cqContext	*pcqCtx;
	cqContext	 cqc;
	Relation	 rel	   = NULL;
	bool		 bWithout  = false;
	TupleDesc	 tupdesc   = NULL;

#ifdef USE_ASSERT_CHECKING
	{
		DefElem    *defel = (DefElem *) lfirst(initcell);
		Assert(0 == strcmp(defel->defname, "withliststart"));
	}
#endif

	initcell = lnext(initcell);

	/* walk the original list and build a list of valid entries */

	for_each_cell(lc, initcell)
	{
		DefElem *defel		= (DefElem *) lfirst(lc);
		Oid		 resTypeOid = InvalidOid;
		int		 resTypeInt = 0;
		List	*pentry		= NIL;
		Value	*pKeyVal	= NULL;
		Value	*pStrVal	= NULL;

		if (!bWithout && (strcmp(defel->defname, "withoutliststart") == 0))
		{
			bWithout = true;

			rel = heap_open(ResourceTypeRelationId, RowExclusiveLock);
			tupdesc = RelationGetDescr(rel);

			goto L_loop_cont;
		}

		/* ignore the basic threshold entries -- should already be processed */
		if (strcmp(defel->defname, "active_statements") == 0)
			goto L_loop_cont;
		if (strcmp(defel->defname, "max_cost") == 0)
			goto L_loop_cont;
		if (strcmp(defel->defname, "cost_overcommit") == 0)
			goto L_loop_cont;
		if (strcmp(defel->defname, "min_cost") == 0)
			goto L_loop_cont;

		if (!GetResourceTypeByName(defel->defname, &resTypeInt, &resTypeOid))
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("option \"%s\" is not a valid resource type",
							defel->defname)));

		pKeyVal = makeString(defel->defname);

		/* WITHOUT clause value determined in pg_resourcetype */
		if (!bWithout)
			pStrVal = makeString(defGetString(defel));
		else
		{
			pStrVal = NULL; /* if NULL, delete entry from
							 * pg_resqueuecapability 
							 */

			pcqCtx = caql_beginscan(
					caql_addrel(cqclr(&cqc), rel),
					cql("SELECT * FROM pg_resourcetype" 
						" WHERE restypid = :1 FOR UPDATE", 
						Int16GetDatum(resTypeInt)));
	
			while (HeapTupleIsValid(tuple = caql_getnext(pcqCtx)))
			{
				text	*shutoff_text	  = NULL;
				char	*shutoff_str	  = NULL;
				Datum	 shutoff_datum;
				bool	 isnull			  = false;
				Form_pg_resourcetype rtyp = 
						(Form_pg_resourcetype)GETSTRUCT(tuple);

				if (!rtyp->reshasdisable)
				{
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
							 errmsg("option \"%s\" cannot be disabled",
									defel->defname)));
				}

				/* required type must have a default value if it can
				 * be disabled 
				 */
				if (!rtyp->reshasdefault)
				{
					if (!rtyp->resrequired)
						/* optional resource without a default is
						 * turned off by removing entry from
						 * pg_resqueuecapability 
						 */
						break;
					else
					{
						/* XXX XXX */
						Assert(0);
						ereport(ERROR,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
								 errmsg("required option \"%s\" cannot be disabled",
										defel->defname)));
					}
				}

				/* get the shutoff string */
				shutoff_datum = 
						heap_getattr(tuple,
									 Anum_pg_resourcetype_resdisabledsetting,
									 tupdesc,
									 &isnull);
				Assert(!isnull);
				shutoff_text = DatumGetTextP(shutoff_datum);
				shutoff_str = 
						DatumGetCString(
								DirectFunctionCall1(
										textout,
										PointerGetDatum(shutoff_text)));

				pStrVal = makeString(shutoff_str);
					
				break;
			} /* end while heaptuple is valid */
			caql_endscan(pcqCtx);
		}

		/* check for duplicate key specifications */
		if (list_member(dupcheck, pKeyVal))
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("conflicting or redundant option for \"%s\"",
							defel->defname)));

		dupcheck = lappend(dupcheck, pKeyVal);

		pentry = list_make2(
							makeInteger(resTypeInt),
							pStrVal);

		/* list of lists - (resource type, resource setting) */
		if (bWithout)
		{
			/* if the "without" entry has an "off" value, then treat
			 * it as a regular "with" item and update it in
			 * pg_resqueuecapability, else remove its entry
			 */
			if (!pStrVal)
				dropelems = lappend(dropelems, pentry);
			else
				elems = lappend(elems, pentry);
		}
		else
			elems = lappend(elems, pentry);

	L_loop_cont:
		resTypeInt = 0; /* make compiler happy */
	}
Ejemplo n.º 28
0
/*
 * ExtProtocolCreateWithOid
 */
Oid
ExtProtocolCreateWithOid(const char		*protocolName,
					     List			*readfuncName,
					     List			*writefuncName,
					     List			*validatorfuncName,					   
					     Oid			 protOid,
					     bool			 trusted)
{
	Relation	rel;
	HeapTuple	tup;
	bool		nulls[Natts_pg_extprotocol];
	Datum		values[Natts_pg_extprotocol];
	Oid			readfn = InvalidOid;
	Oid			writefn = InvalidOid;
	Oid			validatorfn = InvalidOid;
	NameData	prtname;
	int			i;
	ObjectAddress myself,
				referenced;
	Oid 		ownerId = GetUserId();
	cqContext	cqc;
	cqContext	cqc2;
	cqContext  *pcqCtx;

	/* sanity checks (caller should have caught these) */
	if (!protocolName)
		elog(ERROR, "no protocol name supplied");

	if (!readfuncName && !writefuncName)
		elog(ERROR, "protocol must have at least one of readfunc or writefunc");

	/*
	 * Until we add system protocols to pg_extprotocol, make sure no
	 * protocols with the same name are created.
	 */
	if (strcasecmp(protocolName, "file") == 0 ||
		strcasecmp(protocolName, "http") == 0 ||
		strcasecmp(protocolName, "gpfdist") == 0 ||
		strcasecmp(protocolName, "gpfdists") == 0)
	{
		ereport(ERROR,
				(errcode(ERRCODE_RESERVED_NAME),
				 errmsg("protocol \"%s\" already exists",
						 protocolName),
				 errhint("pick a different protocol name")));
	}

	rel = heap_open(ExtprotocolRelationId, RowExclusiveLock);

	pcqCtx = caql_beginscan(
			caql_addrel(cqclr(&cqc), rel),
			cql("INSERT INTO pg_extprotocol",
				NULL));

	/* make sure there is no existing protocol of same name */
	if (caql_getcount(
				caql_addrel(cqclr(&cqc2), rel),
				cql("SELECT COUNT(*) FROM pg_extprotocol "
					" WHERE ptcname = :1 ",
					CStringGetDatum((char *) protocolName))))
	{
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("protocol \"%s\" already exists", 
						protocolName)));
	}

	/*
	 * function checks: if supplied, check existence and correct signature in the catalog
	 */
	
	if (readfuncName)
		readfn = ValidateProtocolFunction(readfuncName, EXTPTC_FUNC_READER);

	if (writefuncName)
		writefn = ValidateProtocolFunction(writefuncName, EXTPTC_FUNC_WRITER);				

	if (validatorfuncName)
		validatorfn = ValidateProtocolFunction(validatorfuncName, EXTPTC_FUNC_VALIDATOR);

	/*
	 * Everything looks okay.  Try to create the pg_extprotocol entry for the
	 * protocol.  (This could fail if there's already a conflicting entry.)
	 */

	/* initialize nulls and values */
	for (i = 0; i < Natts_pg_extprotocol; i++)
	{
		nulls[i] = false;
		values[i] = (Datum) 0;
	}
	namestrcpy(&prtname, protocolName);
	values[Anum_pg_extprotocol_ptcname - 1] = NameGetDatum(&prtname);
	values[Anum_pg_extprotocol_ptcreadfn - 1] = ObjectIdGetDatum(readfn);
	values[Anum_pg_extprotocol_ptcwritefn - 1] = ObjectIdGetDatum(writefn);
	values[Anum_pg_extprotocol_ptcvalidatorfn - 1] = ObjectIdGetDatum(validatorfn);
	values[Anum_pg_extprotocol_ptcowner - 1] = ObjectIdGetDatum(ownerId);
	values[Anum_pg_extprotocol_ptctrusted - 1] = BoolGetDatum(trusted);
	nulls[Anum_pg_extprotocol_ptcacl - 1] = true;

	tup = caql_form_tuple(pcqCtx, values, nulls);

	if (protOid != (Oid) 0)
		HeapTupleSetOid(tup, protOid);

	/* insert a new tuple */
	protOid = caql_insert(pcqCtx, tup); /* implicit update of index as well */

	caql_endscan(pcqCtx);
	heap_close(rel, RowExclusiveLock);

	/*
	 * Create dependencies for the protocol
	 */
	myself.classId = ExtprotocolRelationId;
	myself.objectId = protOid;
	myself.objectSubId = 0;

	/* Depends on read function, if any */
	if (OidIsValid(readfn))
	{
		referenced.classId = ProcedureRelationId;
		referenced.objectId = readfn;
		referenced.objectSubId = 0;
		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
	}

	/* Depends on write function, if any */
	if (OidIsValid(writefn))
	{
		referenced.classId = ProcedureRelationId;
		referenced.objectId = writefn;
		referenced.objectSubId = 0;
		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
	}

	/* dependency on owner */
	recordDependencyOnOwner(ExtprotocolRelationId, protOid, GetUserId());

	return protOid;
}
Ejemplo n.º 29
0
/*
 * Rename conversion
 */
void
RenameConversion(List *name, const char *newname)
{
	Oid			conversionOid;
	Oid			namespaceOid;
	HeapTuple	tup;
	Relation	rel;
	AclResult	aclresult;
	cqContext	cqc2;
	cqContext	cqc;
	cqContext  *pcqCtx;

	rel = heap_open(ConversionRelationId, RowExclusiveLock);

	conversionOid = FindConversionByName(name);
	if (!OidIsValid(conversionOid))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("conversion \"%s\" does not exist",
						NameListToString(name))));

	pcqCtx = caql_addrel(cqclr(&cqc), rel);

	tup = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_conversion "
				" WHERE oid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(conversionOid)));

	if (!HeapTupleIsValid(tup)) /* should not happen */
		elog(ERROR, "cache lookup failed for conversion %u", conversionOid);

	namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace;

	/* make sure the new name doesn't exist */
	if (caql_getcount(
				caql_addrel(cqclr(&cqc2), rel),
				cql("SELECT COUNT(*) FROM pg_conversion "
					" WHERE conname = :1 "
					" AND connamespace = :2 ",
					CStringGetDatum((char *) newname),
					ObjectIdGetDatum(namespaceOid))))
	{
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("conversion \"%s\" already exists in schema \"%s\"",
						newname, get_namespace_name(namespaceOid))));
	}

	/* must be owner */
	if (!pg_conversion_ownercheck(conversionOid, GetUserId()))
		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
					   NameListToString(name));

	/* must have CREATE privilege on namespace */
	aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
					   get_namespace_name(namespaceOid));

	/* rename */
	namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname);
	caql_update_current(pcqCtx, tup); /* implicit update of index as well */

	heap_close(rel, NoLock);
	heap_freetuple(tup);
}
Ejemplo n.º 30
0
/*
 * AlterConversionOwner_internal
 *
 * Internal routine for changing the owner.  rel must be pg_conversion, already
 * open and suitably locked; it will not be closed.
 */
static void
AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
{
	Form_pg_conversion convForm;
	HeapTuple	tup;
	cqContext	cqc;
	cqContext  *pcqCtx;

	Assert(RelationGetRelid(rel) == ConversionRelationId);

	pcqCtx = caql_addrel(cqclr(&cqc), rel);

	tup = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_conversion "
				" WHERE oid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(conversionOid)));

	if (!HeapTupleIsValid(tup)) /* should not happen */
		elog(ERROR, "cache lookup failed for conversion %u", conversionOid);

	convForm = (Form_pg_conversion) GETSTRUCT(tup);

	/*
	 * If the new owner is the same as the existing owner, consider the
	 * command to have succeeded.  This is for dump restoration purposes.
	 */
	if (convForm->conowner == newOwnerId)
	{
		heap_freetuple(tup);
		return;
	}

	AclResult	aclresult;

	/* Superusers can always do it */
	if (!superuser())
	{
		/* Otherwise, must be owner of the existing object */
		if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId()))
				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
							   NameStr(convForm->conname));

		/* Must be able to become new owner */
		check_is_member_of_role(GetUserId(), newOwnerId);

		/* New owner must have CREATE privilege on namespace */
		aclresult = pg_namespace_aclcheck(convForm->connamespace,
										  newOwnerId,
										  ACL_CREATE);
		if (aclresult != ACLCHECK_OK)
			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
						   get_namespace_name(convForm->connamespace));
	}

	/*
	 * Modify the owner --- okay to scribble on tup because it's a copy
	 */
	convForm->conowner = newOwnerId;

	caql_update_current(pcqCtx, tup); /* implicit update of index as well */

	/* Update owner dependency reference */
	changeDependencyOnOwner(ConversionRelationId, conversionOid,
								newOwnerId);

	heap_freetuple(tup);
}