/*-------------------------------------------------------------------------
 *
 * foreigncmds.c
 *	  foreign-data wrapper/server creation/manipulation commands
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *	  $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.8 2009/06/11 14:48:55 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/heapam.h"
#include "access/reloptions.h"
#include "catalog/catalog.h"
#include "catalog/catquery.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "cdb/cdbdisp.h"
#include "cdb/cdbvars.h"
#include "commands/defrem.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "access/genam.h"
#include "cdb/dispatcher.h"


/*
 * Convert a DefElem list to the text array format that is used in
 * pg_foreign_data_wrapper, pg_foreign_server, and pg_user_mapping.
 * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
 * if the list is empty.
 *
 * Note: The array is usually stored to database without further
 * processing, hence any validation should be done before this
 * conversion.
 */
static Datum
optionListToArray(List *options)
{
	ArrayBuildState *astate = NULL;
	ListCell   *cell;

	foreach(cell, options)
	{
		DefElem    *def = lfirst(cell);
		char *value;
		Size		len;
		text	   *t;

		bool need_free_value = false;
		value = defGetString(def, &need_free_value);
		len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
		t = palloc(len + 1);
		SET_VARSIZE(t, len);
		sprintf(VARDATA(t), "%s=%s", def->defname, value);
		if (need_free_value)
		{
			pfree(value);
			value = NULL;
		}

		AssertImply(need_free_value, NULL == value);

		astate = accumArrayResult(astate, PointerGetDatum(t),
								  false, TEXTOID,
								  CurrentMemoryContext);
	}

	if (astate)
		return makeArrayResult(astate, CurrentMemoryContext);

	return PointerGetDatum(NULL);
}


/*
 * Transform a list of DefElem into text array format.	This is substantially
 * the same thing as optionListToArray(), except we recognize SET/ADD/DROP
 * actions for modifying an existing list of options, which is passed in
 * Datum form as oldOptions.  Also, if fdwvalidator isn't InvalidOid
 * it specifies a validator function to call on the result.
 *
 * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
 * if the list is empty.
 *
 * This is used by CREATE/ALTER of FOREIGN DATA WRAPPER/SERVER/USER MAPPING.
 */
static Datum
transformGenericOptions(Datum oldOptions,
						List *options,
						Oid fdwvalidator)
{
	List	   *resultOptions = untransformRelOptions(oldOptions);
	ListCell   *optcell;
	Datum		result;

	foreach(optcell, options)
	{
		DefElem    *od = lfirst(optcell);
		ListCell   *cell;
		ListCell   *prev = NULL;

		/*
		 * Find the element in resultOptions.  We need this for validation in
		 * all cases.  Also identify the previous element.
		 */
		foreach(cell, resultOptions)
		{
			DefElem    *def = lfirst(cell);

			if (strcmp(def->defname, od->defname) == 0)
				break;
			else
				prev = cell;
		}

		/*
		 * It is possible to perform multiple SET/DROP actions on the same
		 * option.	The standard permits this, as long as the options to be
		 * added are unique.  Note that an unspecified action is taken to be
		 * ADD.
		 */
		switch (od->defaction)
		{
			case DEFELEM_DROP:
				if (!cell)
					ereport(ERROR,
							(errcode(ERRCODE_UNDEFINED_OBJECT),
							 errmsg("option \"%s\" not found",
									od->defname),
									errOmitLocation(true)));
				resultOptions = list_delete_cell(resultOptions, cell, prev);
				break;

			case DEFELEM_SET:
				if (!cell)
					ereport(ERROR,
							(errcode(ERRCODE_UNDEFINED_OBJECT),
							 errmsg("option \"%s\" not found",
									od->defname),
											errOmitLocation(true)));
				lfirst(cell) = od;
				break;

			case DEFELEM_ADD:
			case DEFELEM_UNSPEC:
				if (cell)
					ereport(ERROR,
							(errcode(ERRCODE_DUPLICATE_OBJECT),
							 errmsg("option \"%s\" provided more than once",
									od->defname),
											errOmitLocation(true)));
				resultOptions = lappend(resultOptions, od);
				break;

			default:
				elog(ERROR, "unrecognized action %d on option \"%s\"",
					 (int) od->defaction, od->defname);
				break;
		}
	}

	result = optionListToArray(resultOptions);

	if (fdwvalidator)
		OidFunctionCall2(fdwvalidator, result, (Datum) 0);

	return result;
}


/*
 * Convert the user mapping user name to OID
 */
static Oid
GetUserOidFromMapping(const char *username, bool missing_ok)
{
	if (!username)
		/* PUBLIC user mapping */
		return InvalidOid;

	if (strcmp(username, "current_user") == 0)
		/* map to the owner */
		return GetUserId();

	/* map to provided user */
	return missing_ok ? get_roleid(username) : get_roleid_checked(username);
}


/*
 * Change foreign-data wrapper owner.
 *
 * Allow this only for superusers; also the new owner must be a
 * superuser.
 */
void
AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
{
	HeapTuple	tup;
	Relation	rel;
	Oid			fdwId;
	Form_pg_foreign_data_wrapper form;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/* Must be a superuser to change a FDW owner */
	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
						name),
				 errhint("Must be superuser to change owner of a foreign-data wrapper."),
							errOmitLocation(true)));

	/* New owner must also be a superuser */
	if (!superuser_arg(newOwnerId))
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
						name),
		errhint("The owner of a foreign-data wrapper must be a superuser."),
				errOmitLocation(true)));

	rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);

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

	tup = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_foreign_data_wrapper "
				" WHERE fdwname = :1 "
				" FOR UPDATE ",
				CStringGetDatum(name)));

	if (!HeapTupleIsValid(tup))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("foreign-data wrapper \"%s\" does not exist", name),
							errOmitLocation(true)));

	fdwId = HeapTupleGetOid(tup);
	form = (Form_pg_foreign_data_wrapper) GETSTRUCT(tup);

	if (form->fdwowner != newOwnerId)
	{
		form->fdwowner = newOwnerId;

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

		/* Update owner dependency reference */
		changeDependencyOnOwner(ForeignDataWrapperRelationId,
								fdwId,
								newOwnerId);
	}

	heap_close(rel, NoLock);
	heap_freetuple(tup);
}


/*
 * Change foreign server owner
 */
void
AlterForeignServerOwner(const char *name, Oid newOwnerId)
{
	HeapTuple	tup;
	Relation	rel;
	Oid			srvId;
	AclResult	aclresult;
	Form_pg_foreign_server form;
	cqContext	cqc;
	cqContext  *pcqCtx;

	rel = heap_open(ForeignServerRelationId, RowExclusiveLock);

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

	tup = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_foreign_server "
				" WHERE srvname = :1 "
				" FOR UPDATE ",
				CStringGetDatum(name)));

	if (!HeapTupleIsValid(tup))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("server \"%s\" does not exist", name),
							errOmitLocation(true)));

	srvId = HeapTupleGetOid(tup);
	form = (Form_pg_foreign_server) GETSTRUCT(tup);

	if (form->srvowner != newOwnerId)
	{
		/* Superusers can always do it */
		if (!superuser())
		{
			/* Must be owner */
			if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
							   name);

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

			/* New owner must have USAGE privilege on foreign-data wrapper */
			aclresult = pg_foreign_data_wrapper_aclcheck(form->srvfdw, newOwnerId, ACL_USAGE);
			if (aclresult != ACLCHECK_OK)
			{
				ForeignDataWrapper *fdw = GetForeignDataWrapper(form->srvfdw);

				aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);
			}
		}

		form->srvowner = newOwnerId;

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

		/* Update owner dependency reference */
		changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
								newOwnerId);
	}

	heap_close(rel, NoLock);
	heap_freetuple(tup);
}


/*
 * Convert a validator function name passed from the parser to an Oid.
 */
static Oid
lookup_fdw_validator_func(List *validator)
{
	Oid			funcargtypes[2];

	funcargtypes[0] = TEXTARRAYOID;
	funcargtypes[1] = OIDOID;
	return LookupFuncName(validator, 2, funcargtypes, false);
	/* return value is ignored, so we don't check the type */
}


/*
 * Create a foreign-data wrapper
 */
void
CreateForeignDataWrapper(CreateFdwStmt *stmt)
{
	Relation	rel;
	Datum		values[Natts_pg_foreign_data_wrapper];
	bool		nulls[Natts_pg_foreign_data_wrapper];
	HeapTuple	tuple;
	Oid			fdwId;
	Oid			fdwvalidator;
	Datum		fdwoptions;
	Oid			ownerId;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/* Must be super user */
	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
			errmsg("permission denied to create foreign-data wrapper \"%s\"",
				   stmt->fdwname),
			errhint("Must be superuser to create a foreign-data wrapper."),
					errOmitLocation(true)));

	/* For now the owner cannot be specified on create. Use effective user ID. */
	ownerId = GetUserId();

	/*
	 * Check that there is no other foreign-data wrapper by this name.
	 */
	if (GetForeignDataWrapperByName(stmt->fdwname, true) != NULL)
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("foreign-data wrapper \"%s\" already exists",
						stmt->fdwname),
								errOmitLocation(true)));

	/*
	 * Insert tuple into pg_foreign_data_wrapper.
	 */
	rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);

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

	memset(values, 0, sizeof(values));
	memset(nulls, false, sizeof(nulls));

	values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
		DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
	values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);

	if (stmt->validator)
		fdwvalidator = lookup_fdw_validator_func(stmt->validator);
	else
		fdwvalidator = InvalidOid;

	values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator;

	nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;

	fdwoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
										 fdwvalidator);

	if (PointerIsValid(DatumGetPointer(fdwoptions)))
		values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
	else
		nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;

	tuple = caql_form_tuple(pcqCtx, values, nulls);

	fdwId = caql_insert(pcqCtx, tuple); /* implicit update of index as well */

	heap_freetuple(tuple);

	if (fdwvalidator)
	{
		ObjectAddress myself;
		ObjectAddress referenced;

		myself.classId = ForeignDataWrapperRelationId;
		myself.objectId = fdwId;
		myself.objectSubId = 0;

		referenced.classId = ProcedureRelationId;
		referenced.objectId = fdwvalidator;
		referenced.objectSubId = 0;
		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
	}

	recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);

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

	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);
}


/*
 * Alter foreign-data wrapper
 */
void
AlterForeignDataWrapper(AlterFdwStmt *stmt)
{
	Relation	rel;
	HeapTuple	tp;
	Datum		repl_val[Natts_pg_foreign_data_wrapper];
	bool		repl_null[Natts_pg_foreign_data_wrapper];
	bool		repl_repl[Natts_pg_foreign_data_wrapper];
	Oid			fdwId;
	bool		isnull;
	Datum		datum;
	Oid			fdwvalidator;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/* Must be super user */
	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
			 errmsg("permission denied to alter foreign-data wrapper \"%s\"",
					stmt->fdwname),
			 errhint("Must be superuser to alter a foreign-data wrapper."),
						errOmitLocation(true)));

	rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);

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

	tp = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_foreign_data_wrapper "
				" WHERE fdwname = :1 "
				" FOR UPDATE ",
				CStringGetDatum(stmt->fdwname)));

	if (!HeapTupleIsValid(tp))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
		errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname),
				errOmitLocation(true)));

	fdwId = HeapTupleGetOid(tp);

	memset(repl_val, 0, sizeof(repl_val));
	memset(repl_null, false, sizeof(repl_null));
	memset(repl_repl, false, sizeof(repl_repl));

	if (stmt->change_validator)
	{
		fdwvalidator = stmt->validator ? lookup_fdw_validator_func(stmt->validator) : InvalidOid;
		repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
		repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;

		/*
		 * It could be that the options for the FDW, SERVER and USER MAPPING
		 * are no longer valid with the new validator.	Warn about this.
		 */
		if (stmt->validator)
			ereport(WARNING,
			 (errmsg("changing the foreign-data wrapper validator can cause "
					 "the options for dependent objects to become invalid"),
								errOmitLocation(true)));
	}
	else
	{
		/*
		 * Validator is not changed, but we need it for validating options.
		 */
		datum = caql_getattr(pcqCtx,
							 Anum_pg_foreign_data_wrapper_fdwvalidator,
							 &isnull);
		Assert(!isnull);
		fdwvalidator = DatumGetObjectId(datum);
	}

	/*
	 * Options specified, validate and update.
	 */
	if (stmt->options)
	{
		/* Extract the current options */
		datum = caql_getattr(pcqCtx,
							 Anum_pg_foreign_data_wrapper_fdwoptions,
							 &isnull);
		if (isnull)
			datum = PointerGetDatum(NULL);

		/* Transform the options */
		datum = transformGenericOptions(datum, stmt->options, fdwvalidator);

		if (PointerIsValid(DatumGetPointer(datum)))
			repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
		else
			repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;

		repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
	}

	/* Everything looks good - update the tuple */

	tp = caql_modify_current(pcqCtx,
							 repl_val, repl_null, repl_repl);

	caql_update_current(pcqCtx, tp);
	/* and Update indexes (implicit) */

	heap_close(rel, RowExclusiveLock);
	heap_freetuple(tp);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Drop foreign-data wrapper
 */
void
RemoveForeignDataWrapper(DropFdwStmt *stmt)
{
	Oid			fdwId;
	ObjectAddress object;

	fdwId = GetForeignDataWrapperOidByName(stmt->fdwname, true);

	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
			  errmsg("permission denied to drop foreign-data wrapper \"%s\"",
					 stmt->fdwname),
			  errhint("Must be superuser to drop a foreign-data wrapper."),
						errOmitLocation(true)));

	if (!OidIsValid(fdwId))
	{
		if (!stmt->missing_ok)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("foreign-data wrapper \"%s\" does not exist",
							stmt->fdwname),
									errOmitLocation(true)));

		/* IF EXISTS specified, just note it */
		ereport(NOTICE,
			  (errmsg("foreign-data wrapper \"%s\" does not exist, skipping",
					  stmt->fdwname),
								errOmitLocation(true)));
		return;
	}

	/*
	 * Do the deletion
	 */
	object.classId = ForeignDataWrapperRelationId;
	object.objectId = fdwId;
	object.objectSubId = 0;

	performDeletion(&object, stmt->behavior);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Drop foreign-data wrapper by OID
 */
void
RemoveForeignDataWrapperById(Oid fdwId)
{
	if (0 == caql_getcount(
				NULL,
				cql("DELETE FROM pg_foreign_data_wrapper "
					" WHERE oid = :1 ",
					ObjectIdGetDatum(fdwId))))
	{
		elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwId);
	}
}


/*
 * Create a foreign server
 */
void
CreateForeignServer(CreateForeignServerStmt *stmt)
{
	Relation	rel;
	Datum		srvoptions;
	Datum		values[Natts_pg_foreign_server];
	bool		nulls[Natts_pg_foreign_server];
	HeapTuple	tuple;
	Oid			srvId;
	Oid			ownerId;
	AclResult	aclresult;
	ObjectAddress myself;
	ObjectAddress referenced;
	ForeignDataWrapper *fdw;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/* For now the owner cannot be specified on create. Use effective user ID. */
	ownerId = GetUserId();

	/*
	 * Check that there is no other foreign server by this name.
	 */
	if (GetForeignServerByName(stmt->servername, true) != NULL)
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("server \"%s\" already exists",
						stmt->servername),
								errOmitLocation(true)));

	/*
	 * Check that the FDW exists and that we have USAGE on it. Also get the
	 * actual FDW for option validation etc.
	 */
	fdw = GetForeignDataWrapperByName(stmt->fdwname, false);

	aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, ACL_USAGE);
	if (aclresult != ACLCHECK_OK)
		aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);

	/*
	 * Insert tuple into pg_foreign_server.
	 */
	rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
	pcqCtx = caql_beginscan(
			caql_addrel(cqclr(&cqc), rel),
			cql("INSERT INTO pg_foreign_server", 
				NULL));

	memset(values, 0, sizeof(values));
	memset(nulls, false, sizeof(nulls));

	values[Anum_pg_foreign_server_srvname - 1] =
		DirectFunctionCall1(namein, CStringGetDatum(stmt->servername));
	values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
	values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid);

	/* Add server type if supplied */
	if (stmt->servertype)
		values[Anum_pg_foreign_server_srvtype - 1] =
			CStringGetTextDatum(stmt->servertype);
	else
		nulls[Anum_pg_foreign_server_srvtype - 1] = true;

	/* Add server version if supplied */
	if (stmt->version)
		values[Anum_pg_foreign_server_srvversion - 1] =
			CStringGetTextDatum(stmt->version);
	else
		nulls[Anum_pg_foreign_server_srvversion - 1] = true;

	/* Start with a blank acl */
	nulls[Anum_pg_foreign_server_srvacl - 1] = true;

	/* Add server options */
	srvoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
										 fdw->fdwvalidator);

	if (PointerIsValid(DatumGetPointer(srvoptions)))
		values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
	else
		nulls[Anum_pg_foreign_server_srvoptions - 1] = true;

	tuple = caql_form_tuple(pcqCtx, values, nulls);

	srvId = caql_insert(pcqCtx, tuple); /* implicit update of index as well */

	heap_freetuple(tuple);

	/* Add dependency on FDW and owner */
	myself.classId = ForeignServerRelationId;
	myself.objectId = srvId;
	myself.objectSubId = 0;

	referenced.classId = ForeignDataWrapperRelationId;
	referenced.objectId = fdw->fdwid;
	referenced.objectSubId = 0;
	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);

	recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);

	caql_endscan(pcqCtx);
	heap_close(rel, NoLock);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Alter foreign server
 */
void
AlterForeignServer(AlterForeignServerStmt *stmt)
{
	Relation	rel;
	HeapTuple	tp;
	Datum		repl_val[Natts_pg_foreign_server];
	bool		repl_null[Natts_pg_foreign_server];
	bool		repl_repl[Natts_pg_foreign_server];
	Oid			srvId;
	Form_pg_foreign_server srvForm;
	cqContext	cqc;
	cqContext  *pcqCtx;

	rel = heap_open(ForeignServerRelationId, RowExclusiveLock);

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

	tp = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_foreign_server "
				" WHERE srvname = :1 "
				" FOR UPDATE ",
				CStringGetDatum(stmt->servername)));

	if (!HeapTupleIsValid(tp))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("server \"%s\" does not exist", stmt->servername),
							errOmitLocation(true)));

	srvId = HeapTupleGetOid(tp);
	srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);

	/*
	 * Only owner or a superuser can ALTER a SERVER.
	 */
	if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
					   stmt->servername);

	memset(repl_val, 0, sizeof(repl_val));
	memset(repl_null, false, sizeof(repl_null));
	memset(repl_repl, false, sizeof(repl_repl));

	if (stmt->has_version)
	{
		/*
		 * Change the server VERSION string.
		 */
		if (stmt->version)
			repl_val[Anum_pg_foreign_server_srvversion - 1] =
				CStringGetTextDatum(stmt->version);
		else
			repl_null[Anum_pg_foreign_server_srvversion - 1] = true;

		repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
	}

	if (stmt->options)
	{
		ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
		Datum		datum;
		bool		isnull;

		/* Extract the current srvoptions */
		datum = caql_getattr(pcqCtx,
							 Anum_pg_foreign_server_srvoptions,
							 &isnull);
		if (isnull)
			datum = PointerGetDatum(NULL);

		/* Prepare the options array */
		datum = transformGenericOptions(datum, stmt->options,
										fdw->fdwvalidator);

		if (PointerIsValid(DatumGetPointer(datum)))
			repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
		else
			repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;

		repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
	}

	/* Everything looks good - update the tuple */

	tp = caql_modify_current(pcqCtx,
							 repl_val, repl_null, repl_repl);

	caql_update_current(pcqCtx, tp);
	/* and Update indexes (implicit) */

	heap_close(rel, RowExclusiveLock);
	heap_freetuple(tp);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Drop foreign server
 */
void
RemoveForeignServer(DropForeignServerStmt *stmt)
{
	Oid			srvId;
	ObjectAddress object;

	srvId = GetForeignServerOidByName(stmt->servername, true);

	if (!OidIsValid(srvId))
	{
		/* Server not found, complain or notice */
		if (!stmt->missing_ok)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
				  errmsg("server \"%s\" does not exist", stmt->servername),
							errOmitLocation(true)));

		/* IF EXISTS specified, just note it */
		ereport(NOTICE,
				(errmsg("server \"%s\" does not exist, skipping",
						stmt->servername),
								errOmitLocation(true)));
		return;
	}

	/* Only allow DROP if the server is owned by the user. */
	if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
					   stmt->servername);

	object.classId = ForeignServerRelationId;
	object.objectId = srvId;
	object.objectSubId = 0;

	performDeletion(&object, stmt->behavior);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Drop foreign server by OID
 */
void
RemoveForeignServerById(Oid srvId)
{
	if (0 == caql_getcount(
				NULL,
				cql("DELETE FROM pg_foreign_server "
					" WHERE oid = :1 ",
					ObjectIdGetDatum(srvId))))
	{
		elog(ERROR, "cache lookup failed for foreign server %u", srvId);
	}
}

/*
 * Common routine to check permission for user-mapping-related DDL
 * commands.  We allow server owners to operate on any mapping, and
 * users to operate on their own mapping.
 */
static void
user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
{
	Oid			curuserid = GetUserId();

	if (!pg_foreign_server_ownercheck(serverid, curuserid))
	{
		if (umuserid == curuserid)
		{
			AclResult	aclresult;

			aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE);
			if (aclresult != ACLCHECK_OK)
				aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, servername);
		}
		else
			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
						   servername);
	}
}


/*
 * Create user mapping
 */
void
CreateUserMapping(CreateUserMappingStmt *stmt)
{
	Relation	rel;
	Datum		useoptions;
	Datum		values[Natts_pg_user_mapping];
	bool		nulls[Natts_pg_user_mapping];
	HeapTuple	tuple;
	Oid			useId;
	Oid			umId;
	ObjectAddress myself;
	ObjectAddress referenced;
	ForeignServer *srv;
	ForeignDataWrapper *fdw;
	cqContext	cqc;
	cqContext	cqc2;
	cqContext  *pcqCtx;


	useId = GetUserOidFromMapping(stmt->username, false);

	/* Check that the server exists. */
	srv = GetForeignServerByName(stmt->servername, false);

	user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);

	rel = heap_open(UserMappingRelationId, RowExclusiveLock);

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

	/*
	 * Check that the user mapping is unique within server.
	 */
	umId = caql_getoid(
			caql_addrel(cqclr(&cqc2), rel),
			cql("SELECT oid FROM pg_user_mapping "
				" WHERE umuser = :1 "
				" AND umserver = :2 ",
				ObjectIdGetDatum(useId),
				ObjectIdGetDatum(srv->serverid)));

	if (OidIsValid(umId))
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("user mapping \"%s\" already exists for server %s",
						MappingUserName(useId),
						stmt->servername),
								errOmitLocation(true)));

	fdw = GetForeignDataWrapper(srv->fdwid);

	/*
	 * Insert tuple into pg_user_mapping.
	 */

	memset(values, 0, sizeof(values));
	memset(nulls, false, sizeof(nulls));

	values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
	values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);

	/* Add user options */
	useoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
										 fdw->fdwvalidator);

	if (PointerIsValid(DatumGetPointer(useoptions)))
		values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
	else
		nulls[Anum_pg_user_mapping_umoptions - 1] = true;
	
	tuple = caql_form_tuple(pcqCtx, values, nulls);

	umId = caql_insert(pcqCtx, tuple); /* implicit update of index as well */

	heap_freetuple(tuple);

	/* Add dependency on the server */
	myself.classId = UserMappingRelationId;
	myself.objectId = umId;
	myself.objectSubId = 0;

	referenced.classId = ForeignServerRelationId;
	referenced.objectId = srv->serverid;
	referenced.objectSubId = 0;
	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);

	if (OidIsValid(useId))
		/* Record the mapped user dependency */
		recordDependencyOnOwner(UserMappingRelationId, umId, useId);

	caql_endscan(pcqCtx);
	heap_close(rel, NoLock);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);
}


/*
 * Alter user mapping
 */
void
AlterUserMapping(AlterUserMappingStmt *stmt)
{
	Relation	rel;
	HeapTuple	tp;
	Datum		repl_val[Natts_pg_user_mapping];
	bool		repl_null[Natts_pg_user_mapping];
	bool		repl_repl[Natts_pg_user_mapping];
	Oid			useId;
	Oid			umId;
	ForeignServer *srv;
	cqContext	cqc;
	cqContext  *pcqCtx;

	useId = GetUserOidFromMapping(stmt->username, false);
	srv = GetForeignServerByName(stmt->servername, false);

	umId = caql_getoid(
			NULL,
			cql("SELECT oid FROM pg_user_mapping "
				" WHERE umuser = :1 "
				" AND umserver = :2 ",
				ObjectIdGetDatum(useId),
				ObjectIdGetDatum(srv->serverid)));

	if (!OidIsValid(umId))
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("user mapping \"%s\" does not exist for the server",
						MappingUserName(useId)),
								errOmitLocation(true)));

	user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);

	rel = heap_open(UserMappingRelationId, RowExclusiveLock);

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

	tp = caql_getfirst(
			pcqCtx,
			cql("SELECT * FROM pg_user_mapping "
				" WHERE oid = :1 "
				" FOR UPDATE ",
				ObjectIdGetDatum(umId)));

	if (!HeapTupleIsValid(tp))
		elog(ERROR, "cache lookup failed for user mapping %u", umId);

	memset(repl_val, 0, sizeof(repl_val));
	memset(repl_null, false, sizeof(repl_null));
	memset(repl_repl, false, sizeof(repl_repl));

	if (stmt->options)
	{
		ForeignDataWrapper *fdw;
		Datum		datum;
		bool		isnull;

		/*
		 * Process the options.
		 */

		fdw = GetForeignDataWrapper(srv->fdwid);

		datum = caql_getattr(pcqCtx,
							 Anum_pg_user_mapping_umoptions,
							 &isnull);
		if (isnull)
			datum = PointerGetDatum(NULL);

		/* Prepare the options array */
		datum = transformGenericOptions(datum, stmt->options,
										fdw->fdwvalidator);

		if (PointerIsValid(DatumGetPointer(datum)))
			repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
		else
			repl_null[Anum_pg_user_mapping_umoptions - 1] = true;

		repl_repl[Anum_pg_user_mapping_umoptions - 1] = true;
	}

	/* Everything looks good - update the tuple */

	tp = caql_modify_current(pcqCtx,
							 repl_val, repl_null, repl_repl);

	caql_update_current(pcqCtx, tp);
	/* and Update indexes (implicit) */

	heap_close(rel, RowExclusiveLock);
	heap_freetuple(tp);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);

}


/*
 * Drop user mapping
 */
void
RemoveUserMapping(DropUserMappingStmt *stmt)
{
	ObjectAddress object;
	Oid			useId;
	Oid			umId;
	ForeignServer *srv;

	useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok);
	srv = GetForeignServerByName(stmt->servername, true);

	if (stmt->username && !OidIsValid(useId))
	{
		/*
		 * IF EXISTS specified, role not found and not public. Notice this and
		 * leave.
		 */
		elog(NOTICE, "role \"%s\" does not exist, skipping", stmt->username);
		return;
	}

	if (!srv)
	{
		if (!stmt->missing_ok)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("server \"%s\" does not exist",
							stmt->servername),
									errOmitLocation(true)));
		/* IF EXISTS, just note it */
		ereport(NOTICE, (errmsg("server does not exist, skipping"),
				errOmitLocation(true)));
		return;
	}

	umId = caql_getoid(
			NULL,
			cql("SELECT oid FROM pg_user_mapping "
				" WHERE umuser = :1 "
				" AND umserver = :2 ",
				ObjectIdGetDatum(useId),
				ObjectIdGetDatum(srv->serverid)));

	if (!OidIsValid(umId))
	{
		if (!stmt->missing_ok)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
				  errmsg("user mapping \"%s\" does not exist for the server",
						 MappingUserName(useId)),
									errOmitLocation(true)));

		/* IF EXISTS specified, just note it */
		ereport(NOTICE,
		(errmsg("user mapping \"%s\" does not exist for the server, skipping",
				MappingUserName(useId))));
		return;
	}

	user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername);

	/*
	 * Do the deletion
	 */
	object.classId = UserMappingRelationId;
	object.objectId = umId;
	object.objectSubId = 0;

	performDeletion(&object, DROP_CASCADE);
	
	/* dispatch to QEs */
	if (Gp_role == GP_ROLE_DISPATCH)
		dispatch_statement_node((Node *) stmt, NULL, NULL, NULL);
}


/*
 * Drop user mapping by OID.  This is called to clean up dependencies.
 */
void
RemoveUserMappingById(Oid umId)
{
	if (0 == caql_getcount(
				NULL,
				cql("DELETE FROM pg_user_mapping "
					" WHERE oid = :1 ",
					ObjectIdGetDatum(umId))))
	{
		elog(ERROR, "cache lookup failed for user mapping %u", umId);
	}
}

/*******************************************************************
 * FOREIGN TABLE catalog manipulation
 * 
 * The foreign table API below is slightly different from the above
 * API. FDW, SERVER, and MAPPING are objects by themselves, and
 * creating/dropping/altering them is done directly on their
 * respective catalog tables. FOREIGN TABLE, however, is different
 * because the object is stored in pg_class and only the foreign
 * specifics are stored in pg_foreign_table (much like the design of
 * pg_exttable and pg_appendonly). So, instead of dealing with the
 * statement as a whole, we leave it to tablecmds.c, which here we
 * take care of physically inserting/altering/removing entries from
 * pg_foreign_table upon request.
 *******************************************************************/

void
InsertForeignTableEntry(Oid relid, char	*servername, List *options)
{
	Relation	rel;
	Datum		tbloptions;
	Datum		values[Natts_pg_foreign_table];
	bool		nulls[Natts_pg_foreign_table];
	HeapTuple	tuple;
	Oid			srvId;
	Oid			ownerId;
	AclResult	aclresult;
	ForeignServer *srv;
	ForeignDataWrapper *fdw;
	cqContext	cqc;
	cqContext  *pcqCtx;

	/* For now the owner cannot be specified on create. Use effective user ID. */
	ownerId = GetUserId();

	/* Check that the server exists. */
	srv = GetForeignServerByName(servername, false);

	/* Check we have at least USAGE permissions */
	if (!pg_foreign_server_ownercheck(srv->serverid, ownerId))
	{
		aclresult = pg_foreign_server_aclcheck(srv->serverid, ownerId, ACL_USAGE);
		if (aclresult != ACLCHECK_OK)
			aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, servername);
	}

	fdw = GetForeignDataWrapper(srv->fdwid);
	
	/*
	 * Insert tuple into pg_foreign_table.
	 */
	rel = heap_open(ForeignTableRelationId, RowExclusiveLock);
	pcqCtx = caql_beginscan(
			caql_addrel(cqclr(&cqc), rel),
			cql("INSERT INTO pg_foreign_table", 
				NULL));

	memset(values, 0, sizeof(values));
	memset(nulls, false, sizeof(nulls));

	values[Anum_pg_foreign_table_reloid - 1] = ObjectIdGetDatum(relid);
	values[Anum_pg_foreign_table_server - 1] = ObjectIdGetDatum(srv->serverid);

	/* Add server options */
	tbloptions = transformGenericOptions(PointerGetDatum(NULL), 
										 options,
										 fdw->fdwvalidator);

	if (PointerIsValid(DatumGetPointer(tbloptions)))
		values[Anum_pg_foreign_table_tbloptions - 1] = tbloptions;
	else
		nulls[Anum_pg_foreign_table_tbloptions - 1] = true;

	tuple = caql_form_tuple(pcqCtx, values, nulls);

	srvId = caql_insert(pcqCtx, tuple); /* implicit update of index as well */
	(void) srvId;  /* never used */

	heap_freetuple(tuple);

	caql_endscan(pcqCtx);
	heap_close(rel, NoLock);
}

/*
 * Drop pg_foreign_table entry by OID.  This is called to clean up dependencies.
 */
void
RemoveForeignTableEntry(Oid relid)
{
	Relation	pg_foreigntable_rel;
	int			numDel;
	cqContext	cqc;

	/*
	 * now remove the pg_foreign_table entry
	 */
	pg_foreigntable_rel = heap_open(ForeignTableRelationId, RowExclusiveLock);

	numDel = caql_getcount(
			caql_addrel(cqclr(&cqc), pg_foreigntable_rel),
			cql("DELETE FROM pg_foreign_table "
				" WHERE reloid = :1 ",
				ObjectIdGetDatum(relid)));

	if (!numDel)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("foreign table object id \"%d\" does not exist",
						relid)));

	heap_close(pg_foreigntable_rel, NoLock);
}

