00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include "access/heapam.h"
00017 #include "access/htup_details.h"
00018 #include "access/xact.h"
00019 #include "access/reloptions.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_foreign_data_wrapper.h"
00024 #include "catalog/pg_foreign_server.h"
00025 #include "catalog/pg_foreign_table.h"
00026 #include "catalog/pg_proc.h"
00027 #include "catalog/pg_type.h"
00028 #include "catalog/pg_user_mapping.h"
00029 #include "commands/defrem.h"
00030 #include "foreign/foreign.h"
00031 #include "miscadmin.h"
00032 #include "parser/parse_func.h"
00033 #include "utils/acl.h"
00034 #include "utils/builtins.h"
00035 #include "utils/lsyscache.h"
00036 #include "utils/rel.h"
00037 #include "utils/syscache.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static Datum
00051 optionListToArray(List *options)
00052 {
00053 ArrayBuildState *astate = NULL;
00054 ListCell *cell;
00055
00056 foreach(cell, options)
00057 {
00058 DefElem *def = lfirst(cell);
00059 const char *value;
00060 Size len;
00061 text *t;
00062
00063 value = defGetString(def);
00064 len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
00065 t = palloc(len + 1);
00066 SET_VARSIZE(t, len);
00067 sprintf(VARDATA(t), "%s=%s", def->defname, value);
00068
00069 astate = accumArrayResult(astate, PointerGetDatum(t),
00070 false, TEXTOID,
00071 CurrentMemoryContext);
00072 }
00073
00074 if (astate)
00075 return makeArrayResult(astate, CurrentMemoryContext);
00076
00077 return PointerGetDatum(NULL);
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 Datum
00094 transformGenericOptions(Oid catalogId,
00095 Datum oldOptions,
00096 List *options,
00097 Oid fdwvalidator)
00098 {
00099 List *resultOptions = untransformRelOptions(oldOptions);
00100 ListCell *optcell;
00101 Datum result;
00102
00103 foreach(optcell, options)
00104 {
00105 DefElem *od = lfirst(optcell);
00106 ListCell *cell;
00107 ListCell *prev = NULL;
00108
00109
00110
00111
00112
00113 foreach(cell, resultOptions)
00114 {
00115 DefElem *def = lfirst(cell);
00116
00117 if (strcmp(def->defname, od->defname) == 0)
00118 break;
00119 else
00120 prev = cell;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 switch (od->defaction)
00130 {
00131 case DEFELEM_DROP:
00132 if (!cell)
00133 ereport(ERROR,
00134 (errcode(ERRCODE_UNDEFINED_OBJECT),
00135 errmsg("option \"%s\" not found",
00136 od->defname)));
00137 resultOptions = list_delete_cell(resultOptions, cell, prev);
00138 break;
00139
00140 case DEFELEM_SET:
00141 if (!cell)
00142 ereport(ERROR,
00143 (errcode(ERRCODE_UNDEFINED_OBJECT),
00144 errmsg("option \"%s\" not found",
00145 od->defname)));
00146 lfirst(cell) = od;
00147 break;
00148
00149 case DEFELEM_ADD:
00150 case DEFELEM_UNSPEC:
00151 if (cell)
00152 ereport(ERROR,
00153 (errcode(ERRCODE_DUPLICATE_OBJECT),
00154 errmsg("option \"%s\" provided more than once",
00155 od->defname)));
00156 resultOptions = lappend(resultOptions, od);
00157 break;
00158
00159 default:
00160 elog(ERROR, "unrecognized action %d on option \"%s\"",
00161 (int) od->defaction, od->defname);
00162 break;
00163 }
00164 }
00165
00166 result = optionListToArray(resultOptions);
00167
00168 if (OidIsValid(fdwvalidator))
00169 {
00170 Datum valarg = result;
00171
00172
00173
00174
00175
00176 if (DatumGetPointer(valarg) == NULL)
00177 valarg = PointerGetDatum(construct_empty_array(TEXTOID));
00178 OidFunctionCall2(fdwvalidator, valarg, ObjectIdGetDatum(catalogId));
00179 }
00180
00181 return result;
00182 }
00183
00184
00185
00186
00187
00188 static Oid
00189 GetUserOidFromMapping(const char *username, bool missing_ok)
00190 {
00191 if (!username)
00192
00193 return InvalidOid;
00194
00195 if (strcmp(username, "current_user") == 0)
00196
00197 return GetUserId();
00198
00199
00200 return get_role_oid(username, missing_ok);
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 static void
00210 AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
00211 {
00212 Form_pg_foreign_data_wrapper form;
00213
00214 form = (Form_pg_foreign_data_wrapper) GETSTRUCT(tup);
00215
00216
00217 if (!superuser())
00218 ereport(ERROR,
00219 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00220 errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
00221 NameStr(form->fdwname)),
00222 errhint("Must be superuser to change owner of a foreign-data wrapper.")));
00223
00224
00225 if (!superuser_arg(newOwnerId))
00226 ereport(ERROR,
00227 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00228 errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
00229 NameStr(form->fdwname)),
00230 errhint("The owner of a foreign-data wrapper must be a superuser.")));
00231
00232 if (form->fdwowner != newOwnerId)
00233 {
00234 form->fdwowner = newOwnerId;
00235
00236 simple_heap_update(rel, &tup->t_self, tup);
00237 CatalogUpdateIndexes(rel, tup);
00238
00239
00240 changeDependencyOnOwner(ForeignDataWrapperRelationId,
00241 HeapTupleGetOid(tup),
00242 newOwnerId);
00243 }
00244
00245 InvokeObjectPostAlterHook(ForeignDataWrapperRelationId,
00246 HeapTupleGetOid(tup), 0);
00247 }
00248
00249
00250
00251
00252
00253
00254 Oid
00255 AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
00256 {
00257 Oid fdwId;
00258 HeapTuple tup;
00259 Relation rel;
00260
00261 rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
00262
00263 tup = SearchSysCacheCopy1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(name));
00264
00265 if (!HeapTupleIsValid(tup))
00266 ereport(ERROR,
00267 (errcode(ERRCODE_UNDEFINED_OBJECT),
00268 errmsg("foreign-data wrapper \"%s\" does not exist", name)));
00269
00270 fdwId = HeapTupleGetOid(tup);
00271
00272 AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
00273
00274 heap_freetuple(tup);
00275
00276 heap_close(rel, RowExclusiveLock);
00277
00278 return fdwId;
00279 }
00280
00281
00282
00283
00284
00285
00286 void
00287 AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
00288 {
00289 HeapTuple tup;
00290 Relation rel;
00291
00292 rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
00293
00294 tup = SearchSysCacheCopy1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fwdId));
00295
00296 if (!HeapTupleIsValid(tup))
00297 ereport(ERROR,
00298 (errcode(ERRCODE_UNDEFINED_OBJECT),
00299 errmsg("foreign-data wrapper with OID %u does not exist", fwdId)));
00300
00301 AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
00302
00303 heap_freetuple(tup);
00304
00305 heap_close(rel, RowExclusiveLock);
00306 }
00307
00308
00309
00310
00311 static void
00312 AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
00313 {
00314 Form_pg_foreign_server form;
00315
00316 form = (Form_pg_foreign_server) GETSTRUCT(tup);
00317
00318 if (form->srvowner != newOwnerId)
00319 {
00320
00321 if (!superuser())
00322 {
00323 Oid srvId;
00324 AclResult aclresult;
00325
00326 srvId = HeapTupleGetOid(tup);
00327
00328
00329 if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
00330 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
00331 NameStr(form->srvname));
00332
00333
00334 check_is_member_of_role(GetUserId(), newOwnerId);
00335
00336
00337 aclresult = pg_foreign_data_wrapper_aclcheck(form->srvfdw, newOwnerId, ACL_USAGE);
00338 if (aclresult != ACLCHECK_OK)
00339 {
00340 ForeignDataWrapper *fdw = GetForeignDataWrapper(form->srvfdw);
00341
00342 aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);
00343 }
00344 }
00345
00346 form->srvowner = newOwnerId;
00347
00348 simple_heap_update(rel, &tup->t_self, tup);
00349 CatalogUpdateIndexes(rel, tup);
00350
00351
00352 changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
00353 newOwnerId);
00354 }
00355
00356 InvokeObjectPostAlterHook(ForeignServerRelationId,
00357 HeapTupleGetOid(tup), 0);
00358 }
00359
00360
00361
00362
00363 Oid
00364 AlterForeignServerOwner(const char *name, Oid newOwnerId)
00365 {
00366 Oid servOid;
00367 HeapTuple tup;
00368 Relation rel;
00369
00370 rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
00371
00372 tup = SearchSysCacheCopy1(FOREIGNSERVERNAME, CStringGetDatum(name));
00373
00374 if (!HeapTupleIsValid(tup))
00375 ereport(ERROR,
00376 (errcode(ERRCODE_UNDEFINED_OBJECT),
00377 errmsg("server \"%s\" does not exist", name)));
00378
00379 servOid = HeapTupleGetOid(tup);
00380
00381 AlterForeignServerOwner_internal(rel, tup, newOwnerId);
00382
00383 heap_freetuple(tup);
00384
00385 heap_close(rel, RowExclusiveLock);
00386
00387 return servOid;
00388 }
00389
00390
00391
00392
00393 void
00394 AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
00395 {
00396 HeapTuple tup;
00397 Relation rel;
00398
00399 rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
00400
00401 tup = SearchSysCacheCopy1(FOREIGNSERVEROID, ObjectIdGetDatum(srvId));
00402
00403 if (!HeapTupleIsValid(tup))
00404 ereport(ERROR,
00405 (errcode(ERRCODE_UNDEFINED_OBJECT),
00406 errmsg("foreign server with OID %u does not exist", srvId)));
00407
00408 AlterForeignServerOwner_internal(rel, tup, newOwnerId);
00409
00410 heap_freetuple(tup);
00411
00412 heap_close(rel, RowExclusiveLock);
00413 }
00414
00415
00416
00417
00418 static Oid
00419 lookup_fdw_handler_func(DefElem *handler)
00420 {
00421 Oid handlerOid;
00422
00423 if (handler == NULL || handler->arg == NULL)
00424 return InvalidOid;
00425
00426
00427 handlerOid = LookupFuncName((List *) handler->arg, 0, NULL, false);
00428
00429
00430 if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
00431 ereport(ERROR,
00432 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00433 errmsg("function %s must return type \"fdw_handler\"",
00434 NameListToString((List *) handler->arg))));
00435
00436 return handlerOid;
00437 }
00438
00439
00440
00441
00442 static Oid
00443 lookup_fdw_validator_func(DefElem *validator)
00444 {
00445 Oid funcargtypes[2];
00446
00447 if (validator == NULL || validator->arg == NULL)
00448 return InvalidOid;
00449
00450
00451 funcargtypes[0] = TEXTARRAYOID;
00452 funcargtypes[1] = OIDOID;
00453
00454 return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
00455
00456 }
00457
00458
00459
00460
00461 static void
00462 parse_func_options(List *func_options,
00463 bool *handler_given, Oid *fdwhandler,
00464 bool *validator_given, Oid *fdwvalidator)
00465 {
00466 ListCell *cell;
00467
00468 *handler_given = false;
00469 *validator_given = false;
00470
00471 *fdwhandler = InvalidOid;
00472 *fdwvalidator = InvalidOid;
00473
00474 foreach(cell, func_options)
00475 {
00476 DefElem *def = (DefElem *) lfirst(cell);
00477
00478 if (strcmp(def->defname, "handler") == 0)
00479 {
00480 if (*handler_given)
00481 ereport(ERROR,
00482 (errcode(ERRCODE_SYNTAX_ERROR),
00483 errmsg("conflicting or redundant options")));
00484 *handler_given = true;
00485 *fdwhandler = lookup_fdw_handler_func(def);
00486 }
00487 else if (strcmp(def->defname, "validator") == 0)
00488 {
00489 if (*validator_given)
00490 ereport(ERROR,
00491 (errcode(ERRCODE_SYNTAX_ERROR),
00492 errmsg("conflicting or redundant options")));
00493 *validator_given = true;
00494 *fdwvalidator = lookup_fdw_validator_func(def);
00495 }
00496 else
00497 elog(ERROR, "option \"%s\" not recognized",
00498 def->defname);
00499 }
00500 }
00501
00502
00503
00504
00505 Oid
00506 CreateForeignDataWrapper(CreateFdwStmt *stmt)
00507 {
00508 Relation rel;
00509 Datum values[Natts_pg_foreign_data_wrapper];
00510 bool nulls[Natts_pg_foreign_data_wrapper];
00511 HeapTuple tuple;
00512 Oid fdwId;
00513 bool handler_given;
00514 bool validator_given;
00515 Oid fdwhandler;
00516 Oid fdwvalidator;
00517 Datum fdwoptions;
00518 Oid ownerId;
00519 ObjectAddress myself;
00520 ObjectAddress referenced;
00521
00522 rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
00523
00524
00525 if (!superuser())
00526 ereport(ERROR,
00527 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00528 errmsg("permission denied to create foreign-data wrapper \"%s\"",
00529 stmt->fdwname),
00530 errhint("Must be superuser to create a foreign-data wrapper.")));
00531
00532
00533 ownerId = GetUserId();
00534
00535
00536
00537
00538 if (GetForeignDataWrapperByName(stmt->fdwname, true) != NULL)
00539 ereport(ERROR,
00540 (errcode(ERRCODE_DUPLICATE_OBJECT),
00541 errmsg("foreign-data wrapper \"%s\" already exists",
00542 stmt->fdwname)));
00543
00544
00545
00546
00547 memset(values, 0, sizeof(values));
00548 memset(nulls, false, sizeof(nulls));
00549
00550 values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
00551 DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
00552 values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
00553
00554
00555 parse_func_options(stmt->func_options,
00556 &handler_given, &fdwhandler,
00557 &validator_given, &fdwvalidator);
00558
00559 values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
00560 values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
00561
00562 nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
00563
00564 fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId,
00565 PointerGetDatum(NULL),
00566 stmt->options,
00567 fdwvalidator);
00568
00569 if (PointerIsValid(DatumGetPointer(fdwoptions)))
00570 values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
00571 else
00572 nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
00573
00574 tuple = heap_form_tuple(rel->rd_att, values, nulls);
00575
00576 fdwId = simple_heap_insert(rel, tuple);
00577 CatalogUpdateIndexes(rel, tuple);
00578
00579 heap_freetuple(tuple);
00580
00581
00582 myself.classId = ForeignDataWrapperRelationId;
00583 myself.objectId = fdwId;
00584 myself.objectSubId = 0;
00585
00586 if (OidIsValid(fdwhandler))
00587 {
00588 referenced.classId = ProcedureRelationId;
00589 referenced.objectId = fdwhandler;
00590 referenced.objectSubId = 0;
00591 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00592 }
00593
00594 if (OidIsValid(fdwvalidator))
00595 {
00596 referenced.classId = ProcedureRelationId;
00597 referenced.objectId = fdwvalidator;
00598 referenced.objectSubId = 0;
00599 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00600 }
00601
00602 recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
00603
00604
00605 recordDependencyOnCurrentExtension(&myself, false);
00606
00607
00608 InvokeObjectPostCreateHook(ForeignDataWrapperRelationId, fdwId, 0);
00609
00610 heap_close(rel, RowExclusiveLock);
00611
00612 return fdwId;
00613 }
00614
00615
00616
00617
00618
00619 Oid
00620 AlterForeignDataWrapper(AlterFdwStmt *stmt)
00621 {
00622 Relation rel;
00623 HeapTuple tp;
00624 Form_pg_foreign_data_wrapper fdwForm;
00625 Datum repl_val[Natts_pg_foreign_data_wrapper];
00626 bool repl_null[Natts_pg_foreign_data_wrapper];
00627 bool repl_repl[Natts_pg_foreign_data_wrapper];
00628 Oid fdwId;
00629 bool isnull;
00630 Datum datum;
00631 bool handler_given;
00632 bool validator_given;
00633 Oid fdwhandler;
00634 Oid fdwvalidator;
00635
00636 rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
00637
00638
00639 if (!superuser())
00640 ereport(ERROR,
00641 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00642 errmsg("permission denied to alter foreign-data wrapper \"%s\"",
00643 stmt->fdwname),
00644 errhint("Must be superuser to alter a foreign-data wrapper.")));
00645
00646 tp = SearchSysCacheCopy1(FOREIGNDATAWRAPPERNAME,
00647 CStringGetDatum(stmt->fdwname));
00648
00649 if (!HeapTupleIsValid(tp))
00650 ereport(ERROR,
00651 (errcode(ERRCODE_UNDEFINED_OBJECT),
00652 errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
00653
00654 fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
00655 fdwId = HeapTupleGetOid(tp);
00656
00657 memset(repl_val, 0, sizeof(repl_val));
00658 memset(repl_null, false, sizeof(repl_null));
00659 memset(repl_repl, false, sizeof(repl_repl));
00660
00661 parse_func_options(stmt->func_options,
00662 &handler_given, &fdwhandler,
00663 &validator_given, &fdwvalidator);
00664
00665 if (handler_given)
00666 {
00667 repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
00668 repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
00669
00670
00671
00672
00673
00674 ereport(WARNING,
00675 (errmsg("changing the foreign-data wrapper handler can change behavior of existing foreign tables")));
00676 }
00677
00678 if (validator_given)
00679 {
00680 repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
00681 repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
00682
00683
00684
00685
00686
00687 if (OidIsValid(fdwvalidator))
00688 ereport(WARNING,
00689 (errmsg("changing the foreign-data wrapper validator can cause "
00690 "the options for dependent objects to become invalid")));
00691 }
00692 else
00693 {
00694
00695
00696
00697 fdwvalidator = fdwForm->fdwvalidator;
00698 }
00699
00700
00701
00702
00703 if (stmt->options)
00704 {
00705
00706 datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
00707 tp,
00708 Anum_pg_foreign_data_wrapper_fdwoptions,
00709 &isnull);
00710 if (isnull)
00711 datum = PointerGetDatum(NULL);
00712
00713
00714 datum = transformGenericOptions(ForeignDataWrapperRelationId,
00715 datum,
00716 stmt->options,
00717 fdwvalidator);
00718
00719 if (PointerIsValid(DatumGetPointer(datum)))
00720 repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
00721 else
00722 repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
00723
00724 repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
00725 }
00726
00727
00728 tp = heap_modify_tuple(tp, RelationGetDescr(rel),
00729 repl_val, repl_null, repl_repl);
00730
00731 simple_heap_update(rel, &tp->t_self, tp);
00732 CatalogUpdateIndexes(rel, tp);
00733
00734 heap_freetuple(tp);
00735
00736
00737 if (handler_given || validator_given)
00738 {
00739 ObjectAddress myself;
00740 ObjectAddress referenced;
00741
00742
00743
00744
00745
00746 deleteDependencyRecordsForClass(ForeignDataWrapperRelationId,
00747 fdwId,
00748 ProcedureRelationId,
00749 DEPENDENCY_NORMAL);
00750
00751
00752 myself.classId = ForeignDataWrapperRelationId;
00753 myself.objectId = fdwId;
00754 myself.objectSubId = 0;
00755
00756 if (OidIsValid(fdwhandler))
00757 {
00758 referenced.classId = ProcedureRelationId;
00759 referenced.objectId = fdwhandler;
00760 referenced.objectSubId = 0;
00761 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00762 }
00763
00764 if (OidIsValid(fdwvalidator))
00765 {
00766 referenced.classId = ProcedureRelationId;
00767 referenced.objectId = fdwvalidator;
00768 referenced.objectSubId = 0;
00769 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00770 }
00771 }
00772
00773 InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0);
00774
00775 heap_close(rel, RowExclusiveLock);
00776
00777 return fdwId;
00778 }
00779
00780
00781
00782
00783
00784 void
00785 RemoveForeignDataWrapperById(Oid fdwId)
00786 {
00787 HeapTuple tp;
00788 Relation rel;
00789
00790 rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
00791
00792 tp = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdwId));
00793
00794 if (!HeapTupleIsValid(tp))
00795 elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwId);
00796
00797 simple_heap_delete(rel, &tp->t_self);
00798
00799 ReleaseSysCache(tp);
00800
00801 heap_close(rel, RowExclusiveLock);
00802 }
00803
00804
00805
00806
00807
00808 Oid
00809 CreateForeignServer(CreateForeignServerStmt *stmt)
00810 {
00811 Relation rel;
00812 Datum srvoptions;
00813 Datum values[Natts_pg_foreign_server];
00814 bool nulls[Natts_pg_foreign_server];
00815 HeapTuple tuple;
00816 Oid srvId;
00817 Oid ownerId;
00818 AclResult aclresult;
00819 ObjectAddress myself;
00820 ObjectAddress referenced;
00821 ForeignDataWrapper *fdw;
00822
00823 rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
00824
00825
00826 ownerId = GetUserId();
00827
00828
00829
00830
00831 if (GetForeignServerByName(stmt->servername, true) != NULL)
00832 ereport(ERROR,
00833 (errcode(ERRCODE_DUPLICATE_OBJECT),
00834 errmsg("server \"%s\" already exists",
00835 stmt->servername)));
00836
00837
00838
00839
00840
00841 fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
00842
00843 aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, ACL_USAGE);
00844 if (aclresult != ACLCHECK_OK)
00845 aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);
00846
00847
00848
00849
00850 memset(values, 0, sizeof(values));
00851 memset(nulls, false, sizeof(nulls));
00852
00853 values[Anum_pg_foreign_server_srvname - 1] =
00854 DirectFunctionCall1(namein, CStringGetDatum(stmt->servername));
00855 values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
00856 values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid);
00857
00858
00859 if (stmt->servertype)
00860 values[Anum_pg_foreign_server_srvtype - 1] =
00861 CStringGetTextDatum(stmt->servertype);
00862 else
00863 nulls[Anum_pg_foreign_server_srvtype - 1] = true;
00864
00865
00866 if (stmt->version)
00867 values[Anum_pg_foreign_server_srvversion - 1] =
00868 CStringGetTextDatum(stmt->version);
00869 else
00870 nulls[Anum_pg_foreign_server_srvversion - 1] = true;
00871
00872
00873 nulls[Anum_pg_foreign_server_srvacl - 1] = true;
00874
00875
00876 srvoptions = transformGenericOptions(ForeignServerRelationId,
00877 PointerGetDatum(NULL),
00878 stmt->options,
00879 fdw->fdwvalidator);
00880
00881 if (PointerIsValid(DatumGetPointer(srvoptions)))
00882 values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
00883 else
00884 nulls[Anum_pg_foreign_server_srvoptions - 1] = true;
00885
00886 tuple = heap_form_tuple(rel->rd_att, values, nulls);
00887
00888 srvId = simple_heap_insert(rel, tuple);
00889
00890 CatalogUpdateIndexes(rel, tuple);
00891
00892 heap_freetuple(tuple);
00893
00894
00895 myself.classId = ForeignServerRelationId;
00896 myself.objectId = srvId;
00897 myself.objectSubId = 0;
00898
00899 referenced.classId = ForeignDataWrapperRelationId;
00900 referenced.objectId = fdw->fdwid;
00901 referenced.objectSubId = 0;
00902 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00903
00904 recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);
00905
00906
00907 recordDependencyOnCurrentExtension(&myself, false);
00908
00909
00910 InvokeObjectPostCreateHook(ForeignServerRelationId, srvId, 0);
00911
00912 heap_close(rel, RowExclusiveLock);
00913
00914 return srvId;
00915 }
00916
00917
00918
00919
00920
00921 Oid
00922 AlterForeignServer(AlterForeignServerStmt *stmt)
00923 {
00924 Relation rel;
00925 HeapTuple tp;
00926 Datum repl_val[Natts_pg_foreign_server];
00927 bool repl_null[Natts_pg_foreign_server];
00928 bool repl_repl[Natts_pg_foreign_server];
00929 Oid srvId;
00930 Form_pg_foreign_server srvForm;
00931
00932 rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
00933
00934 tp = SearchSysCacheCopy1(FOREIGNSERVERNAME,
00935 CStringGetDatum(stmt->servername));
00936
00937 if (!HeapTupleIsValid(tp))
00938 ereport(ERROR,
00939 (errcode(ERRCODE_UNDEFINED_OBJECT),
00940 errmsg("server \"%s\" does not exist", stmt->servername)));
00941
00942 srvId = HeapTupleGetOid(tp);
00943 srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
00944
00945
00946
00947
00948 if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
00949 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
00950 stmt->servername);
00951
00952 memset(repl_val, 0, sizeof(repl_val));
00953 memset(repl_null, false, sizeof(repl_null));
00954 memset(repl_repl, false, sizeof(repl_repl));
00955
00956 if (stmt->has_version)
00957 {
00958
00959
00960
00961 if (stmt->version)
00962 repl_val[Anum_pg_foreign_server_srvversion - 1] =
00963 CStringGetTextDatum(stmt->version);
00964 else
00965 repl_null[Anum_pg_foreign_server_srvversion - 1] = true;
00966
00967 repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
00968 }
00969
00970 if (stmt->options)
00971 {
00972 ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
00973 Datum datum;
00974 bool isnull;
00975
00976
00977 datum = SysCacheGetAttr(FOREIGNSERVEROID,
00978 tp,
00979 Anum_pg_foreign_server_srvoptions,
00980 &isnull);
00981 if (isnull)
00982 datum = PointerGetDatum(NULL);
00983
00984
00985 datum = transformGenericOptions(ForeignServerRelationId,
00986 datum,
00987 stmt->options,
00988 fdw->fdwvalidator);
00989
00990 if (PointerIsValid(DatumGetPointer(datum)))
00991 repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
00992 else
00993 repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;
00994
00995 repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
00996 }
00997
00998
00999 tp = heap_modify_tuple(tp, RelationGetDescr(rel),
01000 repl_val, repl_null, repl_repl);
01001
01002 simple_heap_update(rel, &tp->t_self, tp);
01003 CatalogUpdateIndexes(rel, tp);
01004
01005 InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
01006
01007 heap_freetuple(tp);
01008
01009 heap_close(rel, RowExclusiveLock);
01010
01011 return srvId;
01012 }
01013
01014
01015
01016
01017
01018 void
01019 RemoveForeignServerById(Oid srvId)
01020 {
01021 HeapTuple tp;
01022 Relation rel;
01023
01024 rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
01025
01026 tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srvId));
01027
01028 if (!HeapTupleIsValid(tp))
01029 elog(ERROR, "cache lookup failed for foreign server %u", srvId);
01030
01031 simple_heap_delete(rel, &tp->t_self);
01032
01033 ReleaseSysCache(tp);
01034
01035 heap_close(rel, RowExclusiveLock);
01036 }
01037
01038
01039
01040
01041
01042
01043
01044 static void
01045 user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
01046 {
01047 Oid curuserid = GetUserId();
01048
01049 if (!pg_foreign_server_ownercheck(serverid, curuserid))
01050 {
01051 if (umuserid == curuserid)
01052 {
01053 AclResult aclresult;
01054
01055 aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE);
01056 if (aclresult != ACLCHECK_OK)
01057 aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, servername);
01058 }
01059 else
01060 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
01061 servername);
01062 }
01063 }
01064
01065
01066
01067
01068
01069 Oid
01070 CreateUserMapping(CreateUserMappingStmt *stmt)
01071 {
01072 Relation rel;
01073 Datum useoptions;
01074 Datum values[Natts_pg_user_mapping];
01075 bool nulls[Natts_pg_user_mapping];
01076 HeapTuple tuple;
01077 Oid useId;
01078 Oid umId;
01079 ObjectAddress myself;
01080 ObjectAddress referenced;
01081 ForeignServer *srv;
01082 ForeignDataWrapper *fdw;
01083
01084 rel = heap_open(UserMappingRelationId, RowExclusiveLock);
01085
01086 useId = GetUserOidFromMapping(stmt->username, false);
01087
01088
01089 srv = GetForeignServerByName(stmt->servername, false);
01090
01091 user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
01092
01093
01094
01095
01096 umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
01097 ObjectIdGetDatum(useId),
01098 ObjectIdGetDatum(srv->serverid));
01099 if (OidIsValid(umId))
01100 ereport(ERROR,
01101 (errcode(ERRCODE_DUPLICATE_OBJECT),
01102 errmsg("user mapping \"%s\" already exists for server %s",
01103 MappingUserName(useId),
01104 stmt->servername)));
01105
01106 fdw = GetForeignDataWrapper(srv->fdwid);
01107
01108
01109
01110
01111 memset(values, 0, sizeof(values));
01112 memset(nulls, false, sizeof(nulls));
01113
01114 values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
01115 values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
01116
01117
01118 useoptions = transformGenericOptions(UserMappingRelationId,
01119 PointerGetDatum(NULL),
01120 stmt->options,
01121 fdw->fdwvalidator);
01122
01123 if (PointerIsValid(DatumGetPointer(useoptions)))
01124 values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
01125 else
01126 nulls[Anum_pg_user_mapping_umoptions - 1] = true;
01127
01128 tuple = heap_form_tuple(rel->rd_att, values, nulls);
01129
01130 umId = simple_heap_insert(rel, tuple);
01131
01132 CatalogUpdateIndexes(rel, tuple);
01133
01134 heap_freetuple(tuple);
01135
01136
01137 myself.classId = UserMappingRelationId;
01138 myself.objectId = umId;
01139 myself.objectSubId = 0;
01140
01141 referenced.classId = ForeignServerRelationId;
01142 referenced.objectId = srv->serverid;
01143 referenced.objectSubId = 0;
01144 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01145
01146 if (OidIsValid(useId))
01147 {
01148
01149 recordDependencyOnOwner(UserMappingRelationId, umId, useId);
01150 }
01151
01152
01153 recordDependencyOnCurrentExtension(&myself, false);
01154
01155
01156 InvokeObjectPostCreateHook(UserMappingRelationId, umId, 0);
01157
01158 heap_close(rel, RowExclusiveLock);
01159
01160 return umId;
01161 }
01162
01163
01164
01165
01166
01167 Oid
01168 AlterUserMapping(AlterUserMappingStmt *stmt)
01169 {
01170 Relation rel;
01171 HeapTuple tp;
01172 Datum repl_val[Natts_pg_user_mapping];
01173 bool repl_null[Natts_pg_user_mapping];
01174 bool repl_repl[Natts_pg_user_mapping];
01175 Oid useId;
01176 Oid umId;
01177 ForeignServer *srv;
01178
01179 rel = heap_open(UserMappingRelationId, RowExclusiveLock);
01180
01181 useId = GetUserOidFromMapping(stmt->username, false);
01182 srv = GetForeignServerByName(stmt->servername, false);
01183
01184 umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
01185 ObjectIdGetDatum(useId),
01186 ObjectIdGetDatum(srv->serverid));
01187 if (!OidIsValid(umId))
01188 ereport(ERROR,
01189 (errcode(ERRCODE_UNDEFINED_OBJECT),
01190 errmsg("user mapping \"%s\" does not exist for the server",
01191 MappingUserName(useId))));
01192
01193 user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
01194
01195 tp = SearchSysCacheCopy1(USERMAPPINGOID, ObjectIdGetDatum(umId));
01196
01197 if (!HeapTupleIsValid(tp))
01198 elog(ERROR, "cache lookup failed for user mapping %u", umId);
01199
01200 memset(repl_val, 0, sizeof(repl_val));
01201 memset(repl_null, false, sizeof(repl_null));
01202 memset(repl_repl, false, sizeof(repl_repl));
01203
01204 if (stmt->options)
01205 {
01206 ForeignDataWrapper *fdw;
01207 Datum datum;
01208 bool isnull;
01209
01210
01211
01212
01213
01214 fdw = GetForeignDataWrapper(srv->fdwid);
01215
01216 datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
01217 tp,
01218 Anum_pg_user_mapping_umoptions,
01219 &isnull);
01220 if (isnull)
01221 datum = PointerGetDatum(NULL);
01222
01223
01224 datum = transformGenericOptions(UserMappingRelationId,
01225 datum,
01226 stmt->options,
01227 fdw->fdwvalidator);
01228
01229 if (PointerIsValid(DatumGetPointer(datum)))
01230 repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
01231 else
01232 repl_null[Anum_pg_user_mapping_umoptions - 1] = true;
01233
01234 repl_repl[Anum_pg_user_mapping_umoptions - 1] = true;
01235 }
01236
01237
01238 tp = heap_modify_tuple(tp, RelationGetDescr(rel),
01239 repl_val, repl_null, repl_repl);
01240
01241 simple_heap_update(rel, &tp->t_self, tp);
01242 CatalogUpdateIndexes(rel, tp);
01243
01244 heap_freetuple(tp);
01245
01246 heap_close(rel, RowExclusiveLock);
01247
01248 return umId;
01249 }
01250
01251
01252
01253
01254
01255 Oid
01256 RemoveUserMapping(DropUserMappingStmt *stmt)
01257 {
01258 ObjectAddress object;
01259 Oid useId;
01260 Oid umId;
01261 ForeignServer *srv;
01262
01263 useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok);
01264 srv = GetForeignServerByName(stmt->servername, true);
01265
01266 if (stmt->username && !OidIsValid(useId))
01267 {
01268
01269
01270
01271
01272 elog(NOTICE, "role \"%s\" does not exist, skipping", stmt->username);
01273 return InvalidOid;
01274 }
01275
01276 if (!srv)
01277 {
01278 if (!stmt->missing_ok)
01279 ereport(ERROR,
01280 (errcode(ERRCODE_UNDEFINED_OBJECT),
01281 errmsg("server \"%s\" does not exist",
01282 stmt->servername)));
01283
01284 ereport(NOTICE, (errmsg("server does not exist, skipping")));
01285 return InvalidOid;
01286 }
01287
01288 umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
01289 ObjectIdGetDatum(useId),
01290 ObjectIdGetDatum(srv->serverid));
01291
01292 if (!OidIsValid(umId))
01293 {
01294 if (!stmt->missing_ok)
01295 ereport(ERROR,
01296 (errcode(ERRCODE_UNDEFINED_OBJECT),
01297 errmsg("user mapping \"%s\" does not exist for the server",
01298 MappingUserName(useId))));
01299
01300
01301 ereport(NOTICE,
01302 (errmsg("user mapping \"%s\" does not exist for the server, skipping",
01303 MappingUserName(useId))));
01304 return InvalidOid;
01305 }
01306
01307 user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername);
01308
01309
01310
01311
01312 object.classId = UserMappingRelationId;
01313 object.objectId = umId;
01314 object.objectSubId = 0;
01315
01316 performDeletion(&object, DROP_CASCADE, 0);
01317
01318 return umId;
01319 }
01320
01321
01322
01323
01324
01325 void
01326 RemoveUserMappingById(Oid umId)
01327 {
01328 HeapTuple tp;
01329 Relation rel;
01330
01331 rel = heap_open(UserMappingRelationId, RowExclusiveLock);
01332
01333 tp = SearchSysCache1(USERMAPPINGOID, ObjectIdGetDatum(umId));
01334
01335 if (!HeapTupleIsValid(tp))
01336 elog(ERROR, "cache lookup failed for user mapping %u", umId);
01337
01338 simple_heap_delete(rel, &tp->t_self);
01339
01340 ReleaseSysCache(tp);
01341
01342 heap_close(rel, RowExclusiveLock);
01343 }
01344
01345
01346
01347
01348
01349 void
01350 CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
01351 {
01352 Relation ftrel;
01353 Datum ftoptions;
01354 Datum values[Natts_pg_foreign_table];
01355 bool nulls[Natts_pg_foreign_table];
01356 HeapTuple tuple;
01357 AclResult aclresult;
01358 ObjectAddress myself;
01359 ObjectAddress referenced;
01360 Oid ownerId;
01361 ForeignDataWrapper *fdw;
01362 ForeignServer *server;
01363
01364
01365
01366
01367
01368 CommandCounterIncrement();
01369
01370 ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
01371
01372
01373
01374
01375 ownerId = GetUserId();
01376
01377
01378
01379
01380
01381 server = GetForeignServerByName(stmt->servername, false);
01382 aclresult = pg_foreign_server_aclcheck(server->serverid, ownerId, ACL_USAGE);
01383 if (aclresult != ACLCHECK_OK)
01384 aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, server->servername);
01385
01386 fdw = GetForeignDataWrapper(server->fdwid);
01387
01388
01389
01390
01391 memset(values, 0, sizeof(values));
01392 memset(nulls, false, sizeof(nulls));
01393
01394 values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid);
01395 values[Anum_pg_foreign_table_ftserver - 1] = ObjectIdGetDatum(server->serverid);
01396
01397 ftoptions = transformGenericOptions(ForeignTableRelationId,
01398 PointerGetDatum(NULL),
01399 stmt->options,
01400 fdw->fdwvalidator);
01401
01402 if (PointerIsValid(DatumGetPointer(ftoptions)))
01403 values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions;
01404 else
01405 nulls[Anum_pg_foreign_table_ftoptions - 1] = true;
01406
01407 tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
01408
01409 simple_heap_insert(ftrel, tuple);
01410 CatalogUpdateIndexes(ftrel, tuple);
01411
01412 heap_freetuple(tuple);
01413
01414
01415 myself.classId = RelationRelationId;
01416 myself.objectId = relid;
01417 myself.objectSubId = 0;
01418
01419 referenced.classId = ForeignServerRelationId;
01420 referenced.objectId = server->serverid;
01421 referenced.objectSubId = 0;
01422 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01423
01424 heap_close(ftrel, RowExclusiveLock);
01425 }