mirror of
https://github.com/postgres/postgres.git
synced 2025-06-17 17:02:08 +03:00
CREATE LIKE INCLUDING COMMENTS and STORAGE, and INCLUDING ALL shortcut. Itagaki Takahiro.
This commit is contained in:
@ -19,7 +19,7 @@
|
||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||
* 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_opclass.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "commands/tablecmds.h"
|
||||
#include "commands/tablespace.h"
|
||||
@ -101,6 +102,7 @@ static void transformTableConstraint(ParseState *pstate,
|
||||
Constraint *constraint);
|
||||
static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
InhRelation *inhrelation);
|
||||
static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt);
|
||||
static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
|
||||
Relation parent_index, AttrNumber *attmap);
|
||||
static List *get_opclass(Oid opclass, Oid actual_datatype);
|
||||
@ -546,10 +548,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
TupleDesc tupleDesc;
|
||||
TupleConstr *constr;
|
||||
AclResult aclresult;
|
||||
bool including_defaults = false;
|
||||
bool including_constraints = false;
|
||||
bool including_indexes = false;
|
||||
ListCell *elem;
|
||||
char *comment;
|
||||
|
||||
relation = parserOpenTable(pstate, inhRelation->relation, AccessShareLock);
|
||||
|
||||
@ -571,36 +570,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
tupleDesc = RelationGetDescr(relation);
|
||||
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.
|
||||
*/
|
||||
@ -642,7 +611,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
/*
|
||||
* 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;
|
||||
AttrDefault *attrdef;
|
||||
@ -668,13 +638,34 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
|
||||
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
|
||||
* numbers
|
||||
*/
|
||||
if (including_constraints && tupleDesc->constr)
|
||||
if ((inhRelation->options & CREATE_TABLE_LIKE_CONSTRAINTS) && tupleDesc->constr)
|
||||
{
|
||||
AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns);
|
||||
int ccnum;
|
||||
@ -694,13 +685,31 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
n->raw_expr = NULL;
|
||||
n->cooked_expr = nodeToString(ccbin_node);
|
||||
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
|
||||
*/
|
||||
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);
|
||||
List *parent_indexes;
|
||||
@ -719,6 +728,68 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
/* Build CREATE INDEX statement to recreate the parent_index */
|
||||
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 */
|
||||
cxt->inh_indexes = lappend(cxt->inh_indexes, index_stmt);
|
||||
|
||||
@ -734,6 +805,32 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
|
||||
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
|
||||
* "source_idx". Attribute numbers should be adjusted according to attmap.
|
||||
|
Reference in New Issue
Block a user