提交 faa1afc6 编写于 作者: A Andrew Dunstan

CREATE LIKE INCLUDING COMMENTS and STORAGE, and INCLUDING ALL shortcut. Itagaki Takahiro.

上级 0adaf4cb
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.116 2009/09/18 05:00:41 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.117 2009/10/12 19:49:24 adunstan Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -24,7 +24,7 @@ PostgreSQL documentation ...@@ -24,7 +24,7 @@ PostgreSQL documentation
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> ( [ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> ( [
{ <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ] { <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
| <replaceable>table_constraint</replaceable> | <replaceable>table_constraint</replaceable>
| LIKE <replaceable>parent_table</replaceable> [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES } ] ... } | LIKE <replaceable>parent_table</replaceable> [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | ALL } ] ... }
[, ... ] [, ... ]
] ) ] )
[ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ] [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
...@@ -230,6 +230,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR ...@@ -230,6 +230,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR
will always be chosen for it. will always be chosen for it.
</para> </para>
<para>
Column storage parameters are also copied from parent tables.
</para>
<!-- <!--
<para> <para>
<productname>PostgreSQL</> automatically allows the <productname>PostgreSQL</> automatically allows the
...@@ -247,7 +251,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR ...@@ -247,7 +251,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>LIKE <replaceable>parent_table</replaceable> [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES } ]</literal></term> <term><literal>LIKE <replaceable>parent_table</replaceable> [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | ALL } ]</literal></term>
<listitem> <listitem>
<para> <para>
The <literal>LIKE</literal> clause specifies a table from which The <literal>LIKE</literal> clause specifies a table from which
...@@ -280,6 +284,23 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR ...@@ -280,6 +284,23 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR
table, unless the <literal>INCLUDING INDEXES</literal> clause is table, unless the <literal>INCLUDING INDEXES</literal> clause is
specified. specified.
</para> </para>
<para>
Storage parameters for the copied column definitions will only be copied
if <literal>INCLUDING STORAGE</literal> is specified. The default
behavior is to exclude storage parameters, resulting in the copied
columns in the new table having type-specific default parameters. For
more on storage parameters, see <xref linkend="storage-toast">.
</para>
<para>
Comments for the copied column, constraint, index and columns of index
definitions will only be copied if <literal>INCLUDING COMMENTS</literal>
is specified. The default behavior is to exclude comments, resulting in
the copied columns and constraints in the new table having no comments.
</para>
<para>
<literal>INCLUDING ALL</literal> is an abbreviated form of
<literal>INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS</literal>.
</para>
<para> <para>
Note also that unlike <literal>INHERITS</literal>, copied columns and Note also that unlike <literal>INHERITS</literal>, copied columns and
constraints are not merged with similarly named columns and constraints. constraints are not merged with similarly named columns and constraints.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.128 2009/08/02 22:14:51 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.129 2009/10/12 19:49:24 adunstan Exp $
* *
* NOTES * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
...@@ -558,6 +558,8 @@ BuildDescForRelation(List *schema) ...@@ -558,6 +558,8 @@ BuildDescForRelation(List *schema)
has_not_null |= entry->is_not_null; has_not_null |= entry->is_not_null;
desc->attrs[attnum - 1]->attislocal = entry->is_local; desc->attrs[attnum - 1]->attislocal = entry->is_local;
desc->attrs[attnum - 1]->attinhcount = entry->inhcount; desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
if (entry->storage)
desc->attrs[attnum - 1]->attstorage = entry->storage;
} }
if (has_not_null) if (has_not_null)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.47 2009/07/28 02:56:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.48 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -702,3 +702,65 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, ...@@ -702,3 +702,65 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
heap_close(conRel, RowExclusiveLock); heap_close(conRel, RowExclusiveLock);
} }
/*
* GetConstraintByName
* Find a constraint with the specified name.
*/
Oid
GetConstraintByName(Oid relid, const char *conname)
{
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
ScanKeyData skey[1];
Oid conOid = InvalidOid;
/*
* Fetch the constraint tuple from pg_constraint. There may be more than
* one match, because constraints are not required to have unique names;
* if so, error out.
*/
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ, relid);
scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
SnapshotNow, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
if (strcmp(NameStr(con->conname), conname) == 0)
{
if (OidIsValid(conOid))
{
char *relname = get_rel_name(relid);
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("table \"%s\" has multiple constraints named \"%s\"",
(relname ? relname : "(unknown)"), conname)));
}
conOid = HeapTupleGetOid(tuple);
}
}
systable_endscan(scan);
/* If no constraint exists for the relation specified, notify user */
if (!OidIsValid(conOid))
{
char *relname = get_rel_name(relid);
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" for table \"%s\" does not exist",
conname, (relname ? relname : "(unknown)"))));
}
heap_close(pg_constraint, AccessShareLock);
return conOid;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 1996-2009, PostgreSQL Global Development Group * Copyright (c) 1996-2009, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.107 2009/06/11 14:48:55 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.108 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -462,6 +462,61 @@ DeleteSharedComments(Oid oid, Oid classoid) ...@@ -462,6 +462,61 @@ DeleteSharedComments(Oid oid, Oid classoid)
heap_close(shdescription, RowExclusiveLock); heap_close(shdescription, RowExclusiveLock);
} }
/*
* GetComment -- get the comment for an object, or null if not found.
*/
char *
GetComment(Oid oid, Oid classoid, int32 subid)
{
Relation description;
ScanKeyData skey[3];
SysScanDesc sd;
TupleDesc tupdesc;
HeapTuple tuple;
char *comment;
/* Use the index to search for a matching old tuple */
ScanKeyInit(&skey[0],
Anum_pg_description_objoid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(oid));
ScanKeyInit(&skey[1],
Anum_pg_description_classoid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(classoid));
ScanKeyInit(&skey[2],
Anum_pg_description_objsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(subid));
description = heap_open(DescriptionRelationId, AccessShareLock);
tupdesc = RelationGetDescr(description);
sd = systable_beginscan(description, DescriptionObjIndexId, true,
SnapshotNow, 3, skey);
comment = NULL;
while ((tuple = systable_getnext(sd)) != NULL)
{
Datum value;
bool isnull;
/* Found the tuple, get description field */
value = heap_getattr(tuple, Anum_pg_description_description, tupdesc, &isnull);
if (!isnull)
comment = TextDatumGetCString(value);
break; /* Assume there can be only one match */
}
systable_endscan(sd);
/* Done */
heap_close(description, AccessShareLock);
return comment;
}
/* /*
* CommentRelation -- * CommentRelation --
* *
...@@ -1064,12 +1119,8 @@ CommentConstraint(List *qualname, char *comment) ...@@ -1064,12 +1119,8 @@ CommentConstraint(List *qualname, char *comment)
List *relName; List *relName;
char *conName; char *conName;
RangeVar *rel; RangeVar *rel;
Relation pg_constraint, Relation relation;
relation; Oid conOid;
HeapTuple tuple;
SysScanDesc scan;
ScanKeyData skey[1];
Oid conOid = InvalidOid;
/* Separate relname and constraint name */ /* Separate relname and constraint name */
nnames = list_length(qualname); nnames = list_length(qualname);
...@@ -1088,50 +1139,12 @@ CommentConstraint(List *qualname, char *comment) ...@@ -1088,50 +1139,12 @@ CommentConstraint(List *qualname, char *comment)
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
RelationGetRelationName(relation)); RelationGetRelationName(relation));
/* conOid = GetConstraintByName(RelationGetRelid(relation), conName);
* Fetch the constraint tuple from pg_constraint. There may be more than
* one match, because constraints are not required to have unique names;
* if so, error out.
*/
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
SnapshotNow, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
if (strcmp(NameStr(con->conname), conName) == 0)
{
if (OidIsValid(conOid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("table \"%s\" has multiple constraints named \"%s\"",
RelationGetRelationName(relation), conName)));
conOid = HeapTupleGetOid(tuple);
}
}
systable_endscan(scan);
/* If no constraint exists for the relation specified, notify user */
if (!OidIsValid(conOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" for table \"%s\" does not exist",
conName, RelationGetRelationName(relation))));
/* Call CreateComments() to create/drop the comments */ /* Call CreateComments() to create/drop the comments */
CreateComments(conOid, ConstraintRelationId, 0, comment); CreateComments(conOid, ConstraintRelationId, 0, comment);
/* Done, but hold lock on relation */ /* Done, but hold lock on relation */
heap_close(pg_constraint, AccessShareLock);
heap_close(relation, NoLock); heap_close(relation, NoLock);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.301 2009/10/06 00:55:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.302 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "catalog/storage.h" #include "catalog/storage.h"
#include "catalog/toasting.h" #include "catalog/toasting.h"
#include "commands/cluster.h" #include "commands/cluster.h"
#include "commands/comment.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/sequence.h" #include "commands/sequence.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
...@@ -332,6 +333,7 @@ static void ATExecAddInherit(Relation rel, RangeVar *parent); ...@@ -332,6 +333,7 @@ static void ATExecAddInherit(Relation rel, RangeVar *parent);
static void ATExecDropInherit(Relation rel, RangeVar *parent); static void ATExecDropInherit(Relation rel, RangeVar *parent);
static void copy_relation_data(SMgrRelation rel, SMgrRelation dst, static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
ForkNumber forkNum, bool istemp); ForkNumber forkNum, bool istemp);
static const char * storage_name(char c);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -1100,6 +1102,25 @@ truncate_check_rel(Relation rel) ...@@ -1100,6 +1102,25 @@ truncate_check_rel(Relation rel)
CheckTableNotInUse(rel, "TRUNCATE"); CheckTableNotInUse(rel, "TRUNCATE");
} }
/*----------------
* storage_name
* returns a name corresponding to a storage enum value
* For use in error messages
*/
static const char *
storage_name(char c)
{
switch (c)
{
case 'p': return "PLAIN";
case 'm': return "MAIN";
case 'x': return "EXTENDED";
case 'e': return "EXTERNAL";
default: return "???";
}
}
/*---------- /*----------
* MergeAttributes * MergeAttributes
* Returns new schema given initial schema and superclasses. * Returns new schema given initial schema and superclasses.
...@@ -1168,6 +1189,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1168,6 +1189,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
List *constraints = NIL; List *constraints = NIL;
int parentsWithOids = 0; int parentsWithOids = 0;
bool have_bogus_defaults = false; bool have_bogus_defaults = false;
bool have_bogus_comments = false;
int child_attno; int child_attno;
static Node bogus_marker = { 0 }; /* marks conflicting defaults */ static Node bogus_marker = { 0 }; /* marks conflicting defaults */
...@@ -1323,6 +1345,18 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1323,6 +1345,18 @@ MergeAttributes(List *schema, List *supers, bool istemp,
errdetail("%s versus %s", errdetail("%s versus %s",
TypeNameToString(def->typeName), TypeNameToString(def->typeName),
format_type_be(attribute->atttypid)))); format_type_be(attribute->atttypid))));
/* Copy storage parameter */
if (def->storage == 0)
def->storage = attribute->attstorage;
else if (def->storage != attribute->attstorage)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("inherited column \"%s\" has a storage parameter conflict",
attributeName),
errdetail("%s versus %s", storage_name(def->storage),
storage_name(attribute->attstorage))));
def->inhcount++; def->inhcount++;
/* Merge of NOT NULL constraints = OR 'em together */ /* Merge of NOT NULL constraints = OR 'em together */
def->is_not_null |= attribute->attnotnull; def->is_not_null |= attribute->attnotnull;
...@@ -1344,6 +1378,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1344,6 +1378,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
def->raw_default = NULL; def->raw_default = NULL;
def->cooked_default = NULL; def->cooked_default = NULL;
def->constraints = NIL; def->constraints = NIL;
def->storage = attribute->attstorage;
inhSchema = lappend(inhSchema, def); inhSchema = lappend(inhSchema, def);
newattno[parent_attno - 1] = ++child_attno; newattno[parent_attno - 1] = ++child_attno;
} }
...@@ -1481,6 +1516,18 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1481,6 +1516,18 @@ MergeAttributes(List *schema, List *supers, bool istemp,
errdetail("%s versus %s", errdetail("%s versus %s",
TypeNameToString(def->typeName), TypeNameToString(def->typeName),
TypeNameToString(newdef->typeName)))); TypeNameToString(newdef->typeName))));
/* Copy storage parameter */
if (def->storage == 0)
def->storage = newdef->storage;
else if (newdef->storage != 0 && def->storage != newdef->storage)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("column \"%s\" has a storage parameter conflict",
attributeName),
errdetail("%s versus %s", storage_name(def->storage),
storage_name(newdef->storage))));
/* Mark the column as locally defined */ /* Mark the column as locally defined */
def->is_local = true; def->is_local = true;
/* Merge of NOT NULL constraints = OR 'em together */ /* Merge of NOT NULL constraints = OR 'em together */
...@@ -1533,6 +1580,20 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1533,6 +1580,20 @@ MergeAttributes(List *schema, List *supers, bool istemp,
} }
} }
/* Raise an error if we found conflicting comments. */
if (have_bogus_comments)
{
foreach(entry, schema)
{
ColumnDef *def = lfirst(entry);
if (def->cooked_default == &bogus_marker)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
errmsg("column \"%s\" inherits conflicting comments", def->colname)));
}
}
*supOids = parentOids; *supOids = parentOids;
*supconstr = constraints; *supconstr = constraints;
*supOidCount = parentsWithOids; *supOidCount = parentsWithOids;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.444 2009/10/12 18:10:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.445 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2489,7 +2489,7 @@ _copyInhRelation(InhRelation *from) ...@@ -2489,7 +2489,7 @@ _copyInhRelation(InhRelation *from)
InhRelation *newnode = makeNode(InhRelation); InhRelation *newnode = makeNode(InhRelation);
COPY_NODE_FIELD(relation); COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(options);
return newnode; return newnode;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.366 2009/10/12 18:10:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.367 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1107,7 +1107,7 @@ static bool ...@@ -1107,7 +1107,7 @@ static bool
_equalInhRelation(InhRelation *a, InhRelation *b) _equalInhRelation(InhRelation *a, InhRelation *b)
{ {
COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(options);
return true; return true;
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.682 2009/10/08 02:39:22 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.683 2009/10/12 19:49:24 adunstan Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -407,8 +407,7 @@ static TypeName *TableFuncTypeName(List *columns); ...@@ -407,8 +407,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <keyword> col_name_keyword reserved_keyword %type <keyword> col_name_keyword reserved_keyword
%type <node> TableConstraint TableLikeClause %type <node> TableConstraint TableLikeClause
%type <list> TableLikeOptionList %type <ival> TableLikeOptionList TableLikeOption
%type <ival> TableLikeOption
%type <list> ColQualList %type <list> ColQualList
%type <node> ColConstraint ColConstraintElem ConstraintAttr %type <node> ColConstraint ColConstraintElem ConstraintAttr
%type <ival> key_actions key_delete key_match key_update key_action %type <ival> key_actions key_delete key_match key_update key_action
...@@ -466,7 +465,7 @@ static TypeName *TableFuncTypeName(List *columns); ...@@ -466,7 +465,7 @@ static TypeName *TableFuncTypeName(List *columns);
CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT CLUSTER COALESCE COLLATE COLUMN COMMENT COMMENTS COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P CREATEROLE CREATEUSER CROSS CSV CURRENT_P
...@@ -2417,17 +2416,18 @@ TableLikeClause: ...@@ -2417,17 +2416,18 @@ TableLikeClause:
; ;
TableLikeOptionList: TableLikeOptionList:
TableLikeOptionList TableLikeOption { $$ = lappend_int($1, $2); } TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; }
| /* EMPTY */ { $$ = NIL; } | TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; }
| /* EMPTY */ { $$ = 0; }
; ;
TableLikeOption: TableLikeOption:
INCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_INCLUDING_DEFAULTS; } DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| EXCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS; } | CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| INCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS; } | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
| EXCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS; } | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
| INCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_INCLUDING_INDEXES; } | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| EXCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_EXCLUDING_INDEXES; } | ALL { $$ = CREATE_TABLE_LIKE_ALL; }
; ;
...@@ -10481,6 +10481,7 @@ unreserved_keyword: ...@@ -10481,6 +10481,7 @@ unreserved_keyword:
| CLOSE | CLOSE
| CLUSTER | CLUSTER
| COMMENT | COMMENT
| COMMENTS
| COMMIT | COMMIT
| COMMITTED | COMMITTED
| CONCURRENTLY | CONCURRENTLY
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.26 2009/10/06 00:55:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.27 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "catalog/pg_constraint.h" #include "catalog/pg_constraint.h"
#include "catalog/pg_opclass.h" #include "catalog/pg_opclass.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/comment.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
#include "commands/tablespace.h" #include "commands/tablespace.h"
...@@ -101,6 +102,7 @@ static void transformTableConstraint(ParseState *pstate, ...@@ -101,6 +102,7 @@ static void transformTableConstraint(ParseState *pstate,
Constraint *constraint); Constraint *constraint);
static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
InhRelation *inhrelation); InhRelation *inhrelation);
static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt);
static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt, static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
Relation parent_index, AttrNumber *attmap); Relation parent_index, AttrNumber *attmap);
static List *get_opclass(Oid opclass, Oid actual_datatype); static List *get_opclass(Oid opclass, Oid actual_datatype);
...@@ -546,10 +548,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -546,10 +548,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
TupleDesc tupleDesc; TupleDesc tupleDesc;
TupleConstr *constr; TupleConstr *constr;
AclResult aclresult; AclResult aclresult;
bool including_defaults = false; char *comment;
bool including_constraints = false;
bool including_indexes = false;
ListCell *elem;
relation = parserOpenTable(pstate, inhRelation->relation, AccessShareLock); relation = parserOpenTable(pstate, inhRelation->relation, AccessShareLock);
...@@ -571,36 +570,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -571,36 +570,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
tupleDesc = RelationGetDescr(relation); tupleDesc = RelationGetDescr(relation);
constr = tupleDesc->constr; constr = tupleDesc->constr;
foreach(elem, inhRelation->options)
{
int option = lfirst_int(elem);
switch (option)
{
case CREATE_TABLE_LIKE_INCLUDING_DEFAULTS:
including_defaults = true;
break;
case CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS:
including_defaults = false;
break;
case CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS:
including_constraints = true;
break;
case CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS:
including_constraints = false;
break;
case CREATE_TABLE_LIKE_INCLUDING_INDEXES:
including_indexes = true;
break;
case CREATE_TABLE_LIKE_EXCLUDING_INDEXES:
including_indexes = false;
break;
default:
elog(ERROR, "unrecognized CREATE TABLE LIKE option: %d",
option);
}
}
/* /*
* Insert the copied attributes into the cxt for the new table definition. * Insert the copied attributes into the cxt for the new table definition.
*/ */
...@@ -642,7 +611,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -642,7 +611,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
/* /*
* Copy default, if present and the default has been requested * Copy default, if present and the default has been requested
*/ */
if (attribute->atthasdef && including_defaults) if (attribute->atthasdef &&
(inhRelation->options & CREATE_TABLE_LIKE_DEFAULTS))
{ {
Node *this_default = NULL; Node *this_default = NULL;
AttrDefault *attrdef; AttrDefault *attrdef;
...@@ -668,13 +638,34 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -668,13 +638,34 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
def->cooked_default = this_default; def->cooked_default = this_default;
} }
/* Likewise, copy storage if requested */
if (inhRelation->options & CREATE_TABLE_LIKE_STORAGE)
def->storage = attribute->attstorage;
/* Likewise, copy comment if requested */
if ((inhRelation->options & CREATE_TABLE_LIKE_COMMENTS) &&
(comment = GetComment(attribute->attrelid, RelationRelationId,
attribute->attnum)) != NULL)
{
CommentStmt *stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_COLUMN;
stmt->objname = list_make3(makeString(cxt->relation->schemaname),
makeString(cxt->relation->relname),
makeString(def->colname));
stmt->objargs = NIL;
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
}
} }
/* /*
* Copy CHECK constraints if requested, being careful to adjust attribute * Copy CHECK constraints if requested, being careful to adjust attribute
* numbers * numbers
*/ */
if (including_constraints && tupleDesc->constr) if ((inhRelation->options & CREATE_TABLE_LIKE_CONSTRAINTS) && tupleDesc->constr)
{ {
AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns); AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns);
int ccnum; int ccnum;
...@@ -694,13 +685,31 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -694,13 +685,31 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
n->raw_expr = NULL; n->raw_expr = NULL;
n->cooked_expr = nodeToString(ccbin_node); n->cooked_expr = nodeToString(ccbin_node);
cxt->ckconstraints = lappend(cxt->ckconstraints, n); cxt->ckconstraints = lappend(cxt->ckconstraints, n);
/* Copy comment on constraint */
if ((inhRelation->options & CREATE_TABLE_LIKE_COMMENTS) &&
(comment = GetComment(GetConstraintByName(RelationGetRelid(
relation), n->conname), ConstraintRelationId, 0)) != NULL)
{
CommentStmt *stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_CONSTRAINT;
stmt->objname = list_make3(makeString(cxt->relation->schemaname),
makeString(cxt->relation->relname),
makeString(n->conname));
stmt->objargs = NIL;
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
}
} }
} }
/* /*
* Likewise, copy indexes if requested * Likewise, copy indexes if requested
*/ */
if (including_indexes && relation->rd_rel->relhasindex) if ((inhRelation->options & CREATE_TABLE_LIKE_INDEXES) &&
relation->rd_rel->relhasindex)
{ {
AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns); AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns);
List *parent_indexes; List *parent_indexes;
...@@ -719,6 +728,68 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -719,6 +728,68 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
/* Build CREATE INDEX statement to recreate the parent_index */ /* Build CREATE INDEX statement to recreate the parent_index */
index_stmt = generateClonedIndexStmt(cxt, parent_index, attmap); index_stmt = generateClonedIndexStmt(cxt, parent_index, attmap);
/* Copy comment on index */
if (inhRelation->options & CREATE_TABLE_LIKE_COMMENTS)
{
CommentStmt *stmt;
ListCell *lc;
int i;
comment = GetComment(parent_index_oid, RelationRelationId, 0);
if (comment != NULL)
{
/* Assign name for index because CommentStmt requires name. */
if (index_stmt->idxname == NULL)
index_stmt->idxname = chooseIndexName(cxt->relation, index_stmt);
stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_INDEX;
stmt->objname = list_make2(makeString(cxt->relation->schemaname),
makeString(index_stmt->idxname));
stmt->objargs = NIL;
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
}
/* Copy comment on index's columns */
i = 0;
foreach(lc, index_stmt->indexParams)
{
char *attname;
i++;
comment = GetComment(parent_index_oid, RelationRelationId, i);
if (comment == NULL)
continue;
/* Assign name for index because CommentStmt requires name. */
if (index_stmt->idxname == NULL)
index_stmt->idxname = chooseIndexName(cxt->relation, index_stmt);
attname = ((IndexElem *) lfirst(lc))->name;
/* expression index has a dummy column name */
if (attname == NULL)
{
attname = palloc(NAMEDATALEN);
sprintf(attname, "pg_expression_%d", i);
}
stmt = makeNode(CommentStmt);
stmt->objtype = OBJECT_COLUMN;
stmt->objname = list_make3(
makeString(cxt->relation->schemaname),
makeString(index_stmt->idxname),
makeString(attname));
stmt->objargs = NIL;
stmt->comment = comment;
cxt->alist = lappend(cxt->alist, stmt);
}
}
/* Save it in the inh_indexes list for the time being */ /* Save it in the inh_indexes list for the time being */
cxt->inh_indexes = lappend(cxt->inh_indexes, index_stmt); cxt->inh_indexes = lappend(cxt->inh_indexes, index_stmt);
...@@ -734,6 +805,32 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, ...@@ -734,6 +805,32 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
heap_close(relation, NoLock); heap_close(relation, NoLock);
} }
/*
* chooseIndexName
*
* Set name to unnamed index. See also the same logic in DefineIndex.
*/
static char *
chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt)
{
Oid namespaceId;
namespaceId = RangeVarGetCreationNamespace(relation);
if (index_stmt->primary)
{
/* no need for column list with pkey */
return ChooseRelationName(relation->relname, NULL,
"pkey", namespaceId);
}
else
{
IndexElem *iparam = (IndexElem *) linitial(index_stmt->indexParams);
return ChooseRelationName(relation->relname, iparam->name,
"key", namespaceId);
}
}
/* /*
* Generate an IndexStmt node using information from an already existing index * Generate an IndexStmt node using information from an already existing index
* "source_idx". Attribute numbers should be adjusted according to attmap. * "source_idx". Attribute numbers should be adjusted according to attmap.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.32 2009/07/28 02:56:31 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.33 2009/10/12 19:49:24 adunstan Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -226,5 +226,6 @@ extern char *ChooseConstraintName(const char *name1, const char *name2, ...@@ -226,5 +226,6 @@ extern char *ChooseConstraintName(const char *name1, const char *name2,
extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
Oid newNspId, bool isType); Oid newNspId, bool isType);
extern Oid GetConstraintByName(Oid relid, const char *conname);
#endif /* PG_CONSTRAINT_H */ #endif /* PG_CONSTRAINT_H */
/* /*
* $PostgreSQL: pgsql/src/include/commands/comment.h,v 1.24 2009/06/11 14:49:11 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/comment.h,v 1.25 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
* *
...@@ -39,4 +39,6 @@ extern void DeleteSharedComments(Oid oid, Oid classoid); ...@@ -39,4 +39,6 @@ extern void DeleteSharedComments(Oid oid, Oid classoid);
extern void CreateSharedComments(Oid oid, Oid classoid, char *comment); extern void CreateSharedComments(Oid oid, Oid classoid, char *comment);
extern char *GetComment(Oid oid, Oid classoid, int32 subid);
#endif /* COMMENT_H */ #endif /* COMMENT_H */
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.406 2009/10/12 18:10:51 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.407 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -460,6 +460,7 @@ typedef struct ColumnDef ...@@ -460,6 +460,7 @@ typedef struct ColumnDef
int inhcount; /* number of times column is inherited */ int inhcount; /* number of times column is inherited */
bool is_local; /* column has local (non-inherited) def'n */ bool is_local; /* column has local (non-inherited) def'n */
bool is_not_null; /* NOT NULL constraint specified? */ bool is_not_null; /* NOT NULL constraint specified? */
char storage; /* storage parameter of column */
Node *raw_default; /* default value (untransformed parse tree) */ Node *raw_default; /* default value (untransformed parse tree) */
Node *cooked_default; /* default value (transformed expr tree) */ Node *cooked_default; /* default value (transformed expr tree) */
List *constraints; /* other constraints on column */ List *constraints; /* other constraints on column */
...@@ -472,17 +473,17 @@ typedef struct InhRelation ...@@ -472,17 +473,17 @@ typedef struct InhRelation
{ {
NodeTag type; NodeTag type;
RangeVar *relation; RangeVar *relation;
List *options; /* integer List of CreateStmtLikeOption */ bits32 options; /* bitmap of CreateStmtLikeOption */
} InhRelation; } InhRelation;
typedef enum CreateStmtLikeOption typedef enum CreateStmtLikeOption
{ {
CREATE_TABLE_LIKE_INCLUDING_DEFAULTS, CREATE_TABLE_LIKE_DEFAULTS = 1 << 0,
CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS, CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 1,
CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS, CREATE_TABLE_LIKE_INDEXES = 1 << 2,
CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS, CREATE_TABLE_LIKE_STORAGE = 1 << 3,
CREATE_TABLE_LIKE_INCLUDING_INDEXES, CREATE_TABLE_LIKE_COMMENTS = 1 << 4,
CREATE_TABLE_LIKE_EXCLUDING_INDEXES CREATE_TABLE_LIKE_ALL = 0xFFFFFFFF
} CreateStmtLikeOption; } CreateStmtLikeOption;
/* /*
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.3 2009/09/22 23:43:41 tgl Exp $ * $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.4 2009/10/12 19:49:24 adunstan Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -80,6 +80,7 @@ PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD) ...@@ -80,6 +80,7 @@ PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD)
PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD) PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD)
PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD) PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD)
PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD) PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD)
PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD)
PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD) PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD)
PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD) PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD)
PG_KEYWORD("concurrently", CONCURRENTLY, UNRESERVED_KEYWORD) PG_KEYWORD("concurrently", CONCURRENTLY, UNRESERVED_KEYWORD)
......
...@@ -921,3 +921,139 @@ drop table pp1 cascade; ...@@ -921,3 +921,139 @@ drop table pp1 cascade;
NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table cc1 DETAIL: drop cascades to table cc1
drop cascades to table cc2 drop cascades to table cc2
-- including storage and comments
CREATE TABLE t1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t1_pkey" for table "t1"
CREATE INDEX t1_b_key ON t1 (b);
CREATE INDEX t1_fnidx ON t1 ((a || b));
COMMENT ON COLUMN t1.a IS 'A';
COMMENT ON COLUMN t1.b IS 'B';
COMMENT ON CONSTRAINT t1_a_check ON t1 IS 't1_a_check';
COMMENT ON INDEX t1_pkey IS 'index pkey';
COMMENT ON INDEX t1_b_key IS 'index b_key';
COMMENT ON COLUMN t1_pkey.a IS 'index column pkey.a';
COMMENT ON COLUMN t1_fnidx.pg_expression_1 IS 'index column fnidx';
ALTER TABLE t1 ALTER COLUMN a SET STORAGE MAIN;
CREATE TABLE t2 (c text);
ALTER TABLE t2 ALTER COLUMN c SET STORAGE EXTERNAL;
COMMENT ON COLUMN t2.c IS 'C';
CREATE TABLE t3 (a text CHECK (length(a) < 5), c text);
ALTER TABLE t3 ALTER COLUMN c SET STORAGE EXTERNAL;
ALTER TABLE t3 ALTER COLUMN a SET STORAGE MAIN;
COMMENT ON COLUMN t3.a IS 'A3';
COMMENT ON COLUMN t3.c IS 'C';
COMMENT ON CONSTRAINT t3_a_check ON t3 IS 't3_a_check';
CREATE TABLE t4 (a text, c text);
ALTER TABLE t4 ALTER COLUMN c SET STORAGE EXTERNAL;
CREATE TABLE t12_storage (LIKE t1 INCLUDING STORAGE, LIKE t2 INCLUDING STORAGE);
\d+ t12_storage
Table "public.t12_storage"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | main |
b | text | | extended |
c | text | | external |
Has OIDs: no
CREATE TABLE t12_comments (LIKE t1 INCLUDING COMMENTS, LIKE t2 INCLUDING COMMENTS);
\d+ t12_comments
Table "public.t12_comments"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | extended | A
b | text | | extended | B
c | text | | extended | C
Has OIDs: no
CREATE TABLE t1_inh (LIKE t1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) INHERITS (t1);
NOTICE: merging column "a" with inherited definition
NOTICE: merging column "b" with inherited definition
NOTICE: merging constraint "t1_a_check" with inherited definition
\d+ t1_inh
Table "public.t1_inh"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | main | A
b | text | | extended | B
Check constraints:
"t1_a_check" CHECK (length(a) > 2)
Inherits: t1
Has OIDs: no
SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 't1_inh'::regclass;
description
-------------
t1_a_check
(1 row)
CREATE TABLE t13_inh () INHERITS (t1, t3);
NOTICE: merging multiple inherited definitions of column "a"
\d+ t13_inh
Table "public.t13_inh"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | main |
b | text | | extended |
c | text | | external |
Check constraints:
"t1_a_check" CHECK (length(a) > 2)
"t3_a_check" CHECK (length(a) < 5)
Inherits: t1,
t3
Has OIDs: no
CREATE TABLE t13_like (LIKE t3 INCLUDING CONSTRAINTS INCLUDING COMMENTS INCLUDING STORAGE) INHERITS (t1);
NOTICE: merging column "a" with inherited definition
\d+ t13_like
Table "public.t13_like"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | main | A3
b | text | | extended |
c | text | | external | C
Check constraints:
"t1_a_check" CHECK (length(a) > 2)
"t3_a_check" CHECK (length(a) < 5)
Inherits: t1
Has OIDs: no
SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 't13_like'::regclass;
description
-------------
t3_a_check
(1 row)
CREATE TABLE t_all (LIKE t1 INCLUDING ALL);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_all_pkey" for table "t_all"
\d+ t_all
Table "public.t_all"
Column | Type | Modifiers | Storage | Description
--------+------+-----------+----------+-------------
a | text | not null | main | A
b | text | | extended | B
Indexes:
"t_all_pkey" PRIMARY KEY, btree (a)
"t_all_b_key" btree (b)
"t_all_key" btree ((a || b))
Check constraints:
"t1_a_check" CHECK (length(a) > 2)
Has OIDs: no
SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 't_all'::regclass ORDER BY c.relname, objsubid;
relname | objsubid | description
-------------+----------+---------------------
t_all_b_key | 0 | index b_key
t_all_key | 1 | index column fnidx
t_all_pkey | 0 | index pkey
t_all_pkey | 1 | index column pkey.a
(4 rows)
CREATE TABLE inh_error1 () INHERITS (t1, t4);
NOTICE: merging multiple inherited definitions of column "a"
ERROR: inherited column "a" has a storage parameter conflict
DETAIL: MAIN versus EXTENDED
CREATE TABLE inh_error2 (LIKE t4 INCLUDING STORAGE) INHERITS (t1);
NOTICE: merging column "a" with inherited definition
ERROR: column "a" has a storage parameter conflict
DETAIL: MAIN versus EXTENDED
DROP TABLE t1, t2, t3, t4, t12_storage, t12_comments, t1_inh, t13_inh, t13_like, t_all;
...@@ -287,3 +287,52 @@ create table cc2(f4 float) inherits(pp1,cc1); ...@@ -287,3 +287,52 @@ create table cc2(f4 float) inherits(pp1,cc1);
alter table pp1 add column a2 int check (a2 > 0); alter table pp1 add column a2 int check (a2 > 0);
\d cc2 \d cc2
drop table pp1 cascade; drop table pp1 cascade;
-- including storage and comments
CREATE TABLE t1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text);
CREATE INDEX t1_b_key ON t1 (b);
CREATE INDEX t1_fnidx ON t1 ((a || b));
COMMENT ON COLUMN t1.a IS 'A';
COMMENT ON COLUMN t1.b IS 'B';
COMMENT ON CONSTRAINT t1_a_check ON t1 IS 't1_a_check';
COMMENT ON INDEX t1_pkey IS 'index pkey';
COMMENT ON INDEX t1_b_key IS 'index b_key';
COMMENT ON COLUMN t1_pkey.a IS 'index column pkey.a';
COMMENT ON COLUMN t1_fnidx.pg_expression_1 IS 'index column fnidx';
ALTER TABLE t1 ALTER COLUMN a SET STORAGE MAIN;
CREATE TABLE t2 (c text);
ALTER TABLE t2 ALTER COLUMN c SET STORAGE EXTERNAL;
COMMENT ON COLUMN t2.c IS 'C';
CREATE TABLE t3 (a text CHECK (length(a) < 5), c text);
ALTER TABLE t3 ALTER COLUMN c SET STORAGE EXTERNAL;
ALTER TABLE t3 ALTER COLUMN a SET STORAGE MAIN;
COMMENT ON COLUMN t3.a IS 'A3';
COMMENT ON COLUMN t3.c IS 'C';
COMMENT ON CONSTRAINT t3_a_check ON t3 IS 't3_a_check';
CREATE TABLE t4 (a text, c text);
ALTER TABLE t4 ALTER COLUMN c SET STORAGE EXTERNAL;
CREATE TABLE t12_storage (LIKE t1 INCLUDING STORAGE, LIKE t2 INCLUDING STORAGE);
\d+ t12_storage
CREATE TABLE t12_comments (LIKE t1 INCLUDING COMMENTS, LIKE t2 INCLUDING COMMENTS);
\d+ t12_comments
CREATE TABLE t1_inh (LIKE t1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) INHERITS (t1);
\d+ t1_inh
SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 't1_inh'::regclass;
CREATE TABLE t13_inh () INHERITS (t1, t3);
\d+ t13_inh
CREATE TABLE t13_like (LIKE t3 INCLUDING CONSTRAINTS INCLUDING COMMENTS INCLUDING STORAGE) INHERITS (t1);
\d+ t13_like
SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 't13_like'::regclass;
CREATE TABLE t_all (LIKE t1 INCLUDING ALL);
\d+ t_all
SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 't_all'::regclass ORDER BY c.relname, objsubid;
CREATE TABLE inh_error1 () INHERITS (t1, t4);
CREATE TABLE inh_error2 (LIKE t4 INCLUDING STORAGE) INHERITS (t1);
DROP TABLE t1, t2, t3, t4, t12_storage, t12_comments, t1_inh, t13_inh, t13_like, t_all;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册