mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
CREATE LIKE INCLUDING COMMENTS and STORAGE, and INCLUDING ALL shortcut. Itagaki Takahiro.
This commit is contained in:
parent
0adaf4cb31
commit
faa1afc6c1
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$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
|
|||||||
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
|
|||||||
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
|
|||||||
</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
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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);
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 @@
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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
|
|||||||
_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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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);
|
|||||||
%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);
|
|||||||
|
|
||||||
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:
|
|||||||
;
|
;
|
||||||
|
|
||||||
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:
|
|||||||
| CLOSE
|
| CLOSE
|
||||||
| CLUSTER
|
| CLUSTER
|
||||||
| COMMENT
|
| COMMENT
|
||||||
|
| COMMENTS
|
||||||
| COMMIT
|
| COMMIT
|
||||||
| COMMITTED
|
| COMMITTED
|
||||||
| CONCURRENTLY
|
| CONCURRENTLY
|
||||||
|
@ -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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
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 @@
|
|||||||
* 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,
|
|||||||
|
|
||||||
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 */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $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);
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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
|
|||||||
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
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
* 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)
|
|||||||
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;
|
|||||||
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);
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user