mirror of
https://github.com/postgres/postgres.git
synced 2025-08-25 20:23:07 +03:00
CREATE LIKE INCLUDING COMMENTS and STORAGE, and INCLUDING ALL shortcut. Itagaki Takahiro.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 --
|
||||
*
|
||||
@@ -1064,12 +1119,8 @@ CommentConstraint(List *qualname, char *comment)
|
||||
List *relName;
|
||||
char *conName;
|
||||
RangeVar *rel;
|
||||
Relation pg_constraint,
|
||||
relation;
|
||||
HeapTuple tuple;
|
||||
SysScanDesc scan;
|
||||
ScanKeyData skey[1];
|
||||
Oid conOid = InvalidOid;
|
||||
Relation relation;
|
||||
Oid conOid;
|
||||
|
||||
/* Separate relname and constraint name */
|
||||
nnames = list_length(qualname);
|
||||
@@ -1088,50 +1139,12 @@ CommentConstraint(List *qualname, char *comment)
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
|
||||
RelationGetRelationName(relation));
|
||||
|
||||
/*
|
||||
* 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))));
|
||||
conOid = GetConstraintByName(RelationGetRelid(relation), conName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(conOid, ConstraintRelationId, 0, comment);
|
||||
|
||||
/* Done, but hold lock on relation */
|
||||
heap_close(pg_constraint, AccessShareLock);
|
||||
heap_close(relation, NoLock);
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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/toasting.h"
|
||||
#include "commands/cluster.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "commands/sequence.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 copy_relation_data(SMgrRelation rel, SMgrRelation dst,
|
||||
ForkNumber forkNum, bool istemp);
|
||||
static const char * storage_name(char c);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@@ -1100,6 +1102,25 @@ truncate_check_rel(Relation rel)
|
||||
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
|
||||
* Returns new schema given initial schema and superclasses.
|
||||
@@ -1168,6 +1189,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
List *constraints = NIL;
|
||||
int parentsWithOids = 0;
|
||||
bool have_bogus_defaults = false;
|
||||
bool have_bogus_comments = false;
|
||||
int child_attno;
|
||||
static Node bogus_marker = { 0 }; /* marks conflicting defaults */
|
||||
|
||||
@@ -1323,6 +1345,18 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
errdetail("%s versus %s",
|
||||
TypeNameToString(def->typeName),
|
||||
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++;
|
||||
/* Merge of NOT NULL constraints = OR 'em together */
|
||||
def->is_not_null |= attribute->attnotnull;
|
||||
@@ -1344,6 +1378,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
def->raw_default = NULL;
|
||||
def->cooked_default = NULL;
|
||||
def->constraints = NIL;
|
||||
def->storage = attribute->attstorage;
|
||||
inhSchema = lappend(inhSchema, def);
|
||||
newattno[parent_attno - 1] = ++child_attno;
|
||||
}
|
||||
@@ -1481,6 +1516,18 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
errdetail("%s versus %s",
|
||||
TypeNameToString(def->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 */
|
||||
def->is_local = true;
|
||||
/* 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;
|
||||
*supconstr = constraints;
|
||||
*supOidCount = parentsWithOids;
|
||||
|
Reference in New Issue
Block a user