Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
c4096c76
Commit
c4096c76
authored
Aug 05, 2011
by
Robert Haas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow per-column foreign data wrapper options.
Shigeru Hanada, with fairly minor editing by me.
parent
68cbb9f4
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
407 additions
and
47 deletions
+407
-47
doc/src/sgml/catalogs.sgml
doc/src/sgml/catalogs.sgml
+9
-0
doc/src/sgml/information_schema.sgml
doc/src/sgml/information_schema.sgml
+63
-0
doc/src/sgml/ref/alter_foreign_table.sgml
doc/src/sgml/ref/alter_foreign_table.sgml
+6
-4
doc/src/sgml/ref/create_foreign_table.sgml
doc/src/sgml/ref/create_foreign_table.sgml
+5
-3
doc/src/sgml/ref/psql-ref.sgml
doc/src/sgml/ref/psql-ref.sgml
+6
-0
src/backend/access/common/tupdesc.c
src/backend/access/common/tupdesc.c
+2
-2
src/backend/catalog/genbki.pl
src/backend/catalog/genbki.pl
+3
-1
src/backend/catalog/heap.c
src/backend/catalog/heap.c
+2
-1
src/backend/catalog/information_schema.sql
src/backend/catalog/information_schema.sql
+33
-0
src/backend/commands/tablecmds.c
src/backend/commands/tablecmds.c
+106
-0
src/backend/nodes/copyfuncs.c
src/backend/nodes/copyfuncs.c
+1
-0
src/backend/nodes/outfuncs.c
src/backend/nodes/outfuncs.c
+1
-0
src/backend/parser/gram.y
src/backend/parser/gram.y
+12
-2
src/backend/parser/parse_utilcmd.c
src/backend/parser/parse_utilcmd.c
+25
-0
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.c
+54
-6
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dump.h
+1
-0
src/bin/psql/describe.c
src/bin/psql/describe.c
+20
-2
src/include/catalog/catversion.h
src/include/catalog/catversion.h
+1
-1
src/include/catalog/pg_attribute.h
src/include/catalog/pg_attribute.h
+5
-1
src/include/catalog/pg_class.h
src/include/catalog/pg_class.h
+1
-1
src/include/nodes/parsenodes.h
src/include/nodes/parsenodes.h
+2
-0
src/test/regress/expected/foreign_data.out
src/test/regress/expected/foreign_data.out
+41
-20
src/test/regress/sql/foreign_data.sql
src/test/regress/sql/foreign_data.sql
+8
-3
No files found.
doc/src/sgml/catalogs.sgml
View file @
c4096c76
...
...
@@ -1157,6 +1157,15 @@
</entry>
</row>
<row>
<entry><structfield>attfdwoptions</structfield></entry>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
Attribute-level foreign data wrapper options, as <quote>keyword=value</> strings
</entry>
</row>
</tbody>
</tgroup>
</table>
...
...
doc/src/sgml/information_schema.sgml
View file @
c4096c76
...
...
@@ -1018,6 +1018,69 @@
</table>
</sect1>
<sect1 id="infoschema-column-options">
<title><literal>column_options</literal></title>
<para>
The view <literal>column_options</literal> contains all the
options defined for foreign table columns in the current database. Only
those foreign table columns are shown that the current user has access to
(by way of being the owner or having some privilege).
</para>
<table>
<title><literal>column_options</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>table_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that contains the foreign table (always the current database)</entry>
</row>
<row>
<entry><literal>table_schema</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the schema that contains the foreign table</entry>
</row>
<row>
<entry><literal>table_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign table</entry>
</row>
<row>
<entry><literal>column_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the column</entry>
</row>
<row>
<entry><literal>option_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of an option</entry>
</row>
<row>
<entry><literal>option_value</literal></entry>
<entry><type>character_data</type></entry>
<entry>Value of the option</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-column-privileges">
<title><literal>column_privileges</literal></title>
...
...
doc/src/sgml/ref/alter_foreign_table.sgml
View file @
c4096c76
...
...
@@ -36,6 +36,7 @@ ALTER FOREIGN TABLE <replaceable class="PARAMETER">name</replaceable>
DROP [ COLUMN ] [ IF EXISTS ] <replaceable class="PARAMETER">column</replaceable> [ RESTRICT | CASCADE ]
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">type</replaceable>
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> { SET | DROP } NOT NULL
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ])
OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ])
</synopsis>
...
...
@@ -125,12 +126,13 @@ ALTER FOREIGN TABLE <replaceable class="PARAMETER">name</replaceable>
<term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
Change options for the foreign table.
Change options for the foreign table
or one of its columns
.
<literal>ADD</>, <literal>SET</>, and <literal>DROP</>
specify the action to be performed. <literal>ADD</> is assumed
if no operation is explicitly specified. Option names must be
unique; names and values are also validated using the foreign
data wrapper library.
if no operation is explicitly specified. Duplicate option names are not
allowed (although it's OK for a table option and a column option to have
the same name). Option names and values are also validated using the
foreign data wrapper library.
</para>
</listitem>
</varlistentry>
...
...
doc/src/sgml/ref/create_foreign_table.sgml
View file @
c4096c76
...
...
@@ -19,7 +19,7 @@
<refsynopsisdiv>
<synopsis>
CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable> ( [
{ <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ NULL | NOT NULL ] }
{ <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [
OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ] [
NULL | NOT NULL ] }
[, ... ]
] )
SERVER <replaceable class="parameter">server_name</replaceable>
...
...
@@ -138,10 +138,12 @@ CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name
<term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ...] )</literal></term>
<listitem>
<para>
Options to be associated with the new foreign table.
Options to be associated with the new foreign table or one of its
columns.
The allowed option names and values are specific to each foreign
data wrapper and are validated using the foreign-data wrapper's
validator function. Option names must be unique.
validator function. Duplicate option names are not allowed (although
it's OK for a table option and a column option to have the same name).
</para>
</listitem>
</varlistentry>
...
...
doc/src/sgml/ref/psql-ref.sgml
View file @
c4096c76
...
...
@@ -891,6 +891,12 @@ testdb=>
below.)
</para>
<para>
For some types of relation, <literal>\d</> shows additional information
for each column: column values for sequences, indexed expression for
indexes and per-column foreign data wrapper options for foreign tables.
</para>
<para>
The command form <literal>\d+</literal> is identical, except that
more information is displayed: any comments associated with the
...
...
src/backend/access/common/tupdesc.c
View file @
c4096c76
...
...
@@ -363,7 +363,7 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return
false
;
if
(
attr1
->
attcollation
!=
attr2
->
attcollation
)
return
false
;
/* attacl
and att
options are not even present... */
/* attacl
, attoptions and attfdw
options are not even present... */
}
if
(
tupdesc1
->
constr
!=
NULL
)
...
...
@@ -483,7 +483,7 @@ TupleDescInitEntry(TupleDesc desc,
att
->
attisdropped
=
false
;
att
->
attislocal
=
true
;
att
->
attinhcount
=
0
;
/* attacl
and att
options are not present in tupledescs */
/* attacl
, attoptions and attfdw
options are not present in tupledescs */
tuple
=
SearchSysCache1
(
TYPEOID
,
ObjectIdGetDatum
(
oidtypeid
));
if
(
!
HeapTupleIsValid
(
tuple
))
...
...
src/backend/catalog/genbki.pl
View file @
c4096c76
...
...
@@ -369,7 +369,8 @@ sub emit_pgattr_row
attislocal
=>
'
t
',
attinhcount
=>
'
0
',
attacl
=>
'
_null_
',
attoptions
=>
'
_null_
'
attoptions
=>
'
_null_
',
attfdwoptions
=>
'
_null_
'
);
return
{
%
PGATTR_DEFAULTS
,
%
row
};
}
...
...
@@ -400,6 +401,7 @@ sub emit_schemapg_row
# Only the fixed-size portions of the descriptors are ever used.
delete
$row
->
{
attacl
};
delete
$row
->
{
attoptions
};
delete
$row
->
{
attfdwoptions
};
# Expand booleans from 'f'/'t' to 'false'/'true'.
# Some values might be other macros (eg FLOAT4PASSBYVAL), don't change.
...
...
src/backend/catalog/heap.c
View file @
c4096c76
...
...
@@ -126,7 +126,7 @@ static List *insert_ordered_unique_oid(List *list, Oid datum);
*/
/*
* The initializers below do not include t
he attoptions or attacl
fields,
* The initializers below do not include t
railing variable length
fields,
* but that's OK - we're never going to reference anything beyond the
* fixed-size portion of the structure anyway.
*/
...
...
@@ -620,6 +620,7 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
/* start out with empty permissions and empty options */
nulls
[
Anum_pg_attribute_attacl
-
1
]
=
true
;
nulls
[
Anum_pg_attribute_attoptions
-
1
]
=
true
;
nulls
[
Anum_pg_attribute_attfdwoptions
-
1
]
=
true
;
tup
=
heap_form_tuple
(
RelationGetDescr
(
pg_attribute_rel
),
values
,
nulls
);
...
...
src/backend/catalog/information_schema.sql
View file @
c4096c76
...
...
@@ -2534,6 +2534,39 @@ GRANT SELECT ON element_types TO PUBLIC;
-- SQL/MED views; these use section numbers from part 9 of the standard.
/* Base view for foreign table columns */
CREATE
VIEW
_pg_foreign_table_columns
AS
SELECT
n
.
nspname
,
c
.
relname
,
a
.
attname
,
a
.
attfdwoptions
FROM
pg_foreign_table
t
,
pg_authid
u
,
pg_namespace
n
,
pg_class
c
,
pg_attribute
a
WHERE
u
.
oid
=
c
.
relowner
AND
(
pg_has_role
(
c
.
relowner
,
'USAGE'
)
OR
has_column_privilege
(
c
.
oid
,
a
.
attnum
,
'SELECT, INSERT, UPDATE, REFERENCES'
))
AND
n
.
oid
=
c
.
relnamespace
AND
c
.
oid
=
t
.
ftrelid
AND
c
.
relkind
=
'f'
AND
a
.
attrelid
=
c
.
oid
AND
a
.
attnum
>
0
;
/*
* 24.2
* COLUMN_OPTIONS view
*/
CREATE
VIEW
column_options
AS
SELECT
CAST
(
current_database
()
AS
sql_identifier
)
AS
table_catalog
,
c
.
nspname
AS
table_schema
,
c
.
relname
AS
table_name
,
c
.
attname
AS
column_name
,
CAST
((
pg_options_to_table
(
c
.
attfdwoptions
)).
option_name
AS
sql_identifier
)
AS
option_name
,
CAST
((
pg_options_to_table
(
c
.
attfdwoptions
)).
option_value
AS
character_data
)
AS
option_value
FROM
_pg_foreign_table_columns
c
;
GRANT
SELECT
ON
column_options
TO
PUBLIC
;
/* Base view for foreign-data wrappers */
CREATE
VIEW
_pg_foreign_data_wrappers
AS
SELECT
w
.
oid
,
...
...
src/backend/commands/tablecmds.c
View file @
c4096c76
...
...
@@ -346,6 +346,8 @@ static void ATPrepAlterColumnType(List **wqueue,
static
bool
ATColumnChangeRequiresRewrite
(
Node
*
expr
,
AttrNumber
varattno
);
static
void
ATExecAlterColumnType
(
AlteredTableInfo
*
tab
,
Relation
rel
,
AlterTableCmd
*
cmd
,
LOCKMODE
lockmode
);
static
void
ATExecAlterColumnGenericOptions
(
Relation
rel
,
const
char
*
colName
,
List
*
options
,
LOCKMODE
lockmode
);
static
void
ATPostAlterTypeCleanup
(
List
**
wqueue
,
AlteredTableInfo
*
tab
,
LOCKMODE
lockmode
);
static
void
ATPostAlterTypeParse
(
Oid
oldId
,
char
*
cmd
,
List
**
wqueue
,
LOCKMODE
lockmode
,
bool
rewrite
);
...
...
@@ -2648,6 +2650,7 @@ AlterTableGetLockLevel(List *cmds)
case
AT_DropNotNull
:
/* may change some SQL plans */
case
AT_SetNotNull
:
case
AT_GenericOptions
:
case
AT_AlterColumnGenericOptions
:
cmd_lockmode
=
AccessExclusiveLock
;
break
;
...
...
@@ -2925,6 +2928,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
ATPrepAlterColumnType
(
wqueue
,
tab
,
rel
,
recurse
,
recursing
,
cmd
,
lockmode
);
pass
=
AT_PASS_ALTER_TYPE
;
break
;
case
AT_AlterColumnGenericOptions
:
ATSimplePermissions
(
rel
,
ATT_FOREIGN_TABLE
);
/* This command never recurses */
/* No command-specific prep needed */
pass
=
AT_PASS_MISC
;
break
;
case
AT_ChangeOwner
:
/* ALTER OWNER */
/* This command never recurses */
/* No command-specific prep needed */
...
...
@@ -3169,6 +3178,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case
AT_AlterColumnType
:
/* ALTER COLUMN TYPE */
ATExecAlterColumnType
(
tab
,
rel
,
cmd
,
lockmode
);
break
;
case
AT_AlterColumnGenericOptions
:
/* ALTER COLUMN OPTIONS */
ATExecAlterColumnGenericOptions
(
rel
,
cmd
->
name
,
(
List
*
)
cmd
->
def
,
lockmode
);
break
;
case
AT_ChangeOwner
:
/* ALTER OWNER */
ATExecChangeOwner
(
RelationGetRelid
(
rel
),
get_role_oid
(
cmd
->
name
,
false
),
...
...
@@ -7397,6 +7409,100 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
heap_freetuple
(
heapTup
);
}
static
void
ATExecAlterColumnGenericOptions
(
Relation
rel
,
const
char
*
colName
,
List
*
options
,
LOCKMODE
lockmode
)
{
Relation
ftrel
;
Relation
attrel
;
ForeignServer
*
server
;
ForeignDataWrapper
*
fdw
;
HeapTuple
tuple
;
HeapTuple
newtuple
;
bool
isnull
;
Datum
repl_val
[
Natts_pg_attribute
];
bool
repl_null
[
Natts_pg_attribute
];
bool
repl_repl
[
Natts_pg_attribute
];
Datum
datum
;
Form_pg_foreign_table
fttableform
;
Form_pg_attribute
atttableform
;
if
(
options
==
NIL
)
return
;
/* First, determine FDW validator associated to the foreign table. */
ftrel
=
heap_open
(
ForeignTableRelationId
,
AccessShareLock
);
tuple
=
SearchSysCache1
(
FOREIGNTABLEREL
,
rel
->
rd_id
);
if
(
!
HeapTupleIsValid
(
tuple
))
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"foreign table
\"
%s
\"
does not exist"
,
RelationGetRelationName
(
rel
))));
fttableform
=
(
Form_pg_foreign_table
)
GETSTRUCT
(
tuple
);
server
=
GetForeignServer
(
fttableform
->
ftserver
);
fdw
=
GetForeignDataWrapper
(
server
->
fdwid
);
heap_close
(
ftrel
,
AccessShareLock
);
ReleaseSysCache
(
tuple
);
attrel
=
heap_open
(
AttributeRelationId
,
RowExclusiveLock
);
tuple
=
SearchSysCacheAttName
(
RelationGetRelid
(
rel
),
colName
);
if
(
!
HeapTupleIsValid
(
tuple
))
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_COLUMN
),
errmsg
(
"column
\"
%s
\"
of relation
\"
%s
\"
does not exist"
,
colName
,
RelationGetRelationName
(
rel
))));
/* Prevent them from altering a system attribute */
atttableform
=
(
Form_pg_attribute
)
GETSTRUCT
(
tuple
);
if
(
atttableform
->
attnum
<=
0
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_FEATURE_NOT_SUPPORTED
),
errmsg
(
"cannot alter system column
\"
%s
\"
"
,
colName
)));
/* Initialize buffers for new tuple values */
memset
(
repl_val
,
0
,
sizeof
(
repl_val
));
memset
(
repl_null
,
false
,
sizeof
(
repl_null
));
memset
(
repl_repl
,
false
,
sizeof
(
repl_repl
));
/* Extract the current options */
datum
=
SysCacheGetAttr
(
ATTNAME
,
tuple
,
Anum_pg_attribute_attfdwoptions
,
&
isnull
);
if
(
isnull
)
datum
=
PointerGetDatum
(
NULL
);
/* Transform the options */
datum
=
transformGenericOptions
(
AttributeRelationId
,
datum
,
options
,
fdw
->
fdwvalidator
);
if
(
PointerIsValid
(
DatumGetPointer
(
datum
)))
repl_val
[
Anum_pg_attribute_attfdwoptions
-
1
]
=
datum
;
else
repl_null
[
Anum_pg_attribute_attfdwoptions
-
1
]
=
true
;
repl_repl
[
Anum_pg_attribute_attfdwoptions
-
1
]
=
true
;
/* Everything looks good - update the tuple */
newtuple
=
heap_modify_tuple
(
tuple
,
RelationGetDescr
(
attrel
),
repl_val
,
repl_null
,
repl_repl
);
ReleaseSysCache
(
tuple
);
simple_heap_update
(
attrel
,
&
newtuple
->
t_self
,
newtuple
);
CatalogUpdateIndexes
(
attrel
,
newtuple
);
heap_close
(
attrel
,
RowExclusiveLock
);
heap_freetuple
(
newtuple
);
}
/*
* Cleanup after we've finished all the ALTER TYPE operations for a
* particular relation. We have to drop and recreate all the indexes
...
...
src/backend/nodes/copyfuncs.c
View file @
c4096c76
...
...
@@ -2312,6 +2312,7 @@ _copyColumnDef(ColumnDef *from)
COPY_NODE_FIELD
(
collClause
);
COPY_SCALAR_FIELD
(
collOid
);
COPY_NODE_FIELD
(
constraints
);
COPY_NODE_FIELD
(
fdwoptions
);
return
newnode
;
}
...
...
src/backend/nodes/outfuncs.c
View file @
c4096c76
...
...
@@ -2102,6 +2102,7 @@ _outColumnDef(StringInfo str, ColumnDef *node)
WRITE_NODE_FIELD
(
collClause
);
WRITE_OID_FIELD
(
collOid
);
WRITE_NODE_FIELD
(
constraints
);
WRITE_NODE_FIELD
(
fdwoptions
);
}
static
void
...
...
src/backend/parser/gram.y
View file @
c4096c76
...
...
@@ -1769,6 +1769,15 @@ alter_table_cmd:
def->raw_default = $8;
$$ = (Node *)n;
}
/* ALTER FOREIGN TABLE <name> ALTER [COLUMN] <colname> OPTIONS */
| ALTER opt_column ColId alter_generic_options
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AlterColumnGenericOptions;
n->name = $3;
n->def = (Node *) $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ADD CONSTRAINT ... */
| ADD_P TableConstraint
{
...
...
@@ -2497,7 +2506,7 @@ TypedTableElement:
| TableConstraint { $$ = $1; }
;
columnDef: ColId Typename ColQualList
columnDef: ColId Typename
create_generic_options
ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
...
...
@@ -2510,7 +2519,8 @@ columnDef: ColId Typename ColQualList
n->raw_default = NULL;
n->cooked_default = NULL;
n->collOid = InvalidOid;
SplitColQualList($3, &n->constraints, &n->collClause,
n->fdwoptions = $3;
SplitColQualList($4, &n->constraints, &n->collClause,
yyscanner);
$$ = (Node *)n;
}
...
...
src/backend/parser/parse_utilcmd.c
View file @
c4096c76
...
...
@@ -559,6 +559,31 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
break
;
}
}
/*
* Generate ALTER FOREIGN TABLE ALTER COLUMN statement which adds
* per-column foreign data wrapper options for this column.
*/
if
(
column
->
fdwoptions
!=
NIL
)
{
AlterTableStmt
*
stmt
;
AlterTableCmd
*
cmd
;
cmd
=
makeNode
(
AlterTableCmd
);
cmd
->
subtype
=
AT_AlterColumnGenericOptions
;
cmd
->
name
=
column
->
colname
;
cmd
->
def
=
(
Node
*
)
column
->
fdwoptions
;
cmd
->
behavior
=
DROP_RESTRICT
;
cmd
->
missing_ok
=
false
;
stmt
=
makeNode
(
AlterTableStmt
);
stmt
->
relation
=
cxt
->
relation
;
stmt
->
cmds
=
NIL
;
stmt
->
relkind
=
OBJECT_FOREIGN_TABLE
;
stmt
->
cmds
=
lappend
(
stmt
->
cmds
,
cmd
);
cxt
->
alist
=
lappend
(
cxt
->
alist
,
stmt
);
}
}
/*
...
...
src/bin/pg_dump/pg_dump.c
View file @
c4096c76
...
...
@@ -5574,6 +5574,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
int
i_attislocal
;
int
i_attoptions
;
int
i_attcollation
;
int
i_attfdwoptions
;
PGresult
*
res
;
int
ntups
;
bool
hasdefaults
;
...
...
@@ -5611,7 +5612,31 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
resetPQExpBuffer
(
q
);
if
(
g_fout
->
remoteVersion
>=
90100
)
if
(
g_fout
->
remoteVersion
>=
90200
)
{
/*
* attfdwoptions is new in 9.2.
*/
appendPQExpBuffer
(
q
,
"SELECT a.attnum, a.attname, a.atttypmod, "
"a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"array_to_string(a.attoptions, ', ') AS attoptions, "
"CASE WHEN a.attcollation <> t.typcollation "
"THEN a.attcollation ELSE 0 END AS attcollation, "
"array_to_string(ARRAY("
" SELECT option_name || ' ' || quote_literal(option_value) "
" FROM pg_options_to_table(attfdwoptions)), ', ') "
" AS attfdwoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
"AND a.attnum > 0::pg_catalog.int2 "
"ORDER BY a.attrelid, a.attnum"
,
tbinfo
->
dobj
.
catId
.
oid
);
}
else
if
(
g_fout
->
remoteVersion
>=
90100
)
{
/*
* attcollation is new in 9.1. Since we only want to dump COLLATE
...
...
@@ -5626,7 +5651,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"array_to_string(a.attoptions, ', ') AS attoptions, "
"CASE WHEN a.attcollation <> t.typcollation "
"THEN a.attcollation ELSE 0 END AS attcollation "
"THEN a.attcollation ELSE 0 END AS attcollation, "
"NULL AS attfdwoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
...
...
@@ -5643,7 +5669,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"array_to_string(a.attoptions, ', ') AS attoptions, "
"0 AS attcollation "
"0 AS attcollation, "
"NULL AS attfdwoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
...
...
@@ -5659,7 +5686,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"'' AS attoptions, 0 AS attcollation "
"'' AS attoptions, 0 AS attcollation, "
"NULL AS attfdwoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
...
...
@@ -5680,7 +5708,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"false AS attisdropped, a.attlen, "
"a.attalign, false AS attislocal, "
"format_type(t.oid,a.atttypmod) AS atttypname, "
"'' AS attoptions, 0 AS attcollation "
"'' AS attoptions, 0 AS attcollation, "
"NULL AS attfdwoptions "
"FROM pg_attribute a LEFT JOIN pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::oid "
...
...
@@ -5698,7 +5727,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"attlen, attalign, "
"false AS attislocal, "
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
"'' AS attoptions, 0 AS attcollation "
"'' AS attoptions, 0 AS attcollation, "
"NULL AS attfdwoptions "
"FROM pg_attribute a "
"WHERE attrelid = '%u'::oid "
"AND attnum > 0::int2 "
...
...
@@ -5726,6 +5756,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
i_attislocal
=
PQfnumber
(
res
,
"attislocal"
);
i_attoptions
=
PQfnumber
(
res
,
"attoptions"
);
i_attcollation
=
PQfnumber
(
res
,
"attcollation"
);
i_attfdwoptions
=
PQfnumber
(
res
,
"attfdwoptions"
);
tbinfo
->
numatts
=
ntups
;
tbinfo
->
attnames
=
(
char
**
)
malloc
(
ntups
*
sizeof
(
char
*
));
...
...
@@ -5742,6 +5773,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo
->
attrdefs
=
(
AttrDefInfo
**
)
malloc
(
ntups
*
sizeof
(
AttrDefInfo
*
));
tbinfo
->
attoptions
=
(
char
**
)
malloc
(
ntups
*
sizeof
(
char
*
));
tbinfo
->
attcollation
=
(
Oid
*
)
malloc
(
ntups
*
sizeof
(
Oid
));
tbinfo
->
attfdwoptions
=
(
char
**
)
malloc
(
ntups
*
sizeof
(
char
*
));
tbinfo
->
inhAttrs
=
(
bool
*
)
malloc
(
ntups
*
sizeof
(
bool
));
tbinfo
->
inhAttrDef
=
(
bool
*
)
malloc
(
ntups
*
sizeof
(
bool
));
tbinfo
->
inhNotNull
=
(
bool
*
)
malloc
(
ntups
*
sizeof
(
bool
));
...
...
@@ -5768,6 +5800,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo
->
notnull
[
j
]
=
(
PQgetvalue
(
res
,
j
,
i_attnotnull
)[
0
]
==
't'
);
tbinfo
->
attoptions
[
j
]
=
strdup
(
PQgetvalue
(
res
,
j
,
i_attoptions
));
tbinfo
->
attcollation
[
j
]
=
atooid
(
PQgetvalue
(
res
,
j
,
i_attcollation
));
tbinfo
->
attfdwoptions
[
j
]
=
strdup
(
PQgetvalue
(
res
,
j
,
i_attfdwoptions
));
tbinfo
->
attrdefs
[
j
]
=
NULL
;
/* fix below */
if
(
PQgetvalue
(
res
,
j
,
i_atthasdef
)[
0
]
==
't'
)
hasdefaults
=
true
;
...
...
@@ -12469,6 +12502,21 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBuffer
(
q
,
"SET (%s);
\n
"
,
tbinfo
->
attoptions
[
j
]);
}
/*
* Dump per-column fdw options.
*/
if
(
tbinfo
->
relkind
==
RELKIND_FOREIGN_TABLE
&&
tbinfo
->
attfdwoptions
[
j
]
&&
tbinfo
->
attfdwoptions
[
j
][
0
]
!=
'\0'
)
{
appendPQExpBuffer
(
q
,
"ALTER FOREIGN TABLE %s "
,
fmtId
(
tbinfo
->
dobj
.
name
));
appendPQExpBuffer
(
q
,
"ALTER COLUMN %s "
,
fmtId
(
tbinfo
->
attnames
[
j
]));
appendPQExpBuffer
(
q
,
"OPTIONS (%s);
\n
"
,
tbinfo
->
attfdwoptions
[
j
]);
}
}
}
...
...
src/bin/pg_dump/pg_dump.h
View file @
c4096c76
...
...
@@ -275,6 +275,7 @@ typedef struct _tableInfo
bool
*
attislocal
;
/* true if attr has local definition */
char
**
attoptions
;
/* per-attribute options */
Oid
*
attcollation
;
/* per-attribute collation selection */
char
**
attfdwoptions
;
/* per-attribute fdw options */
/*
* Note: we need to store per-attribute notnull, default, and constraint
...
...
src/bin/psql/describe.c
View file @
c4096c76
...
...
@@ -1281,7 +1281,12 @@ describeOneTableDetails(const char *schemaname,
res
=
NULL
;
}
/* Get column info */
/*
* Get column info
*
* You need to modify value of "firstvcol" which willbe defined below if
* you are adding column(s) preceding to verbose-only columns.
*/
printfPQExpBuffer
(
&
buf
,
"SELECT a.attname,"
);
appendPQExpBuffer
(
&
buf
,
"
\n
pg_catalog.format_type(a.atttypid, a.atttypmod),"
"
\n
(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)"
...
...
@@ -1295,6 +1300,12 @@ describeOneTableDetails(const char *schemaname,
appendPQExpBuffer
(
&
buf
,
"
\n
NULL AS attcollation"
);
if
(
tableinfo
.
relkind
==
'i'
)
appendPQExpBuffer
(
&
buf
,
",
\n
pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef"
);
else
appendPQExpBuffer
(
&
buf
,
",
\n
NULL AS indexdef"
);
if
(
tableinfo
.
relkind
==
'f'
&&
pset
.
sversion
>=
90200
)
appendPQExpBuffer
(
&
buf
,
",
\n
a.attfdwoptions"
);
else
appendPQExpBuffer
(
&
buf
,
",
\n
NULL AS attfdwoptions"
);
if
(
verbose
)
{
appendPQExpBuffer
(
&
buf
,
",
\n
a.attstorage"
);
...
...
@@ -1386,6 +1397,9 @@ describeOneTableDetails(const char *schemaname,
if
(
tableinfo
.
relkind
==
'i'
)
headers
[
cols
++
]
=
gettext_noop
(
"Definition"
);
if
(
tableinfo
.
relkind
==
'f'
&&
pset
.
sversion
>=
90200
)
headers
[
cols
++
]
=
gettext_noop
(
"Options"
);
if
(
verbose
)
{
headers
[
cols
++
]
=
gettext_noop
(
"Storage"
);
...
...
@@ -1471,10 +1485,14 @@ describeOneTableDetails(const char *schemaname,
if
(
tableinfo
.
relkind
==
'i'
)
printTableAddCell
(
&
cont
,
PQgetvalue
(
res
,
i
,
6
),
false
,
false
);
/* FDW options for foreign table column, only for 9.2 or later */
if
(
tableinfo
.
relkind
==
'f'
&&
pset
.
sversion
>=
90200
)
printTableAddCell
(
&
cont
,
PQgetvalue
(
res
,
i
,
7
),
false
,
false
);
/* Storage and Description */
if
(
verbose
)
{
int
firstvcol
=
(
tableinfo
.
relkind
==
'i'
?
7
:
6
)
;
int
firstvcol
=
8
;
char
*
storage
=
PQgetvalue
(
res
,
i
,
firstvcol
);
/* these strings are literal in our syntax, so not translated. */
...
...
src/include/catalog/catversion.h
View file @
c4096c76
...
...
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 20110
720
1
#define CATALOG_VERSION_NO 20110
805
1
#endif
src/include/catalog/pg_attribute.h
View file @
c4096c76
...
...
@@ -156,6 +156,9 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
/* Column-level options */
text
attoptions
[
1
];
/* Column-level FDW options */
text
attfdwoptions
[
1
];
}
FormData_pg_attribute
;
/*
...
...
@@ -179,7 +182,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
* ----------------
*/
#define Natts_pg_attribute 2
0
#define Natts_pg_attribute 2
1
#define Anum_pg_attribute_attrelid 1
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
...
...
@@ -200,6 +203,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
#define Anum_pg_attribute_attcollation 18
#define Anum_pg_attribute_attacl 19
#define Anum_pg_attribute_attoptions 20
#define Anum_pg_attribute_attfdwoptions 21
/* ----------------
...
...
src/include/catalog/pg_class.h
View file @
c4096c76
...
...
@@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class;
/* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA
(
insert
OID
=
1247
(
pg_type
PGNSP
71
0
PGUID
0
0
0
0
0
0
0
f
f
p
r
29
0
t
f
f
f
f
3
_null_
_null_
));
DESCR
(
""
);
DATA
(
insert
OID
=
1249
(
pg_attribute
PGNSP
75
0
PGUID
0
0
0
0
0
0
0
f
f
p
r
2
0
0
f
f
f
f
f
3
_null_
_null_
));
DATA
(
insert
OID
=
1249
(
pg_attribute
PGNSP
75
0
PGUID
0
0
0
0
0
0
0
f
f
p
r
2
1
0
f
f
f
f
f
3
_null_
_null_
));
DESCR
(
""
);
DATA
(
insert
OID
=
1255
(
pg_proc
PGNSP
81
0
PGUID
0
0
0
0
0
0
0
f
f
p
r
26
0
t
f
f
f
f
3
_null_
_null_
));
DESCR
(
""
);
...
...
src/include/nodes/parsenodes.h
View file @
c4096c76
...
...
@@ -500,6 +500,7 @@ typedef struct ColumnDef
CollateClause
*
collClause
;
/* untransformed COLLATE spec, if any */
Oid
collOid
;
/* collation OID (InvalidOid if not set) */
List
*
constraints
;
/* other constraints on column */
List
*
fdwoptions
;
/* per-column FDW options */
}
ColumnDef
;
/*
...
...
@@ -1197,6 +1198,7 @@ typedef enum AlterTableType
AT_DropConstraint
,
/* drop constraint */
AT_DropConstraintRecurse
,
/* internal to commands/tablecmds.c */
AT_AlterColumnType
,
/* alter column type */
AT_AlterColumnGenericOptions
,
/* alter column OPTIONS (...) */
AT_ChangeOwner
,
/* change owner */
AT_ClusterOn
,
/* CLUSTER ON */
AT_DropCluster
,
/* SET WITHOUT CLUSTER */
...
...
src/test/regress/expected/foreign_data.out
View file @
c4096c76
...
...
@@ -646,19 +646,19 @@ ERROR: syntax error at or near "WITH OIDS"
LINE 1: CREATE FOREIGN TABLE ft1 () SERVER sc WITH OIDS;
^
CREATE FOREIGN TABLE ft1 (
c1 integer NOT NULL,
c2 text,
c1 integer
OPTIONS (param1 'val1')
NOT NULL,
c2 text
OPTIONS (param2 'val2', param3 'val3')
,
c3 date
) SERVER sc OPTIONS (delimiter ',', quote '"');
COMMENT ON FOREIGN TABLE ft1 IS 'ft1';
COMMENT ON COLUMN ft1.c1 IS 'ft1.c1';
\d+ ft1
Foreign table "public.ft1"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+----------+-------------
c1 | integer | not null | plain | ft1.c1
c2 | text | | extended |
c3 | date | | plain |
Column | Type | Modifiers |
Options |
Storage | Description
--------+---------+-----------+----------
-----------------+----------
+-------------
c1 | integer | not null |
{param1=val1} |
plain | ft1.c1
c2 | text | |
{param2=val2,param3=val3} |
extended |
c3 | date | |
|
plain |
Server: sc
Has OIDs: no
...
...
@@ -687,7 +687,7 @@ ALTER FOREIGN TABLE ft1 ADD COLUMN c6 integer;
ALTER FOREIGN TABLE ft1 ADD COLUMN c7 integer NOT NULL;
ALTER FOREIGN TABLE ft1 ADD COLUMN c8 integer;
ALTER FOREIGN TABLE ft1 ADD COLUMN c9 integer;
ALTER FOREIGN TABLE ft1 ADD COLUMN c10 integer;
ALTER FOREIGN TABLE ft1 ADD COLUMN c10 integer
OPTIONS (p1 'v1')
;
ALTER FOREIGN TABLE ft1 ALTER COLUMN c4 SET DEFAULT 0; -- ERROR
ERROR: "ft1" is not a table or view
ALTER FOREIGN TABLE ft1 ALTER COLUMN c5 DROP DEFAULT; -- ERROR
...
...
@@ -698,6 +698,27 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10) USING '0'; -- ERROR
ERROR: "ft1" is not a table
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10);
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET DATA TYPE text;
ALTER FOREIGN TABLE ft1 ALTER COLUMN xmin OPTIONS (ADD p1 'v1'); -- ERROR
ERROR: cannot alter system column "xmin"
ALTER FOREIGN TABLE ft1 ALTER COLUMN c7 OPTIONS (ADD p1 'v1', ADD p2 'v2'),
ALTER COLUMN c8 OPTIONS (ADD p1 'v1', ADD p2 'v2');
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 OPTIONS (SET p2 'V2', DROP p1);
\d+ ft1
Foreign table "public.ft1"
Column | Type | Modifiers | Options | Storage | Description
--------+---------+-----------+---------------------------+----------+-------------
c1 | integer | not null | {param1=val1} | plain |
c2 | text | | {param2=val2,param3=val3} | extended |
c3 | date | | | plain |
c4 | integer | | | plain |
c6 | integer | not null | | plain |
c7 | integer | | {p1=v1,p2=v2} | plain |
c8 | text | | {p2=V2} | extended |
c9 | integer | | | plain |
c10 | integer | | {p1=v1} | plain |
Server: sc
Has OIDs: no
-- can't change the column type if it's used elsewhere
CREATE TABLE use_ft1_column_type (x ft1);
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET DATA TYPE integer; -- ERROR
...
...
@@ -726,17 +747,17 @@ ERROR: relation "ft1" does not exist
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME c1 TO foreign_column_1;
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1;
\d foreign_schema.foreign_table_1
Foreign table "foreign_schema.foreign_table_1"
Column | Type | Modifiers
------------------+---------+-----------
foreign_column_1 | integer | not null
c2 | text |
c3 | date |
c4 | integer |
c6 | integer | not null
c7 | integer |
c8 | text |
c10 | integer |
Foreign table "foreign_schema.foreign_table_1"
Column | Type | Modifiers
| Options
------------------+---------+-----------
+---------------------------
foreign_column_1 | integer | not null
| {param1=val1}
c2 | text |
| {param2=val2,param3=val3}
c3 | date |
|
c4 | integer |
|
c6 | integer | not null
|
c7 | integer |
| {p1=v1,p2=v2}
c8 | text |
| {p2=V2}
c10 | integer |
| {p1=v1}
Server: sc
-- Information schema
...
...
src/test/regress/sql/foreign_data.sql
View file @
c4096c76
...
...
@@ -264,8 +264,8 @@ CREATE FOREIGN TABLE ft1 () SERVER no_server; -- ERROR
CREATE
FOREIGN
TABLE
ft1
(
c1
serial
)
SERVER
sc
;
-- ERROR
CREATE
FOREIGN
TABLE
ft1
()
SERVER
sc
WITH
OIDS
;
-- ERROR
CREATE
FOREIGN
TABLE
ft1
(
c1
integer
NOT
NULL
,
c2
text
,
c1
integer
OPTIONS
(
param1
'val1'
)
NOT
NULL
,
c2
text
OPTIONS
(
param2
'val2'
,
param3
'val3'
)
,
c3
date
)
SERVER
sc
OPTIONS
(
delimiter
','
,
quote
'"'
);
COMMENT
ON
FOREIGN
TABLE
ft1
IS
'ft1'
;
...
...
@@ -288,7 +288,7 @@ ALTER FOREIGN TABLE ft1 ADD COLUMN c6 integer;
ALTER
FOREIGN
TABLE
ft1
ADD
COLUMN
c7
integer
NOT
NULL
;
ALTER
FOREIGN
TABLE
ft1
ADD
COLUMN
c8
integer
;
ALTER
FOREIGN
TABLE
ft1
ADD
COLUMN
c9
integer
;
ALTER
FOREIGN
TABLE
ft1
ADD
COLUMN
c10
integer
;
ALTER
FOREIGN
TABLE
ft1
ADD
COLUMN
c10
integer
OPTIONS
(
p1
'v1'
)
;
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c4
SET
DEFAULT
0
;
-- ERROR
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c5
DROP
DEFAULT
;
-- ERROR
...
...
@@ -297,6 +297,11 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c7 DROP NOT NULL;
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c8
TYPE
char
(
10
)
USING
'0'
;
-- ERROR
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c8
TYPE
char
(
10
);
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c8
SET
DATA
TYPE
text
;
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
xmin
OPTIONS
(
ADD
p1
'v1'
);
-- ERROR
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c7
OPTIONS
(
ADD
p1
'v1'
,
ADD
p2
'v2'
),
ALTER
COLUMN
c8
OPTIONS
(
ADD
p1
'v1'
,
ADD
p2
'v2'
);
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c8
OPTIONS
(
SET
p2
'V2'
,
DROP
p1
);
\
d
+
ft1
-- can't change the column type if it's used elsewhere
CREATE
TABLE
use_ft1_column_type
(
x
ft1
);
ALTER
FOREIGN
TABLE
ft1
ALTER
COLUMN
c8
SET
DATA
TYPE
integer
;
-- ERROR
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment