diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 56 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 58 |
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 * |