aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-03-12 17:37:07 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-03-12 17:37:07 -0400
commita0c6dfeecfcc860858b04617a9d96eaee1d82c66 (patch)
treecb4fc000b7fd65b73974633c2eb75742516f16cb /src/backend/parser
parent1ba0119308e74e522c75662147d89d154f45bb5d (diff)
downloadpostgresql-a0c6dfeecfcc860858b04617a9d96eaee1d82c66.tar.gz
postgresql-a0c6dfeecfcc860858b04617a9d96eaee1d82c66.zip
Allow default expressions to be attached to columns of foreign tables.
There's still some discussion about exactly how postgres_fdw ought to handle this case, but there seems no debate that we want to allow defaults to be used for inserts into foreign tables. So remove the core-code restrictions that prevented it. While at it, get rid of the special grammar productions for CREATE FOREIGN TABLE, and instead add explicit FEATURE_NOT_SUPPORTED error checks for the disallowed cases. This makes the grammar a shade smaller, and more importantly results in much more intelligible error messages for unsupported cases. It's also one less thing to fix if we ever start supporting constraints on foreign tables.
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y38
-rw-r--r--src/backend/parser/parse_utilcmd.c57
2 files changed, 60 insertions, 35 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0787d2f5061..9d07f30906c 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -330,7 +330,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
OptTypedTableElementList TypedTableElementList
- OptForeignTableElementList ForeignTableElementList
reloptions opt_reloptions
OptWith opt_distinct opt_definition func_args func_args_list
func_args_with_defaults func_args_with_defaults_list
@@ -408,7 +407,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
- ForeignTableElement
%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
@@ -4137,57 +4135,37 @@ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_o
CreateForeignTableStmt:
CREATE FOREIGN TABLE qualified_name
- OptForeignTableElementList
+ '(' OptTableElementList ')'
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
$4->relpersistence = RELPERSISTENCE_PERMANENT;
n->base.relation = $4;
- n->base.tableElts = $5;
+ n->base.tableElts = $6;
n->base.inhRelations = NIL;
n->base.if_not_exists = false;
/* FDW-specific data */
- n->servername = $7;
- n->options = $8;
+ n->servername = $9;
+ n->options = $10;
$$ = (Node *) n;
}
| CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name
- OptForeignTableElementList
+ '(' OptTableElementList ')'
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
$7->relpersistence = RELPERSISTENCE_PERMANENT;
n->base.relation = $7;
- n->base.tableElts = $8;
+ n->base.tableElts = $9;
n->base.inhRelations = NIL;
n->base.if_not_exists = true;
/* FDW-specific data */
- n->servername = $10;
- n->options = $11;
+ n->servername = $12;
+ n->options = $13;
$$ = (Node *) n;
}
;
-OptForeignTableElementList:
- '(' ForeignTableElementList ')' { $$ = $2; }
- | '(' ')' { $$ = NIL; }
- ;
-
-ForeignTableElementList:
- ForeignTableElement
- {
- $$ = list_make1($1);
- }
- | ForeignTableElementList ',' ForeignTableElement
- {
- $$ = lappend($1, $3);
- }
- ;
-
-ForeignTableElement:
- columnDef { $$ = $1; }
- ;
-
/*****************************************************************************
*
* QUERY:
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 8a1876c8a39..4fdcf180fa4 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -70,6 +70,7 @@ typedef struct
RangeVar *relation; /* relation to create */
Relation rel; /* opened/locked rel, if ALTER */
List *inhRelations; /* relations to inherit from */
+ bool isforeign; /* true if CREATE/ALTER FOREIGN TABLE */
bool isalter; /* true if altering existing table */
bool hasoids; /* does relation have an OID column? */
List *columns; /* ColumnDef items */
@@ -195,9 +196,15 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
cxt.pstate = pstate;
if (IsA(stmt, CreateForeignTableStmt))
+ {
cxt.stmtType = "CREATE FOREIGN TABLE";
+ cxt.isforeign = true;
+ }
else
+ {
cxt.stmtType = "CREATE TABLE";
+ cxt.isforeign = false;
+ }
cxt.relation = stmt->relation;
cxt.rel = NULL;
cxt.inhRelations = stmt->inhRelations;
@@ -515,11 +522,23 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
break;
case CONSTR_CHECK:
+ if (cxt->isforeign)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constraints are not supported on foreign tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
break;
case CONSTR_PRIMARY:
case CONSTR_UNIQUE:
+ if (cxt->isforeign)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constraints are not supported on foreign tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
if (constraint->keys == NIL)
constraint->keys = list_make1(makeString(column->colname));
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
@@ -531,7 +550,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
break;
case CONSTR_FOREIGN:
-
+ if (cxt->isforeign)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constraints are not supported on foreign tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
/*
* Fill in the current attribute's name and throw it into the
* list of FK constraints to be processed later.
@@ -555,8 +579,8 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
}
/*
- * Generate ALTER FOREIGN TABLE ALTER COLUMN statement which adds
- * per-column foreign data wrapper options for this column.
+ * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add
+ * per-column foreign data wrapper options to this column after creation.
*/
if (column->fdwoptions != NIL)
{
@@ -587,6 +611,13 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
static void
transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
{
+ if (cxt->isforeign)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constraints are not supported on foreign tables"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
+
switch (constraint->contype)
{
case CONSTR_PRIMARY:
@@ -640,7 +671,14 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
char *comment;
ParseCallbackState pcbstate;
- setup_parser_errposition_callback(&pcbstate, cxt->pstate, table_like_clause->relation->location);
+ setup_parser_errposition_callback(&pcbstate, cxt->pstate,
+ table_like_clause->relation->location);
+
+ /* we could support LIKE in many cases, but worry about it another day */
+ if (cxt->isforeign)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("LIKE is not supported for foreign tables")));
relation = relation_openrv(table_like_clause->relation, AccessShareLock);
@@ -2334,7 +2372,16 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
pstate->p_sourcetext = queryString;
cxt.pstate = pstate;
- cxt.stmtType = "ALTER TABLE";
+ if (stmt->relkind == OBJECT_FOREIGN_TABLE)
+ {
+ cxt.stmtType = "ALTER FOREIGN TABLE";
+ cxt.isforeign = true;
+ }
+ else
+ {
+ cxt.stmtType = "ALTER TABLE";
+ cxt.isforeign = false;
+ }
cxt.relation = stmt->relation;
cxt.rel = rel;
cxt.inhRelations = NIL;