Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita0c6dfe

Browse files
committed
Allow default expressions to be attached to columns of foreign tables.
There's still some discussion about exactly how postgres_fdw ought tohandle this case, but there seems no debate that we want to allow defaultsto be used for inserts into foreign tables. So remove the core-coderestrictions that prevented it.While at it, get rid of the special grammar productions for CREATE FOREIGNTABLE, and instead add explicit FEATURE_NOT_SUPPORTED error checks for thedisallowed cases. This makes the grammar a shade smaller, and moreimportantly results in much more intelligible error messages forunsupported cases. It's also one less thing to fix if we ever startsupporting constraints on foreign tables.
1 parent1ba0119 commita0c6dfe

File tree

7 files changed

+123
-64
lines changed

7 files changed

+123
-64
lines changed

‎doc/src/sgml/ref/alter_foreign_table.sgml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceab
3232

3333
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
3434

35-
ADD [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [NULL | NOT NULL ]
35+
ADD [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [COLLATE <replaceable class="PARAMETER">collation</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
3636
DROP [ COLUMN ] [ IF EXISTS ] <replaceable class="PARAMETER">column_name</replaceable> [ RESTRICT | CASCADE ]
3737
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable>
38+
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> SET DEFAULT <replaceable class="PARAMETER">expression</replaceable>
39+
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> DROP DEFAULT
3840
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> { SET | DROP } NOT NULL
3941
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> SET STATISTICS <replaceable class="PARAMETER">integer</replaceable>
4042
ALTER [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> SET ( <replaceable class="PARAMETER">attribute_option</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
@@ -59,6 +61,9 @@ ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceab
5961
<para>
6062
This form adds a new column to the foreign table, using the same syntax as
6163
<xref linkend="SQL-CREATEFOREIGNTABLE">.
64+
Unlike the case when adding a column to a regular table, nothing happens
65+
to the underlying storage: this action simply declares that
66+
some new column is now accessible through the foreign table.
6267
</para>
6368
</listitem>
6469
</varlistentry>
@@ -97,6 +102,18 @@ ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceab
97102
</listitem>
98103
</varlistentry>
99104

105+
<varlistentry>
106+
<term><literal>SET</literal>/<literal>DROP DEFAULT</literal></term>
107+
<listitem>
108+
<para>
109+
These forms set or remove the default value for a column.
110+
Default values only apply in subsequent <command>INSERT</command>
111+
or <command>UPDATE</> commands; they do not cause rows already in the
112+
table to change.
113+
</para>
114+
</listitem>
115+
</varlistentry>
116+
100117
<varlistentry>
101118
<term><literal>SET</literal>/<literal>DROP NOT NULL</literal></term>
102119
<listitem>

‎doc/src/sgml/ref/create_foreign_table.sgml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@
1919
<refsynopsisdiv>
2020
<synopsis>
2121
CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable> ( [
22-
{<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 ] }
22+
<replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ] [COLLATE <replaceable>collation</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
2323
[, ... ]
2424
] )
2525
SERVER <replaceable class="parameter">server_name</replaceable>
2626
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
2727

28+
<phrase>where <replaceable class="PARAMETER">column_constraint</replaceable> is:</phrase>
29+
30+
[ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
31+
{ NOT NULL |
32+
NULL |
33+
DEFAULT <replaceable>default_expr</replaceable> }
2834
</synopsis>
2935
</refsynopsisdiv>
3036

@@ -131,6 +137,27 @@ CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name
131137
</listitem>
132138
</varlistentry>
133139

140+
<varlistentry>
141+
<term><literal>DEFAULT
142+
<replaceable>default_expr</replaceable></literal></term>
143+
<listitem>
144+
<para>
145+
The <literal>DEFAULT</> clause assigns a default data value for
146+
the column whose column definition it appears within. The value
147+
is any variable-free expression (subqueries and cross-references
148+
to other columns in the current table are not allowed). The
149+
data type of the default expression must match the data type of the
150+
column.
151+
</para>
152+
153+
<para>
154+
The default expression will be used in any insert operation that
155+
does not specify a value for the column. If there is no default
156+
for a column, then the default is null.
157+
</para>
158+
</listitem>
159+
</varlistentry>
160+
134161
<varlistentry>
135162
<term><replaceable class="PARAMETER">server_name</replaceable></term>
136163
<listitem>
@@ -190,6 +217,8 @@ SERVER film_server;
190217
<acronym>SQL</acronym> standard; however, much as with
191218
<link linkend="sql-createtable"><command>CREATE TABLE</></link>,
192219
<literal>NULL</> constraints and zero-column foreign tables are permitted.
220+
The ability to specify a default value is also a <productname>PostgreSQL</>
221+
extension.
193222
</para>
194223

195224
</refsect1>

‎src/backend/commands/tablecmds.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
465465
if (stmt->constraints!=NIL&&relkind==RELKIND_FOREIGN_TABLE)
466466
ereport(ERROR,
467467
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
468-
errmsg("constraintson foreign tablesare not supported")));
468+
errmsg("constraints are not supported on foreign tables")));
469469

470470
/*
471471
* Look up the namespace in which we are supposed to create the relation,
@@ -588,11 +588,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
588588
{
589589
RawColumnDefault*rawEnt;
590590

591-
if (relkind==RELKIND_FOREIGN_TABLE)
592-
ereport(ERROR,
593-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
594-
errmsg("default values on foreign tables are not supported")));
595-
596591
Assert(colDef->cooked_default==NULL);
597592

598593
rawEnt= (RawColumnDefault*)palloc(sizeof(RawColumnDefault));
@@ -2978,7 +2973,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
29782973
* substitutes default values into INSERTs before it expands
29792974
* rules.
29802975
*/
2981-
ATSimplePermissions(rel,ATT_TABLE |ATT_VIEW);
2976+
ATSimplePermissions(rel,ATT_TABLE |ATT_VIEW |ATT_FOREIGN_TABLE);
29822977
ATSimpleRecursion(wqueue,rel,cmd,recurse,lockmode);
29832978
/* No command-specific prep needed */
29842979
pass=cmd->def ?AT_PASS_ADD_CONSTR :AT_PASS_DROP;
@@ -4528,11 +4523,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
45284523
{
45294524
RawColumnDefault*rawEnt;
45304525

4531-
if (relkind==RELKIND_FOREIGN_TABLE)
4532-
ereport(ERROR,
4533-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
4534-
errmsg("default values on foreign tables are not supported")));
4535-
45364526
rawEnt= (RawColumnDefault*)palloc(sizeof(RawColumnDefault));
45374527
rawEnt->attnum=attribute.attnum;
45384528
rawEnt->raw_default=copyObject(colDef->raw_default);

‎src/backend/parser/gram.y

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
330330
%type<list>stmtblockstmtmulti
331331
OptTableElementListTableElementListOptInheritdefinition
332332
OptTypedTableElementListTypedTableElementList
333-
OptForeignTableElementListForeignTableElementList
334333
reloptionsopt_reloptions
335334
OptWithopt_distinctopt_definitionfunc_argsfunc_args_list
336335
func_args_with_defaultsfunc_args_with_defaults_list
@@ -408,7 +407,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
408407
%type<vsetstmt>set_restset_rest_moreSetResetClauseFunctionSetResetClause
409408

410409
%type<node>TableElementTypedTableElementConstraintElemTableFuncElement
411-
ForeignTableElement
412410
%type<node>columnDefcolumnOptions
413411
%type<defelt>def_elemreloption_elemold_aggr_elem
414412
%type<node>def_argcolumnElemwhere_clausewhere_or_current_clause
@@ -4137,57 +4135,37 @@ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_o
41374135

41384136
CreateForeignTableStmt:
41394137
CREATEFOREIGNTABLEqualified_name
4140-
OptForeignTableElementList
4138+
'('OptTableElementList')'
41414139
SERVERnamecreate_generic_options
41424140
{
41434141
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
41444142
$4->relpersistence = RELPERSISTENCE_PERMANENT;
41454143
n->base.relation =$4;
4146-
n->base.tableElts =$5;
4144+
n->base.tableElts =$6;
41474145
n->base.inhRelations = NIL;
41484146
n->base.if_not_exists =false;
41494147
/* FDW-specific data*/
4150-
n->servername =$7;
4151-
n->options =$8;
4148+
n->servername =$9;
4149+
n->options =$10;
41524150
$$ = (Node *) n;
41534151
}
41544152
|CREATEFOREIGNTABLEIF_PNOTEXISTSqualified_name
4155-
OptForeignTableElementList
4153+
'('OptTableElementList')'
41564154
SERVERnamecreate_generic_options
41574155
{
41584156
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
41594157
$7->relpersistence = RELPERSISTENCE_PERMANENT;
41604158
n->base.relation =$7;
4161-
n->base.tableElts =$8;
4159+
n->base.tableElts =$9;
41624160
n->base.inhRelations = NIL;
41634161
n->base.if_not_exists =true;
41644162
/* FDW-specific data*/
4165-
n->servername =$10;
4166-
n->options =$11;
4163+
n->servername =$12;
4164+
n->options =$13;
41674165
$$ = (Node *) n;
41684166
}
41694167
;
41704168

4171-
OptForeignTableElementList:
4172-
'('ForeignTableElementList')'{$$ =$2; }
4173-
|'('')'{$$ = NIL; }
4174-
;
4175-
4176-
ForeignTableElementList:
4177-
ForeignTableElement
4178-
{
4179-
$$ = list_make1($1);
4180-
}
4181-
|ForeignTableElementList','ForeignTableElement
4182-
{
4183-
$$ = lappend($1,$3);
4184-
}
4185-
;
4186-
4187-
ForeignTableElement:
4188-
columnDef{$$ =$1; }
4189-
;
4190-
41914169
/*****************************************************************************
41924170
*
41934171
*QUERY:

‎src/backend/parser/parse_utilcmd.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct
7070
RangeVar*relation;/* relation to create */
7171
Relationrel;/* opened/locked rel, if ALTER */
7272
List*inhRelations;/* relations to inherit from */
73+
boolisforeign;/* true if CREATE/ALTER FOREIGN TABLE */
7374
boolisalter;/* true if altering existing table */
7475
boolhasoids;/* does relation have an OID column? */
7576
List*columns;/* ColumnDef items */
@@ -195,9 +196,15 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
195196

196197
cxt.pstate=pstate;
197198
if (IsA(stmt,CreateForeignTableStmt))
199+
{
198200
cxt.stmtType="CREATE FOREIGN TABLE";
201+
cxt.isforeign= true;
202+
}
199203
else
204+
{
200205
cxt.stmtType="CREATE TABLE";
206+
cxt.isforeign= false;
207+
}
201208
cxt.relation=stmt->relation;
202209
cxt.rel=NULL;
203210
cxt.inhRelations=stmt->inhRelations;
@@ -515,11 +522,23 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
515522
break;
516523

517524
caseCONSTR_CHECK:
525+
if (cxt->isforeign)
526+
ereport(ERROR,
527+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
528+
errmsg("constraints are not supported on foreign tables"),
529+
parser_errposition(cxt->pstate,
530+
constraint->location)));
518531
cxt->ckconstraints=lappend(cxt->ckconstraints,constraint);
519532
break;
520533

521534
caseCONSTR_PRIMARY:
522535
caseCONSTR_UNIQUE:
536+
if (cxt->isforeign)
537+
ereport(ERROR,
538+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
539+
errmsg("constraints are not supported on foreign tables"),
540+
parser_errposition(cxt->pstate,
541+
constraint->location)));
523542
if (constraint->keys==NIL)
524543
constraint->keys=list_make1(makeString(column->colname));
525544
cxt->ixconstraints=lappend(cxt->ixconstraints,constraint);
@@ -531,7 +550,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
531550
break;
532551

533552
caseCONSTR_FOREIGN:
534-
553+
if (cxt->isforeign)
554+
ereport(ERROR,
555+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
556+
errmsg("constraints are not supported on foreign tables"),
557+
parser_errposition(cxt->pstate,
558+
constraint->location)));
535559
/*
536560
* Fill in the current attribute's name and throw it into the
537561
* list of FK constraints to be processed later.
@@ -555,8 +579,8 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
555579
}
556580

557581
/*
558-
*GenerateALTER FOREIGN TABLE ALTER COLUMN statementwhich adds
559-
* per-column foreign data wrapper optionsfor this column.
582+
*If needed, generateALTER FOREIGN TABLE ALTER COLUMN statementto add
583+
* per-column foreign data wrapper optionsto this column after creation.
560584
*/
561585
if (column->fdwoptions!=NIL)
562586
{
@@ -587,6 +611,13 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
587611
staticvoid
588612
transformTableConstraint(CreateStmtContext*cxt,Constraint*constraint)
589613
{
614+
if (cxt->isforeign)
615+
ereport(ERROR,
616+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
617+
errmsg("constraints are not supported on foreign tables"),
618+
parser_errposition(cxt->pstate,
619+
constraint->location)));
620+
590621
switch (constraint->contype)
591622
{
592623
caseCONSTR_PRIMARY:
@@ -640,7 +671,14 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
640671
char*comment;
641672
ParseCallbackStatepcbstate;
642673

643-
setup_parser_errposition_callback(&pcbstate,cxt->pstate,table_like_clause->relation->location);
674+
setup_parser_errposition_callback(&pcbstate,cxt->pstate,
675+
table_like_clause->relation->location);
676+
677+
/* we could support LIKE in many cases, but worry about it another day */
678+
if (cxt->isforeign)
679+
ereport(ERROR,
680+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
681+
errmsg("LIKE is not supported for foreign tables")));
644682

645683
relation=relation_openrv(table_like_clause->relation,AccessShareLock);
646684

@@ -2334,7 +2372,16 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
23342372
pstate->p_sourcetext=queryString;
23352373

23362374
cxt.pstate=pstate;
2337-
cxt.stmtType="ALTER TABLE";
2375+
if (stmt->relkind==OBJECT_FOREIGN_TABLE)
2376+
{
2377+
cxt.stmtType="ALTER FOREIGN TABLE";
2378+
cxt.isforeign= true;
2379+
}
2380+
else
2381+
{
2382+
cxt.stmtType="ALTER TABLE";
2383+
cxt.isforeign= false;
2384+
}
23382385
cxt.relation=stmt->relation;
23392386
cxt.rel=rel;
23402387
cxt.inhRelations=NIL;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp