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

Basic foreign table support.

Foreign tables are a core component of SQL/MED.  This commit does
not provide a working SQL/MED infrastructure, because foreign tables
cannot yet be queried.  Support for foreign table scans will need to
be added in a future patch.  However, this patch creates the necessary
system catalog structure, syntax support, and support for ancillary
operations such as COMMENT and SECURITY LABEL.

Shigeru Hanada, heavily revised by Robert Haas
This commit is contained in:
Robert Haas
2011-01-01 23:48:11 -05:00
parent 6600d5e91c
commit 0d692a0dc9
69 changed files with 2275 additions and 211 deletions

View File

@@ -975,8 +975,9 @@ expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
"SELECT c.oid"
"\nFROM pg_catalog.pg_class c"
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
"\nWHERE c.relkind in ('%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
"\nWHERE c.relkind in ('%c', '%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
RELKIND_FOREIGN_TABLE);
processSQLNamePattern(g_conn, query, cell->val, true, false,
"n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)");
@@ -1476,6 +1477,9 @@ getTableData(TableInfo *tblinfo, int numTables, bool oids)
/* Skip SEQUENCEs (handled elsewhere) */
if (tblinfo[i].relkind == RELKIND_SEQUENCE)
continue;
/* Skip FOREIGN TABLEs (no data to dump) */
if (tblinfo[i].relkind == RELKIND_FOREIGN_TABLE)
continue;
/* Skip unlogged tables if so requested */
if (tblinfo[i].relpersistence == RELPERSISTENCE_UNLOGGED
&& no_unlogged_table_data)
@@ -3513,12 +3517,13 @@ getTables(int *numTables)
"d.objsubid = 0 AND "
"d.refclassid = c.tableoid AND d.deptype = 'a') "
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
"WHERE c.relkind in ('%c', '%c', '%c', '%c') "
"WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c') "
"ORDER BY c.oid",
username_subquery,
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
RELKIND_FOREIGN_TABLE);
}
else if (g_fout->remoteVersion >= 90000)
{
@@ -3871,7 +3876,7 @@ getTables(int *numTables)
* assume our lock on the child is enough to prevent schema
* alterations to parent tables.
*
* NOTE: it'd be kinda nice to lock views and sequences too, not only
* NOTE: it'd be kinda nice to lock other relations too, not only
* plain tables, but the backend doesn't presently allow that.
*/
if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
@@ -10938,7 +10943,9 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
/* Handle the ACL here */
namecopy = strdup(fmtId(tbinfo->dobj.name));
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" :
(tbinfo->relkind == RELKIND_FOREIGN_TABLE) ? "FOREIGN TABLE" :
"TABLE",
namecopy, NULL, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl);
@@ -11007,6 +11014,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
int j,
k;
bool toast_set = false;
char *srvname;
char *ftoptions = NULL;
/* Make sure we are in proper schema */
selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
@@ -11080,7 +11089,35 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
}
else
{
reltypename = "TABLE";
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
{
int i_srvname;
int i_ftoptions;
reltypename = "FOREIGN TABLE";
/* retrieve name of foreign server and generic options */
appendPQExpBuffer(query,
"SELECT fs.srvname, array_to_string(ARRAY("
" SELECT option_name || ' ' || quote_literal(option_value)"
" FROM pg_options_to_table(ftoptions)), ', ') AS ftoptions "
"FROM pg_foreign_table ft JOIN pg_foreign_server fs "
" ON (fs.oid = ft.ftserver) "
"WHERE ft.ftrelid = %u", tbinfo->dobj.catId.oid);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
i_srvname = PQfnumber(res, "srvname");
i_ftoptions = PQfnumber(res, "ftoptions");
srvname = strdup(PQgetvalue(res, 0, i_srvname));
ftoptions = strdup(PQgetvalue(res, 0, i_ftoptions));
PQclear(res);
}
else
{
reltypename = "TABLE";
srvname = NULL;
ftoptions = NULL;
}
numParents = tbinfo->numParents;
parents = tbinfo->parents;
@@ -11088,7 +11125,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
* DROP must be fully qualified in case same name appears in
* pg_catalog
*/
appendPQExpBuffer(delq, "DROP TABLE %s.",
appendPQExpBuffer(delq, "DROP %s %s.", reltypename,
fmtId(tbinfo->dobj.namespace->dobj.name));
appendPQExpBuffer(delq, "%s;\n",
fmtId(tbinfo->dobj.name));
@@ -11096,12 +11133,11 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
if (binary_upgrade)
binary_upgrade_set_relfilenodes(q, tbinfo->dobj.catId.oid, false);
if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED)
appendPQExpBuffer(q, "CREATE UNLOGGED TABLE %s",
fmtId(tbinfo->dobj.name));
else
appendPQExpBuffer(q, "CREATE TABLE %s",
fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "CREATE %s%s %s",
tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
"UNLOGGED " : "",
reltypename,
fmtId(tbinfo->dobj.name));
if (tbinfo->reloftype)
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
actual_atts = 0;
@@ -11235,6 +11271,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBuffer(q, ")");
}
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
appendPQExpBuffer(q, "\nSERVER %s", srvname);
if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
(tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))
{
@@ -11254,6 +11293,10 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBuffer(q, ")");
}
/* Dump generic options if any */
if (ftoptions && ftoptions[0])
appendPQExpBuffer(q, "\nOPTIONS (%s)", ftoptions);
appendPQExpBuffer(q, ";\n");
/*
@@ -11268,7 +11311,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
* order. That also means we have to take care about setting
* attislocal correctly, plus fix up any inherited CHECK constraints.
*/
if (binary_upgrade)
if (binary_upgrade && tbinfo->relkind == RELKIND_RELATION)
{
for (j = 0; j < tbinfo->numatts; j++)
{