1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Add the possibility to specify an explicit validator function for foreign-data

wrappers (similar to procedural languages).  This way we don't need to retain
the nearly empty libraries, and we are more free in how to implement the
wrapper API in the future.
This commit is contained in:
Peter Eisentraut
2009-02-24 10:06:36 +00:00
parent f73bed308a
commit 7babccb915
28 changed files with 452 additions and 626 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.5 2009/01/20 09:10:20 petere Exp $
* $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.6 2009/02/24 10:06:32 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,11 +20,13 @@
#include "catalog/indexing.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.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/lsyscache.h"
@ -90,10 +92,11 @@ transformGenericOptions(Datum oldOptions,
List *optionDefList,
GenericOptionFlags flags,
ForeignDataWrapper *fdw,
OptionListValidatorFunc validateOptionList)
Oid fdwvalidator)
{
List *resultOptions = untransformRelOptions(oldOptions);
ListCell *optcell;
Datum result;
foreach(optcell, optionDefList)
{
@ -157,10 +160,12 @@ transformGenericOptions(Datum oldOptions,
}
}
if (validateOptionList)
validateOptionList(fdw, flags, resultOptions);
result = optionListToArray(resultOptions);
return optionListToArray(resultOptions);
if (fdwvalidator)
OidFunctionCall2(fdwvalidator, result, 0);
return result;
}
@ -309,6 +314,21 @@ AlterForeignServerOwner(const char *name, Oid newOwnerId)
}
/*
* 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
*/
@ -320,9 +340,9 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
bool nulls[Natts_pg_foreign_data_wrapper];
HeapTuple tuple;
Oid fdwId;
Oid fdwvalidator;
Datum fdwoptions;
Oid ownerId;
ForeignDataWrapperLibrary *fdwlib;
/* Must be super user */
if (!superuser())
@ -355,18 +375,19 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
values[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = CStringGetTextDatum(stmt->library);
nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
/*
* See if the FDW library loads at all. We also might want to use it
* later for validating the options.
*/
fdwlib = GetForeignDataWrapperLibrary(stmt->library);
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,
FdwOpt, NULL,
fdwlib->validateOptionList);
fdwvalidator);
if (PointerIsValid(DatumGetPointer(fdwoptions)))
values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
@ -380,6 +401,21 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
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);
heap_close(rel, NoLock);
@ -400,7 +436,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
Oid fdwId;
bool isnull;
Datum datum;
ForeignDataWrapperLibrary *fdwlib;
Oid fdwvalidator;
/* Must be super user */
if (!superuser())
@ -425,36 +461,33 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
if (stmt->library)
if (stmt->change_validator)
{
/*
* New library specified -- load to see if valid.
*/
fdwlib = GetForeignDataWrapperLibrary(stmt->library);
repl_val[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = CStringGetTextDatum(stmt->library);
repl_repl[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = true;
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 library. Warn about this.
* are no longer valid with the new validator. Warn about this.
*/
ereport(WARNING,
(errmsg("changing the foreign-data wrapper library can cause "
"the options for dependent objects to become invalid")));
if (stmt->validator)
ereport(WARNING,
(errmsg("changing the foreign-data wrapper validator can cause "
"the options for dependent objects to become invalid")));
}
else
{
/*
* No LIBRARY clause specified, but we need to load it for validating
* Validator is not changed, but we need it for validating
* options.
*/
datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
tp,
Anum_pg_foreign_data_wrapper_fdwlibrary,
Anum_pg_foreign_data_wrapper_fdwvalidator,
&isnull);
Assert(!isnull);
fdwlib = GetForeignDataWrapperLibrary(TextDatumGetCString(datum));
fdwvalidator = DatumGetObjectId(datum);
}
/*
@ -472,7 +505,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
/* Transform the options */
datum = transformGenericOptions(datum, stmt->options, FdwOpt,
NULL, fdwlib->validateOptionList);
NULL, fdwvalidator);
if (PointerIsValid(DatumGetPointer(datum)))
repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
@ -640,7 +673,7 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
/* Add server options */
srvoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
ServerOpt, fdw,
fdw->lib->validateOptionList);
fdw->fdwvalidator);
if (PointerIsValid(DatumGetPointer(srvoptions)))
values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
@ -738,7 +771,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
/* Prepare the options array */
datum = transformGenericOptions(datum, stmt->options, ServerOpt,
fdw, fdw->lib->validateOptionList);
fdw, fdw->fdwvalidator);
if (PointerIsValid(DatumGetPointer(datum)))
repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
@ -910,7 +943,7 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
/* Add user options */
useoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
UserMappingOpt,
fdw, fdw->lib->validateOptionList);
fdw, fdw->fdwvalidator);
if (PointerIsValid(DatumGetPointer(useoptions)))
values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
@ -1005,7 +1038,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
/* Prepare the options array */
datum = transformGenericOptions(datum, stmt->options, UserMappingOpt,
fdw, fdw->lib->validateOptionList);
fdw, fdw->fdwvalidator);
if (PointerIsValid(DatumGetPointer(datum)))
repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;