aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y56
-rw-r--r--src/backend/parser/parse_utilcmd.c58
2 files changed, 97 insertions, 17 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 981d2614042..d7bbbbd1bef 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.705 2010/01/25 20:55:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.706 2010/01/28 23:21:12 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -277,6 +277,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
+ OptTypedTableElementList TypedTableElementList
reloptions opt_reloptions
OptWith opt_distinct opt_definition func_args func_args_list
func_args_with_defaults func_args_with_defaults_list
@@ -347,8 +348,8 @@ static TypeName *TableFuncTypeName(List *columns);
%type <vsetstmt> set_rest SetResetClause
-%type <node> TableElement ConstraintElem TableFuncElement
-%type <node> columnDef
+%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
+%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
a_expr b_expr c_expr func_expr AexprConst indirection_el
@@ -2203,21 +2204,19 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->tablespacename = $11;
$$ = (Node *)n;
}
- | CREATE OptTemp TABLE qualified_name OF qualified_name
- '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
+ | CREATE OptTemp TABLE qualified_name OF any_name
+ OptTypedTableElementList OptWith OnCommitOption OptTableSpace
{
- /* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied
- * by our inheritance capabilities. Let's try it...
- */
CreateStmt *n = makeNode(CreateStmt);
$4->istemp = $2;
n->relation = $4;
- n->tableElts = $8;
- n->inhRelations = list_make1($6);
+ n->tableElts = $7;
+ n->ofTypename = makeTypeNameFromNameList($6);
+ n->ofTypename->location = @6;
n->constraints = NIL;
- n->options = $10;
- n->oncommit = $11;
- n->tablespacename = $12;
+ n->options = $8;
+ n->oncommit = $9;
+ n->tablespacename = $10;
$$ = (Node *)n;
}
;
@@ -2243,6 +2242,11 @@ OptTableElementList:
| /*EMPTY*/ { $$ = NIL; }
;
+OptTypedTableElementList:
+ '(' TypedTableElementList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
TableElementList:
TableElement
{
@@ -2254,12 +2258,28 @@ TableElementList:
}
;
+TypedTableElementList:
+ TypedTableElement
+ {
+ $$ = list_make1($1);
+ }
+ | TypedTableElementList ',' TypedTableElement
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
| TableConstraint { $$ = $1; }
;
+TypedTableElement:
+ columnOptions { $$ = $1; }
+ | TableConstraint { $$ = $1; }
+ ;
+
columnDef: ColId Typename ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
@@ -2271,6 +2291,16 @@ columnDef: ColId Typename ColQualList
}
;
+columnOptions: ColId WITH OPTIONS ColQualList
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->constraints = $4;
+ n->is_local = true;
+ $$ = (Node *)n;
+ }
+ ;
+
ColQualList:
ColQualList ColConstraint { $$ = lappend($1, $2); }
| /*EMPTY*/ { $$ = NIL; }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index a1ed7e48e37..bf455701e33 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -19,7 +19,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.36 2010/01/02 16:57:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.37 2010/01/28 23:21:12 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,6 +58,7 @@
#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
+#include "utils/typcache.h"
/* State shared by transformCreateStmt and its subroutines */
@@ -104,6 +105,8 @@ static void transformTableConstraint(ParseState *pstate,
Constraint *constraint);
static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
InhRelation *inhrelation);
+static void transformOfType(ParseState *pstate, CreateStmtContext *cxt,
+ TypeName *ofTypename);
static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt);
static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
Relation parent_index, AttrNumber *attmap);
@@ -183,6 +186,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
cxt.pkey = NULL;
cxt.hasoids = interpretOidsOption(stmt->options);
+ Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */
+
+ if (stmt->ofTypename)
+ transformOfType(pstate, &cxt, stmt->ofTypename);
+
/*
* Run through each primary element in the table creation clause. Separate
* column defs from constraints, and do preliminary analysis.
@@ -266,8 +274,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
/* Check for SERIAL pseudo-types */
is_serial = false;
- if (list_length(column->typeName->names) == 1 &&
- !column->typeName->pct_type)
+ if (column->typeName
+ && list_length(column->typeName->names) == 1
+ && !column->typeName->pct_type)
{
char *typname = strVal(linitial(column->typeName->names));
@@ -299,7 +308,8 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
}
/* Do necessary work on the column type declaration */
- transformColumnType(pstate, column);
+ if (column->typeName)
+ transformColumnType(pstate, column);
/* Special actions for SERIAL pseudo-types */
if (is_serial)
@@ -787,6 +797,46 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
heap_close(relation, NoLock);
}
+static void
+transformOfType(ParseState *pstate, CreateStmtContext *cxt, TypeName *ofTypename)
+{
+ HeapTuple tuple;
+ Form_pg_type typ;
+ TupleDesc tupdesc;
+ int i;
+ Oid ofTypeId;
+
+ AssertArg(ofTypename);
+
+ tuple = typenameType(NULL, ofTypename, NULL);
+ typ = (Form_pg_type) GETSTRUCT(tuple);
+ ofTypeId = HeapTupleGetOid(tuple);
+ ofTypename->typeOid = ofTypeId; /* cached for later */
+
+ if (typ->typtype != TYPTYPE_COMPOSITE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("type %s is not a composite type",
+ format_type_be(ofTypeId))));
+
+ tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
+ for (i = 0; i < tupdesc->natts; i++)
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ Form_pg_attribute attr = tupdesc->attrs[i];
+
+ n->colname = NameStr(attr->attname);
+ n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
+ n->constraints = NULL;
+ n->is_local = true;
+ n->is_from_type = true;
+ cxt->columns = lappend(cxt->columns, n);
+ }
+ DecrTupleDescRefCount(tupdesc);
+
+ ReleaseSysCache(tuple);
+}
+
/*
* chooseIndexName
*