mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +03:00
Type table feature
This adds the CREATE TABLE name OF type command, per SQL standard.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.103 2010/01/02 16:57:36 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.104 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -217,6 +217,7 @@ Boot_CreateStmt:
|
||||
$5 ? GLOBALTABLESPACE_OID : 0,
|
||||
$3,
|
||||
$7,
|
||||
InvalidOid,
|
||||
BOOTSTRAP_SUPERUSERID,
|
||||
tupdesc,
|
||||
NIL,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.367 2010/01/22 16:40:18 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.368 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -72,7 +72,9 @@
|
||||
|
||||
static void AddNewRelationTuple(Relation pg_class_desc,
|
||||
Relation new_rel_desc,
|
||||
Oid new_rel_oid, Oid new_type_oid,
|
||||
Oid new_rel_oid,
|
||||
Oid new_type_oid,
|
||||
Oid reloftype,
|
||||
Oid relowner,
|
||||
char relkind,
|
||||
Datum relacl,
|
||||
@@ -669,6 +671,7 @@ InsertPgClassTuple(Relation pg_class_desc,
|
||||
values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
|
||||
values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
|
||||
values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
|
||||
values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
|
||||
values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
|
||||
values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
|
||||
values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
|
||||
@@ -727,6 +730,7 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||
Relation new_rel_desc,
|
||||
Oid new_rel_oid,
|
||||
Oid new_type_oid,
|
||||
Oid reloftype,
|
||||
Oid relowner,
|
||||
char relkind,
|
||||
Datum relacl,
|
||||
@@ -785,6 +789,7 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||
|
||||
new_rel_reltup->relowner = relowner;
|
||||
new_rel_reltup->reltype = new_type_oid;
|
||||
new_rel_reltup->reloftype = reloftype;
|
||||
new_rel_reltup->relkind = relkind;
|
||||
|
||||
new_rel_desc->rd_att->tdtypeid = new_type_oid;
|
||||
@@ -876,6 +881,7 @@ heap_create_with_catalog(const char *relname,
|
||||
Oid reltablespace,
|
||||
Oid relid,
|
||||
Oid reltypeid,
|
||||
Oid reloftypeid,
|
||||
Oid ownerid,
|
||||
TupleDesc tupdesc,
|
||||
List *cooked_constraints,
|
||||
@@ -1097,6 +1103,7 @@ heap_create_with_catalog(const char *relname,
|
||||
new_rel_desc,
|
||||
relid,
|
||||
new_type_oid,
|
||||
reloftypeid,
|
||||
ownerid,
|
||||
relkind,
|
||||
PointerGetDatum(relacl),
|
||||
@@ -1139,6 +1146,14 @@ heap_create_with_catalog(const char *relname,
|
||||
|
||||
recordDependencyOnOwner(RelationRelationId, relid, ownerid);
|
||||
|
||||
if (reloftypeid)
|
||||
{
|
||||
referenced.classId = TypeRelationId;
|
||||
referenced.objectId = reloftypeid;
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
if (relacl != NULL)
|
||||
{
|
||||
int nnewmembers;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (c) 2003-2010, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.64 2010/01/17 22:56:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.65 2010/01/28 23:21:11 petere Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1799,25 +1799,25 @@ CREATE VIEW tables AS
|
||||
CAST(null AS sql_identifier) AS self_referencing_column_name,
|
||||
CAST(null AS character_data) AS reference_generation,
|
||||
|
||||
CAST(null AS sql_identifier) AS user_defined_type_catalog,
|
||||
CAST(null AS sql_identifier) AS user_defined_type_schema,
|
||||
CAST(null AS sql_identifier) AS user_defined_type_name,
|
||||
CAST(CASE WHEN t.typname IS NOT NULL THEN current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog,
|
||||
CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema,
|
||||
CAST(t.typname AS sql_identifier) AS user_defined_type_name,
|
||||
|
||||
CAST(CASE WHEN c.relkind = 'r'
|
||||
OR (c.relkind = 'v'
|
||||
AND EXISTS (SELECT 1 FROM pg_rewrite WHERE ev_class = c.oid AND ev_type = '3' AND is_instead))
|
||||
THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into,
|
||||
|
||||
CAST('NO' AS yes_or_no) AS is_typed,
|
||||
CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed,
|
||||
CAST(
|
||||
CASE WHEN nc.oid = pg_my_temp_schema() THEN 'PRESERVE' -- FIXME
|
||||
ELSE null END
|
||||
AS character_data) AS commit_action
|
||||
|
||||
FROM pg_namespace nc, pg_class c
|
||||
FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace)
|
||||
LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid)
|
||||
|
||||
WHERE c.relnamespace = nc.oid
|
||||
AND c.relkind IN ('r', 'v')
|
||||
WHERE c.relkind IN ('r', 'v')
|
||||
AND (NOT pg_is_other_temp_schema(nc.oid))
|
||||
AND (pg_has_role(c.relowner, 'USAGE')
|
||||
OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.27 2010/01/06 03:03:58 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.28 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -203,6 +203,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
|
||||
rel->rd_rel->reltablespace,
|
||||
toastOid,
|
||||
toast_typid,
|
||||
InvalidOid,
|
||||
rel->rd_rel->relowner,
|
||||
tupdesc,
|
||||
NIL,
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.194 2010/01/20 19:43:40 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.195 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -720,6 +720,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
|
||||
NewTableSpace,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
OldHeap->rd_rel->relowner,
|
||||
tupdesc,
|
||||
NIL,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.319 2010/01/28 07:31:42 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.320 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -361,6 +361,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
ListCell *listptr;
|
||||
AttrNumber attnum;
|
||||
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
|
||||
Oid ofTypeId;
|
||||
|
||||
/*
|
||||
* Truncate relname to appropriate length (probably a waste of time, as
|
||||
@@ -443,6 +444,11 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
|
||||
(void) heap_reloptions(relkind, reloptions, true);
|
||||
|
||||
if (stmt->ofTypename)
|
||||
ofTypeId = typenameTypeId(NULL, stmt->ofTypename, NULL);
|
||||
else
|
||||
ofTypeId = InvalidOid;
|
||||
|
||||
/*
|
||||
* Look up inheritance ancestors and generate relation schema, including
|
||||
* inherited attributes.
|
||||
@@ -521,6 +527,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
tablespaceId,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
ofTypeId,
|
||||
GetUserId(),
|
||||
descriptor,
|
||||
list_concat(cookedDefaults,
|
||||
@@ -1230,17 +1237,46 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
foreach(entry, schema)
|
||||
{
|
||||
ColumnDef *coldef = lfirst(entry);
|
||||
ListCell *rest;
|
||||
ListCell *rest = lnext(entry);
|
||||
ListCell *prev = entry;
|
||||
|
||||
for_each_cell(rest, lnext(entry))
|
||||
if (coldef->typeName == NULL)
|
||||
/*
|
||||
* Typed table column option that does not belong to a
|
||||
* column from the type. This works because the columns
|
||||
* from the type come first in the list.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" does not exist",
|
||||
coldef->colname)));
|
||||
|
||||
while (rest != NULL)
|
||||
{
|
||||
ColumnDef *restdef = lfirst(rest);
|
||||
ListCell *next = lnext(rest); /* need to save it in case we delete it */
|
||||
|
||||
if (strcmp(coldef->colname, restdef->colname) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
coldef->colname)));
|
||||
{
|
||||
if (coldef->is_from_type)
|
||||
{
|
||||
/* merge the column options into the column from
|
||||
* the type */
|
||||
coldef->is_not_null = restdef->is_not_null;
|
||||
coldef->raw_default = restdef->raw_default;
|
||||
coldef->cooked_default = restdef->cooked_default;
|
||||
coldef->constraints = restdef->constraints;
|
||||
coldef->is_from_type = false;
|
||||
list_delete_cell(schema, rest, prev);
|
||||
}
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
coldef->colname)));
|
||||
}
|
||||
prev = rest;
|
||||
rest = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1921,6 +1957,11 @@ renameatt(Oid myrelid,
|
||||
*/
|
||||
targetrelation = relation_open(myrelid, AccessExclusiveLock);
|
||||
|
||||
if (targetrelation->rd_rel->reloftype)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot rename column of typed table")));
|
||||
|
||||
/*
|
||||
* permissions checking. this would normally be done in utility.c, but
|
||||
* this particular routine is recursive.
|
||||
@@ -3586,6 +3627,11 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
|
||||
Form_pg_type tform;
|
||||
Expr *defval;
|
||||
|
||||
if (rel->rd_rel->reloftype)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot add column to typed table")));
|
||||
|
||||
attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
@@ -4307,6 +4353,11 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
|
||||
List *children;
|
||||
ObjectAddress object;
|
||||
|
||||
if (rel->rd_rel->reloftype)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot drop column from typed table")));
|
||||
|
||||
/* At top level, permission check was done in ATPrepCmd, else do it */
|
||||
if (recursing)
|
||||
ATSimplePermissions(rel, false);
|
||||
|
@@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.342 2010/01/15 09:19:02 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.343 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2162,6 +2162,7 @@ OpenIntoRel(QueryDesc *queryDesc)
|
||||
tablespaceId,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
GetUserId(),
|
||||
tupdesc,
|
||||
NIL,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.459 2010/01/05 21:53:58 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.460 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2507,6 +2507,7 @@ _copyCreateStmt(CreateStmt *from)
|
||||
COPY_NODE_FIELD(relation);
|
||||
COPY_NODE_FIELD(tableElts);
|
||||
COPY_NODE_FIELD(inhRelations);
|
||||
COPY_NODE_FIELD(ofTypename);
|
||||
COPY_NODE_FIELD(constraints);
|
||||
COPY_NODE_FIELD(options);
|
||||
COPY_SCALAR_FIELD(oncommit);
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.381 2010/01/28 23:21:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1099,6 +1099,7 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b)
|
||||
COMPARE_NODE_FIELD(relation);
|
||||
COMPARE_NODE_FIELD(tableElts);
|
||||
COMPARE_NODE_FIELD(inhRelations);
|
||||
COMPARE_NODE_FIELD(ofTypename);
|
||||
COMPARE_NODE_FIELD(constraints);
|
||||
COMPARE_NODE_FIELD(options);
|
||||
COMPARE_SCALAR_FIELD(oncommit);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.381 2010/01/28 23:21:12 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every node type that can appear in stored rules' parsetrees *must*
|
||||
@@ -1784,6 +1784,7 @@ _outCreateStmt(StringInfo str, CreateStmt *node)
|
||||
WRITE_NODE_FIELD(relation);
|
||||
WRITE_NODE_FIELD(tableElts);
|
||||
WRITE_NODE_FIELD(inhRelations);
|
||||
WRITE_NODE_FIELD(ofTypename);
|
||||
WRITE_NODE_FIELD(constraints);
|
||||
WRITE_NODE_FIELD(options);
|
||||
WRITE_ENUM_FIELD(oncommit, OnCommitAction);
|
||||
|
@@ -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; }
|
||||
|
@@ -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
|
||||
*
|
||||
|
Reference in New Issue
Block a user