Skip to content

Commit 51e58b8

Browse files
committed
after applying fdw_catalog_lookup_20110131.patch, fdw_handler_20110131.patch and foreign_scan_20110131.patch
1 parent 5537074 commit 51e58b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1296
-156
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,17 @@
28112811
</entry>
28122812
</row>
28132813

2814+
<row>
2815+
<entry><structfield>fdwhandler</structfield></entry>
2816+
<entry><type>oid</type></entry>
2817+
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
2818+
<entry>
2819+
References a handler function that is responsible for
2820+
supplying foreign-data wrapper routines.
2821+
Zero if no handler is provided.
2822+
</entry>
2823+
</row>
2824+
28142825
<row>
28152826
<entry><structfield>fdwacl</structfield></entry>
28162827
<entry><type>aclitem[]</type></entry>

doc/src/sgml/ref/alter_foreign_data_wrapper.sgml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PostgreSQL documentation
2323
<synopsis>
2424
ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
2525
[ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
26+
[ HANDLER <replaceable class="parameter">handler</replaceable> | NO HANDLER ]
2627
[ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ]) ]
2728
ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
2829
</synopsis>
@@ -85,6 +86,29 @@ ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWN
8586
</listitem>
8687
</varlistentry>
8788

89+
<varlistentry>
90+
<term><literal>HANDLER <replaceable class="parameter">handler</replaceable></literal></term>
91+
<listitem>
92+
<para>
93+
Specifies a new foreign-data wrapper handler function.
94+
</para>
95+
</listitem>
96+
</varlistentry>
97+
98+
<varlistentry>
99+
<term><literal>NO HANDLER</literal></term>
100+
<listitem>
101+
<para>
102+
This is used to specify that the foreign-data wrapper should no
103+
longer have a handler function.
104+
</para>
105+
<para>
106+
Note that foreign tables which uses a foreign-data wrapper with no
107+
handler can't be used in a SELECT statement.
108+
</para>
109+
</listitem>
110+
</varlistentry>
111+
88112
<varlistentry>
89113
<term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
90114
<listitem>
@@ -127,8 +151,8 @@ ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator;
127151
<para>
128152
<command>ALTER FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
129153
9075-9 (SQL/MED). The standard does not specify the <literal>
130-
VALIDATOR</literal> and <literal>OWNER TO</> variants of the
131-
command.
154+
VALIDATOR</literal>, <literal>HANDLER</> and <literal>OWNER TO</>
155+
variants of the command.
132156
</para>
133157
</refsect1>
134158

doc/src/sgml/ref/create_foreign_data_wrapper.sgml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PostgreSQL documentation
2323
<synopsis>
2424
CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
2525
[ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
26+
[ HANDLER <replaceable class="parameter">handler</replaceable> | NO HANDLER ]
2627
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
2728
</synopsis>
2829
</refsynopsisdiv>
@@ -81,6 +82,19 @@ CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
8182
</listitem>
8283
</varlistentry>
8384

85+
<varlistentry>
86+
<term><literal>HANDLER <replaceable class="parameter">handler</replaceable></literal></term>
87+
<listitem>
88+
<para>
89+
<replaceable class="parameter">handler</replaceable> is the
90+
name of a previously registered function that will be called to
91+
retrieve a set of functions for foreign tables.
92+
The handler function must take no arguments.
93+
The return type must be <type>fdw_handler</type>.
94+
</para>
95+
</listitem>
96+
</varlistentry>
97+
8498
<varlistentry>
8599
<term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] )</literal></term>
86100
<listitem>
@@ -151,8 +165,8 @@ CREATE FOREIGN DATA WRAPPER mywrapper
151165

152166
<para>
153167
<command>CREATE FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
154-
9075-9 (SQL/MED), with the exception that
155-
the <literal>VALIDATOR</literal> clause is an extension and the
168+
9075-9 (SQL/MED), with the exception that the <literal>VALIDATOR</literal>
169+
and <literal>HANDLER</literal> clauses are extensions and the
156170
clauses <literal>LIBRARY</literal> and <literal>LANGUAGE</literal>
157171
are not yet implemented in PostgreSQL.
158172
</para>

doc/src/sgml/ref/explain.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,9 @@ ROLLBACK;
129129
Display additional information regarding the plan. Specifically, include
130130
the output column list for each node in the plan tree, schema-qualify
131131
table and function names, always label variables in expressions with
132-
their range table alias, and always print the name of each trigger for
133-
which statistics are displayed. This parameter defaults to
132+
their range table alias, always print the name of each trigger for
133+
which statistics are displayed, and print FDW-specific information for
134+
each ForeignScan node in the plan tree. This parameter defaults to
134135
<literal>FALSE</literal>.
135136
</para>
136137
</listitem>

doc/src/sgml/ref/lock.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [, ...
108108
<term><replaceable class="PARAMETER">name</replaceable></term>
109109
<listitem>
110110
<para>
111-
The name (optionally schema-qualified) of an existing table to
111+
The name (optionally schema-qualified) of an existing table
112+
or a existing foreign table to
112113
lock. If <literal>ONLY</> is specified, only that table is
113114
locked. If <literal>ONLY</> is not specified, the table and all
114115
its descendant tables (if any) are locked.

doc/src/sgml/ref/select.sgml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ TABLE { [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] |
195195
or <literal>FOR SHARE</literal> requires
196196
<literal>UPDATE</literal> privilege as well (for at least one column
197197
of each table so selected).
198+
So you cannot lock contents of a foreign table because only SELECT
199+
privilege can be granted on foreign tables.
198200
</para>
199201
</refsect1>
200202

src/backend/commands/explain.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
705705
case T_WorkTableScan:
706706
pname = sname = "WorkTable Scan";
707707
break;
708+
case T_ForeignScan:
709+
pname = sname = "Foreign Scan";
710+
break;
708711
case T_Material:
709712
pname = sname = "Materialize";
710713
break;
@@ -854,6 +857,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
854857
case T_ValuesScan:
855858
case T_CteScan:
856859
case T_WorkTableScan:
860+
case T_ForeignScan:
857861
ExplainScanTarget((Scan *) plan, es);
858862
break;
859863
case T_BitmapIndexScan:
@@ -1033,6 +1037,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
10331037
case T_ValuesScan:
10341038
case T_CteScan:
10351039
case T_WorkTableScan:
1040+
case T_ForeignScan:
10361041
case T_SubqueryScan:
10371042
show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
10381043
break;
@@ -1100,6 +1105,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
11001105
break;
11011106
}
11021107

1108+
/* Show FDW specific information, if any */
1109+
if (IsA(plan, ForeignScan))
1110+
{
1111+
ForeignScan *scan = (ForeignScan *) plan;
1112+
if (scan->fplan->explainInfo)
1113+
ExplainPropertyText("FDW-Info", scan->fplan->explainInfo, es);
1114+
}
1115+
11031116
/* Show buffer usage */
11041117
if (es->buffers)
11051118
{
@@ -1570,6 +1583,7 @@ ExplainScanTarget(Scan *plan, ExplainState *es)
15701583
case T_IndexScan:
15711584
case T_BitmapHeapScan:
15721585
case T_TidScan:
1586+
case T_ForeignScan:
15731587
/* Assert it's on a real relation */
15741588
Assert(rte->rtekind == RTE_RELATION);
15751589
objectname = get_rel_name(rte->relid);

src/backend/commands/foreigncmds.c

Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,16 +317,69 @@ AlterForeignServerOwner(const char *name, Oid newOwnerId)
317317
* Convert a validator function name passed from the parser to an Oid.
318318
*/
319319
static Oid
320-
lookup_fdw_validator_func(List *validator)
320+
lookup_fdw_validator_func(DefElem *validator)
321321
{
322322
Oid funcargtypes[2];
323323

324+
if (validator == NULL || validator->arg == NULL)
325+
return InvalidOid;
326+
324327
funcargtypes[0] = TEXTARRAYOID;
325328
funcargtypes[1] = OIDOID;
326-
return LookupFuncName(validator, 2, funcargtypes, false);
329+
return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
327330
/* return value is ignored, so we don't check the type */
328331
}
329332

333+
static Oid
334+
lookup_fdw_handler_func(DefElem *handler)
335+
{
336+
Oid handlerOid;
337+
338+
if (handler == NULL || handler->arg == NULL)
339+
return InvalidOid;
340+
341+
/* check that handler have correct return type */
342+
handlerOid = LookupFuncName((List *) handler->arg, 0, NULL, false);
343+
if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
344+
{
345+
ereport(ERROR,
346+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
347+
errmsg("function %s must return type \"fdw_handler\"",
348+
NameListToString((List *) handler->arg))));
349+
}
350+
351+
return handlerOid;
352+
}
353+
354+
static void
355+
parse_func_options(List *func_options, DefElem **validator, DefElem **handler)
356+
{
357+
ListCell *cell;
358+
359+
*validator = NULL;
360+
*handler = NULL;
361+
foreach (cell, func_options)
362+
{
363+
DefElem *def = lfirst(cell);
364+
365+
if (pg_strcasecmp(def->defname, "validator") == 0)
366+
{
367+
if (*validator)
368+
ereport(ERROR, (errmsg("duplicated VALIDATOR")));
369+
*validator = def;
370+
}
371+
else if (pg_strcasecmp(def->defname, "handler") == 0)
372+
{
373+
if (*handler)
374+
ereport(ERROR, (errmsg("duplicated HANDLER")));
375+
*handler = def;
376+
}
377+
else
378+
{
379+
ereport(ERROR, (errmsg("invalid option")));
380+
}
381+
}
382+
}
330383

331384
/*
332385
* Create a foreign-data wrapper
@@ -339,7 +392,10 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
339392
bool nulls[Natts_pg_foreign_data_wrapper];
340393
HeapTuple tuple;
341394
Oid fdwId;
395+
DefElem *defvalidator;
396+
DefElem *defhandler;
342397
Oid fdwvalidator;
398+
Oid fdwhandler;
343399
Datum fdwoptions;
344400
Oid ownerId;
345401

@@ -375,12 +431,13 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
375431
DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
376432
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
377433

378-
if (stmt->validator)
379-
fdwvalidator = lookup_fdw_validator_func(stmt->validator);
380-
else
381-
fdwvalidator = InvalidOid;
434+
/* determine which validator to be used (or not used at all) */
435+
parse_func_options(stmt->func_options, &defvalidator, &defhandler);
436+
fdwvalidator = lookup_fdw_validator_func(defvalidator);
437+
fdwhandler = lookup_fdw_handler_func(defhandler);
382438

383439
values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator;
440+
values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = fdwhandler;
384441

385442
nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
386443

@@ -416,6 +473,21 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
416473
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
417474
}
418475

476+
if (fdwhandler != InvalidOid)
477+
{
478+
ObjectAddress myself;
479+
ObjectAddress referenced;
480+
481+
myself.classId = ForeignDataWrapperRelationId;
482+
myself.objectId = fdwId;
483+
myself.objectSubId = 0;
484+
485+
referenced.classId = ProcedureRelationId;
486+
referenced.objectId = fdwhandler;
487+
referenced.objectSubId = 0;
488+
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
489+
}
490+
419491
recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
420492

421493
/* Post creation hook for new foreign data wrapper */
@@ -440,7 +512,10 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
440512
Oid fdwId;
441513
bool isnull;
442514
Datum datum;
515+
DefElem *defvalidator;
516+
DefElem *defhandler;
443517
Oid fdwvalidator;
518+
Oid fdwhandler;
444519

445520
/* Must be super user */
446521
if (!superuser())
@@ -464,17 +539,19 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
464539
memset(repl_null, false, sizeof(repl_null));
465540
memset(repl_repl, false, sizeof(repl_repl));
466541

467-
if (stmt->change_validator)
542+
parse_func_options(stmt->func_options, &defvalidator, &defhandler);
543+
544+
if (defvalidator)
468545
{
469-
fdwvalidator = stmt->validator ? lookup_fdw_validator_func(stmt->validator) : InvalidOid;
546+
fdwvalidator = lookup_fdw_validator_func(defvalidator);
470547
repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
471548
repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
472549

473550
/*
474551
* It could be that the options for the FDW, SERVER and USER MAPPING
475552
* are no longer valid with the new validator. Warn about this.
476553
*/
477-
if (stmt->validator)
554+
if (defvalidator->arg)
478555
ereport(WARNING,
479556
(errmsg("changing the foreign-data wrapper validator can cause "
480557
"the options for dependent objects to become invalid")));
@@ -492,6 +569,34 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
492569
fdwvalidator = DatumGetObjectId(datum);
493570
}
494571

572+
if (defhandler)
573+
{
574+
fdwhandler = lookup_fdw_handler_func(defhandler);
575+
repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
576+
repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
577+
578+
/*
579+
* It could be that the behavior of accessing foreign table changes
580+
* with the new handler. Warn about this.
581+
*/
582+
if (defhandler->arg)
583+
ereport(WARNING,
584+
(errmsg("changing the foreign-data wrapper handler would change "
585+
"the behavior of accessing foreign tables")));
586+
}
587+
else
588+
{
589+
/*
590+
* Validator is not changed, but we need it for validating options.
591+
*/
592+
datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
593+
tp,
594+
Anum_pg_foreign_data_wrapper_fdwhandler,
595+
&isnull);
596+
Assert(!isnull);
597+
fdwhandler = DatumGetObjectId(datum);
598+
}
599+
495600
/*
496601
* Options specified, validate and update.
497602
*/

src/backend/executor/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ OBJS = execAmi.o execCurrent.o execGrouping.o execJunk.o execMain.o \
2323
nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \
2424
nodeValuesscan.o nodeCtescan.o nodeWorktablescan.o \
2525
nodeGroup.o nodeSubplan.o nodeSubqueryscan.o nodeTidscan.o \
26-
nodeWindowAgg.o tstoreReceiver.o spi.o
26+
nodeForeignscan.o nodeWindowAgg.o tstoreReceiver.o spi.o
2727

2828
include $(top_srcdir)/src/backend/common.mk

0 commit comments

Comments
 (0)