On Thu, Mar 15, 2012 at 11:23:43AM -0300, Alvaro Herrera wrote:
> Excerpts from David Fetter's message of jue mar 15 02:28:28 -0300 2012:
> > On Wed, Mar 14, 2012 at 12:06:20PM -0400, Robert Haas wrote:
> > > On Wed, Mar 14, 2012 at 10:22 AM, David Fetter <[email protected]> wrote:
> > > >> I think that instead of inventing new grammar productions and a new
> > > >> node type for this, you should just reuse the existing productions for
> > > >> LIKE clauses and then reject invalid options during parse analysis.
> > > >
> > > > OK. Should I first merge CREATE FOREIGN TABLE with CREATE TABLE and
> > > > submit that as a separate patch?
> > >
> > > I don't see any reason to do that. I merely meant that you could
> > > reuse TableLikeClause or maybe even TableElement in the grammer for
> > > CreateForeignTableStmt.
> >
> > Next WIP patch attached implementing this via reusing TableLikeClause
> > and refactoring transformTableLikeClause().
> >
> > What say?
>
> Looks much better to me, but the use of strcmp() doesn't look good.
> ISTM that stmtType is mostly used for error messages. I think you
> should add some kind of identifier (such as the original parser Node)
> into the CreateStmtContext so that you can do a IsA() test instead -- a
> bit more invasive as a patch, but much cleaner.
>
> Also the error messages need more work.
How about this one?
Cheers,
David.
--
David Fetter <[email protected]> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: [email protected]
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
*** a/doc/src/sgml/ref/create_foreign_table.sgml
--- b/doc/src/sgml/ref/create_foreign_table.sgml
***************
*** 19,26 ****
<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> [ OPTIONS ( <replaceable
class="PARAMETER">option</replaceable> '<replaceable
class="PARAMETER">value</replaceable>' [, ... ] ) ] [ NULL | NOT NULL ] }
! [, ... ]
] )
SERVER <replaceable class="parameter">server_name</replaceable>
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable
class="PARAMETER">value</replaceable>' [, ... ] ) ]
--- 19,26 ----
<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 ] | LIKE
<replaceable>source_table</replaceable> } [, ... ]
! [ OPTIONS ( <replaceable class="PARAMETER">option</replaceable>
'<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ] }
] )
SERVER <replaceable class="parameter">server_name</replaceable>
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable
class="PARAMETER">value</replaceable>' [, ... ] ) ]
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 3945,3950 **** ForeignTableElementList:
--- 3945,3951 ----
ForeignTableElement:
columnDef { $$ =
$1; }
+ | TableLikeClause { $$ = $1; }
;
/*****************************************************************************
*** a/src/backend/parser/parse_utilcmd.c
--- b/src/backend/parser/parse_utilcmd.c
***************
*** 66,71 **** typedef struct
--- 66,72 ----
{
ParseState *pstate; /* overall parser state */
const char *stmtType; /* "CREATE [FOREIGN] TABLE" or "ALTER
TABLE" */
+ char relkind; /* r = ordinary table, f =
foreign table, cf. pg_catalog.pg_class */
RangeVar *relation; /* relation to create */
Relation rel; /* opened/locked rel, if ALTER
*/
List *inhRelations; /* relations to inherit from */
***************
*** 194,202 **** transformCreateStmt(CreateStmt *stmt, const char *queryString)
--- 195,209 ----
cxt.pstate = pstate;
if (IsA(stmt, CreateForeignTableStmt))
+ {
cxt.stmtType = "CREATE FOREIGN TABLE";
+ cxt.relkind = 'f';
+ }
else
+ {
cxt.stmtType = "CREATE TABLE";
+ cxt.relkind = 'r';
+ }
cxt.relation = stmt->relation;
cxt.rel = NULL;
cxt.inhRelations = stmt->inhRelations;
***************
*** 623,629 **** transformTableConstraint(CreateStmtContext *cxt, Constraint
*constraint)
/*
* transformTableLikeClause
*
! * Change the LIKE <srctable> portion of a CREATE TABLE statement into
* column definitions which recreate the user defined column portions of
* <srctable>.
*/
--- 630,636 ----
/*
* transformTableLikeClause
*
! * Change the LIKE <srctable> portion of a CREATE [FOREIGN] TABLE statement
into
* column definitions which recreate the user defined column portions of
* <srctable>.
*/
***************
*** 652,657 **** transformTableLikeClause(CreateStmtContext *cxt,
TableLikeClause *table_like_cla
--- 659,683 ----
table_like_clause->relation->relname)));
cancel_parser_errposition_callback(&pcbstate);
+
+ /*
+ * For foreign tables, disallow some options.
+ */
+ if (cxt->relkind == 'f')
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("ERROR: foreign tables do not
support LIKE INCLUDING CONSTRAINTS")));
+ }
+ else if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("ERROR: foreign tables do not
support LIKE INCLUDING INDEXES")));
+ }
+ }
/*
* Check for privileges
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers