1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-03 15:22:11 +03:00

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

This commit is contained in:
Andrew Dunstan
2009-10-12 19:49:24 +00:00
parent 0adaf4cb31
commit faa1afc6c1
15 changed files with 564 additions and 117 deletions

View File

@@ -11,7 +11,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@@ -407,8 +407,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <keyword> col_name_keyword reserved_keyword
%type <node> TableConstraint TableLikeClause
%type <list> TableLikeOptionList
%type <ival> TableLikeOption
%type <ival> TableLikeOptionList TableLikeOption
%type <list> ColQualList
%type <node> ColConstraint ColConstraintElem ConstraintAttr
%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
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
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P
@@ -2417,17 +2416,18 @@ TableLikeClause:
;
TableLikeOptionList:
TableLikeOptionList TableLikeOption { $$ = lappend_int($1, $2); }
| /* EMPTY */ { $$ = NIL; }
TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; }
| TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; }
| /* EMPTY */ { $$ = 0; }
;
TableLikeOption:
INCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_INCLUDING_DEFAULTS; }
| EXCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS; }
| INCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS; }
| EXCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS; }
| INCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_INCLUDING_INDEXES; }
| EXCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_EXCLUDING_INDEXES; }
DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
| STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
| COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| ALL { $$ = CREATE_TABLE_LIKE_ALL; }
;
@@ -10481,6 +10481,7 @@ unreserved_keyword:
| CLOSE
| CLUSTER
| COMMENT
| COMMENTS
| COMMIT
| COMMITTED
| CONCURRENTLY

View File

@@ -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.