aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/bootstrap/bootparse.y3
-rw-r--r--src/backend/catalog/index.c22
-rw-r--r--src/backend/catalog/toasting.c3
-rw-r--r--src/backend/commands/indexcmds.c220
-rw-r--r--src/backend/nodes/copyfuncs.c3
-rw-r--r--src/backend/nodes/equalfuncs.c3
-rw-r--r--src/backend/nodes/outfuncs.c3
-rw-r--r--src/backend/parser/gram.y5
-rw-r--r--src/backend/parser/parse_target.c31
-rw-r--r--src/backend/parser/parse_utilcmd.c47
-rw-r--r--src/include/catalog/index.h3
-rw-r--r--src/include/commands/defrem.h6
-rw-r--r--src/include/nodes/parsenodes.h3
-rw-r--r--src/include/parser/parse_target.h3
-rw-r--r--src/test/regress/expected/alter_table.out2
-rw-r--r--src/test/regress/expected/foreign_key.out6
-rw-r--r--src/test/regress/expected/inherit.out6
-rw-r--r--src/test/regress/output/constraints.source12
18 files changed, 277 insertions, 104 deletions
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 18affeb0988..5c85fcff5ef 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.101 2009/12/07 05:22:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.102 2009/12/23 02:35:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -323,6 +323,7 @@ boot_index_param:
IndexElem *n = makeNode(IndexElem);
n->name = $1;
n->expr = NULL;
+ n->indexcolname = NULL;
n->opclass = list_make1(makeString($2));
n->ordering = SORTBY_DEFAULT;
n->nulls_ordering = SORTBY_NULLS_DEFAULT;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5394d2557eb..9eb96b7718d 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.326 2009/12/09 21:57:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.327 2009/12/23 02:35:18 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -82,6 +82,7 @@ typedef struct
/* non-export function prototypes */
static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
IndexInfo *indexInfo,
+ List *indexColNames,
Oid accessMethodObjectId,
Oid *classObjectId);
static void InitializeAttributeOids(Relation indexRelation,
@@ -117,10 +118,12 @@ static Oid IndexGetRelation(Oid indexId);
static TupleDesc
ConstructTupleDescriptor(Relation heapRelation,
IndexInfo *indexInfo,
+ List *indexColNames,
Oid accessMethodObjectId,
Oid *classObjectId)
{
int numatts = indexInfo->ii_NumIndexAttrs;
+ ListCell *colnames_item = list_head(indexColNames);
ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
HeapTuple amtuple;
Form_pg_am amform;
@@ -217,12 +220,6 @@ ConstructTupleDescriptor(Relation heapRelation,
indexpr_item = lnext(indexpr_item);
/*
- * Make the attribute's name "pg_expresssion_nnn" (maybe think of
- * something better later)
- */
- sprintf(NameStr(to->attname), "pg_expression_%d", i + 1);
-
- /*
* Lookup the expression type in pg_type for the type length etc.
*/
keyType = exprType(indexkey);
@@ -269,6 +266,14 @@ ConstructTupleDescriptor(Relation heapRelation,
to->attrelid = InvalidOid;
/*
+ * Set the attribute name as specified by caller.
+ */
+ if (colnames_item == NULL) /* shouldn't happen */
+ elog(ERROR, "too few entries in colnames list");
+ namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
+ colnames_item = lnext(colnames_item);
+
+ /*
* Check the opclass and index AM to see if either provides a keytype
* (overriding the attribute type). Opclass takes precedence.
*/
@@ -494,6 +499,7 @@ UpdateIndexRelation(Oid indexoid,
* generate an OID for the index. During bootstrap this may be
* nonzero to specify a preselected OID.
* indexInfo: same info executor uses to insert into the index
+ * indexColNames: column names to use for index (List of char *)
* accessMethodObjectId: OID of index AM to use
* tableSpaceId: OID of tablespace to use
* classObjectId: array of index opclass OIDs, one per index column
@@ -517,6 +523,7 @@ index_create(Oid heapRelationId,
const char *indexRelationName,
Oid indexRelationId,
IndexInfo *indexInfo,
+ List *indexColNames,
Oid accessMethodObjectId,
Oid tableSpaceId,
Oid *classObjectId,
@@ -629,6 +636,7 @@ index_create(Oid heapRelationId,
*/
indexTupDesc = ConstructTupleDescriptor(heapRelation,
indexInfo,
+ indexColNames,
accessMethodObjectId,
classObjectId);
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 05f3bb49691..a8c2da66dc3 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.21 2009/12/07 05:22:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.22 2009/12/23 02:35:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -255,6 +255,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
toast_idxid = index_create(toast_relid, toast_idxname, toastIndexOid,
indexInfo,
+ list_make2("chunk_id", "chunk_seq"),
BTREE_AM_OID,
rel->rd_rel->reltablespace,
classObjectId, coloptions, (Datum) 0,
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 00786442b3f..833114abcf0 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.188 2009/12/07 05:22:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.189 2009/12/23 02:35:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,6 +67,7 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo,
bool isconstraint);
static Oid GetIndexOpClass(List *opclass, Oid attrType,
char *accessMethodName, Oid accessMethodId);
+static char *ChooseIndexNameAddition(List *colnames);
static bool relationHasPrimaryKey(Relation rel);
@@ -128,6 +129,7 @@ DefineIndex(RangeVar *heapRelation,
Oid relationId;
Oid namespaceId;
Oid tablespaceId;
+ List *indexColNames;
Relation rel;
Relation indexRelation;
HeapTuple tuple;
@@ -248,36 +250,20 @@ DefineIndex(RangeVar *heapRelation,
tablespaceId = GLOBALTABLESPACE_OID;
/*
+ * Choose the index column names.
+ */
+ indexColNames = ChooseIndexColumnNames(attributeList);
+
+ /*
* Select name for index if caller didn't specify
*/
if (indexRelationName == NULL)
- {
- if (primary)
- {
- indexRelationName = ChooseRelationName(RelationGetRelationName(rel),
- NULL,
- "pkey",
- namespaceId);
- }
- else if (exclusionOpNames != NIL)
- {
- IndexElem *iparam = (IndexElem *) linitial(attributeList);
-
- indexRelationName = ChooseRelationName(RelationGetRelationName(rel),
- iparam->name,
- "exclusion",
- namespaceId);
- }
- else
- {
- IndexElem *iparam = (IndexElem *) linitial(attributeList);
-
- indexRelationName = ChooseRelationName(RelationGetRelationName(rel),
- iparam->name,
- "key",
- namespaceId);
- }
- }
+ indexRelationName = ChooseIndexName(RelationGetRelationName(rel),
+ namespaceId,
+ indexColNames,
+ exclusionOpNames,
+ primary,
+ isconstraint);
/*
* look up the access method, verify it can handle the requested features
@@ -488,35 +474,30 @@ DefineIndex(RangeVar *heapRelation,
SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
heap_close(rel, NoLock);
- if (!concurrent)
- {
- indexRelationId =
- index_create(relationId, indexRelationName, indexRelationId,
- indexInfo, accessMethodId, tablespaceId, classObjectId,
- coloptions, reloptions, primary,
- isconstraint, deferrable, initdeferred,
- allowSystemTableMods, skip_build, concurrent);
-
- return; /* We're done, in the standard case */
- }
-
/*
- * For a concurrent build, we next insert the catalog entry and add
- * constraints. We don't build the index just yet; we must first make the
- * catalog entry so that the new index is visible to updating
- * transactions. That will prevent them from making incompatible HOT
- * updates. The new index will be marked not indisready and not
- * indisvalid, so that no one else tries to either insert into it or use
- * it for queries. We pass skip_build = true to prevent the build.
+ * Make the catalog entries for the index, including constraints.
+ * Then, if not skip_build || concurrent, actually build the index.
*/
indexRelationId =
index_create(relationId, indexRelationName, indexRelationId,
- indexInfo, accessMethodId, tablespaceId, classObjectId,
+ indexInfo, indexColNames,
+ accessMethodId, tablespaceId, classObjectId,
coloptions, reloptions, primary,
isconstraint, deferrable, initdeferred,
- allowSystemTableMods, true, concurrent);
+ allowSystemTableMods,
+ skip_build || concurrent,
+ concurrent);
+
+ if (!concurrent)
+ return; /* We're done, in the standard case */
/*
+ * For a concurrent build, it's important to make the catalog entries
+ * visible to other transactions before we start to build the index.
+ * That will prevent them from making incompatible HOT updates. The new
+ * index will be marked not indisready and not indisvalid, so that no one
+ * else tries to either insert into it or use it for queries.
+ *
* We must commit our current transaction so that the index becomes
* visible; then start another. Note that all the data structures we just
* built are lost in the commit. The only data we keep past here are the
@@ -1392,6 +1373,147 @@ ChooseRelationName(const char *name1, const char *name2,
}
/*
+ * Select the name to be used for an index.
+ *
+ * The argument list is pretty ad-hoc :-(
+ */
+char *
+ChooseIndexName(const char *tabname, Oid namespaceId,
+ List *colnames, List *exclusionOpNames,
+ bool primary, bool isconstraint)
+{
+ char *indexname;
+
+ if (primary)
+ {
+ /* the primary key's name does not depend on the specific column(s) */
+ indexname = ChooseRelationName(tabname,
+ NULL,
+ "pkey",
+ namespaceId);
+ }
+ else if (exclusionOpNames != NIL)
+ {
+ indexname = ChooseRelationName(tabname,
+ ChooseIndexNameAddition(colnames),
+ "exclusion",
+ namespaceId);
+ }
+ else if (isconstraint)
+ {
+ indexname = ChooseRelationName(tabname,
+ ChooseIndexNameAddition(colnames),
+ "key",
+ namespaceId);
+ }
+ else
+ {
+ indexname = ChooseRelationName(tabname,
+ ChooseIndexNameAddition(colnames),
+ "idx",
+ namespaceId);
+ }
+
+ return indexname;
+}
+
+/*
+ * Generate "name2" for a new index given the list of column names for it
+ * (as produced by ChooseIndexColumnNames). This will be passed to
+ * ChooseRelationName along with the parent table name and a suitable label.
+ *
+ * We know that less than NAMEDATALEN characters will actually be used,
+ * so we can truncate the result once we've generated that many.
+ */
+static char *
+ChooseIndexNameAddition(List *colnames)
+{
+ char buf[NAMEDATALEN * 2];
+ int buflen = 0;
+ ListCell *lc;
+
+ buf[0] = '\0';
+ foreach(lc, colnames)
+ {
+ const char *name = (const char *) lfirst(lc);
+
+ if (buflen > 0)
+ buf[buflen++] = '_'; /* insert _ between names */
+
+ /*
+ * At this point we have buflen <= NAMEDATALEN. name should be less
+ * than NAMEDATALEN already, but use strlcpy for paranoia.
+ */
+ strlcpy(buf + buflen, name, NAMEDATALEN);
+ buflen += strlen(buf + buflen);
+ if (buflen >= NAMEDATALEN)
+ break;
+ }
+ return pstrdup(buf);
+}
+
+/*
+ * Select the actual names to be used for the columns of an index, given the
+ * list of IndexElems for the columns. This is mostly about ensuring the
+ * names are unique so we don't get a conflicting-attribute-names error.
+ *
+ * Returns a List of plain strings (char *, not String nodes).
+ */
+List *
+ChooseIndexColumnNames(List *indexElems)
+{
+ List *result = NIL;
+ ListCell *lc;
+
+ foreach(lc, indexElems)
+ {
+ IndexElem *ielem = (IndexElem *) lfirst(lc);
+ const char *origname;
+ const char *curname;
+ int i;
+ char buf[NAMEDATALEN];
+
+ /* Get the preliminary name from the IndexElem */
+ if (ielem->indexcolname)
+ origname = ielem->indexcolname; /* caller-specified name */
+ else if (ielem->name)
+ origname = ielem->name; /* simple column reference */
+ else
+ origname = "expr"; /* default name for expression */
+
+ /* If it conflicts with any previous column, tweak it */
+ curname = origname;
+ for (i = 1;; i++)
+ {
+ ListCell *lc2;
+ char nbuf[32];
+ int nlen;
+
+ foreach(lc2, result)
+ {
+ if (strcmp(curname, (char *) lfirst(lc2)) == 0)
+ break;
+ }
+ if (lc2 == NULL)
+ break; /* found nonconflicting name */
+
+ sprintf(nbuf, "%d", i);
+
+ /* Ensure generated names are shorter than NAMEDATALEN */
+ nlen = pg_mbcliplen(origname, strlen(origname),
+ NAMEDATALEN - 1 - strlen(nbuf));
+ memcpy(buf, origname, nlen);
+ strcpy(buf + nlen, nbuf);
+ curname = buf;
+ }
+
+ /* And attach to the result list */
+ result = lappend(result, pstrdup(curname));
+ }
+ return result;
+}
+
+/*
* relationHasPrimaryKey -
*
* See whether an existing relation has a primary key.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 018f36cef60..2722a93e074 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.454 2009/12/15 17:57:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.455 2009/12/23 02:35:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2121,6 +2121,7 @@ _copyIndexElem(IndexElem *from)
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(expr);
+ COPY_STRING_FIELD(indexcolname);
COPY_NODE_FIELD(opclass);
COPY_SCALAR_FIELD(ordering);
COPY_SCALAR_FIELD(nulls_ordering);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 2387aaba410..e53b4a89e6e 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.376 2009/12/15 17:57:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.377 2009/12/23 02:35:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2072,6 +2072,7 @@ _equalIndexElem(IndexElem *a, IndexElem *b)
{
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(expr);
+ COMPARE_STRING_FIELD(indexcolname);
COMPARE_NODE_FIELD(opclass);
COMPARE_SCALAR_FIELD(ordering);
COMPARE_SCALAR_FIELD(nulls_ordering);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index cac346464bd..419c005b508 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.375 2009/12/15 17:57:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.376 2009/12/23 02:35:21 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1946,6 +1946,7 @@ _outIndexElem(StringInfo str, IndexElem *node)
WRITE_STRING_FIELD(name);
WRITE_NODE_FIELD(expr);
+ WRITE_STRING_FIELD(indexcolname);
WRITE_NODE_FIELD(opclass);
WRITE_ENUM_FIELD(ordering, SortByDir);
WRITE_ENUM_FIELD(nulls_ordering, SortByNulls);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 22449579d0f..7ff46e05cb1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.697 2009/12/15 17:57:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.698 2009/12/23 02:35:22 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -4887,6 +4887,7 @@ index_elem: ColId opt_class opt_asc_desc opt_nulls_order
$$ = makeNode(IndexElem);
$$->name = $1;
$$->expr = NULL;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
@@ -4896,6 +4897,7 @@ index_elem: ColId opt_class opt_asc_desc opt_nulls_order
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $1;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
@@ -4905,6 +4907,7 @@ index_elem: ColId opt_class opt_asc_desc opt_nulls_order
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $2;
+ $$->indexcolname = NULL;
$$->opclass = $4;
$$->ordering = $5;
$$->nulls_ordering = $6;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index ce3f51ca6e5..007a3cc6936 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.174 2009/10/31 01:41:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.175 2009/12/23 02:35:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1410,13 +1410,40 @@ FigureColname(Node *node)
{
char *name = NULL;
- FigureColnameInternal(node, &name);
+ (void) FigureColnameInternal(node, &name);
if (name != NULL)
return name;
/* default result if we can't guess anything */
return "?column?";
}
+/*
+ * FigureIndexColname -
+ * choose the name for an expression column in an index
+ *
+ * This is actually just like FigureColname, except we return NULL if
+ * we can't pick a good name.
+ */
+char *
+FigureIndexColname(Node *node)
+{
+ char *name = NULL;
+
+ (void) FigureColnameInternal(node, &name);
+ return name;
+}
+
+/*
+ * FigureColnameInternal -
+ * internal workhorse for FigureColname
+ *
+ * Return value indicates strength of confidence in result:
+ * 0 - no information
+ * 1 - second-best name choice
+ * 2 - good name choice
+ * The return value is actually only used internally.
+ * If the result isn't zero, *name is set to the chosen name.
+ */
static int
FigureColnameInternal(Node *node, char **name)
{
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 75c8d863dcd..f09e78dd8e3 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -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.34 2009/12/22 23:54:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.35 2009/12/23 02:35:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,6 +48,7 @@
#include "parser/parse_clause.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "parser/parse_utilcmd.h"
#include "parser/parser.h"
@@ -789,34 +790,24 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
/*
* chooseIndexName
*
- * Set name for unnamed index. See also the same logic in DefineIndex.
+ * Compute name for an index. This must match code in indexcmds.c.
+ *
+ * XXX this is inherently broken because the indexes aren't created
+ * immediately, so we fail to resolve conflicts when the same name is
+ * derived for multiple indexes. However, that's a reasonably uncommon
+ * situation, so we'll live with it for now.
*/
static char *
chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt)
{
- Oid namespaceId;
+ Oid namespaceId;
+ List *colnames;
namespaceId = RangeVarGetCreationNamespace(relation);
- if (index_stmt->primary)
- {
- /* no need for column list with pkey */
- return ChooseRelationName(relation->relname, NULL,
- "pkey", namespaceId);
- }
- else if (index_stmt->excludeOpNames != NIL)
- {
- IndexElem *iparam = (IndexElem *) linitial(index_stmt->indexParams);
-
- return ChooseRelationName(relation->relname, iparam->name,
- "exclusion", namespaceId);
- }
- else
- {
- IndexElem *iparam = (IndexElem *) linitial(index_stmt->indexParams);
-
- return ChooseRelationName(relation->relname, iparam->name,
- "key", namespaceId);
- }
+ colnames = ChooseIndexColumnNames(index_stmt->indexParams);
+ return ChooseIndexName(relation->relname, namespaceId,
+ colnames, index_stmt->excludeOpNames,
+ index_stmt->primary, index_stmt->isconstraint);
}
/*
@@ -828,6 +819,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
AttrNumber *attmap)
{
Oid source_relid = RelationGetRelid(source_idx);
+ Form_pg_attribute *attrs = RelationGetDescr(source_idx)->attrs;
HeapTuple ht_idxrel;
HeapTuple ht_idx;
Form_pg_class idxrelrec;
@@ -1023,6 +1015,9 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
keycoltype = exprType(indexkey);
}
+ /* Copy the original index column name */
+ iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
+
/* Add the operator class name, if non-default */
iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
@@ -1416,6 +1411,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
iparam = makeNode(IndexElem);
iparam->name = pstrdup(key);
iparam->expr = NULL;
+ iparam->indexcolname = NULL;
iparam->opclass = NIL;
iparam->ordering = SORTBY_DEFAULT;
iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
@@ -1544,6 +1540,11 @@ transformIndexStmt(IndexStmt *stmt, const char *queryString)
if (ielem->expr)
{
+ /* Extract preliminary index col name before transforming expr */
+ if (ielem->indexcolname == NULL)
+ ielem->indexcolname = FigureIndexColname(ielem->expr);
+
+ /* Now do parse transformation of the expression */
ielem->expr = transformExpr(pstate, ielem->expr);
/*
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a432260058f..f2119a530f9 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.78 2009/07/29 20:56:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.79 2009/12/23 02:35:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,6 +32,7 @@ extern Oid index_create(Oid heapRelationId,
const char *indexRelationName,
Oid indexRelationId,
IndexInfo *indexInfo,
+ List *indexColNames,
Oid accessMethodObjectId,
Oid tableSpaceId,
Oid *classObjectId,
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 1b665ff8550..2ac7e160fe8 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.98 2009/12/07 05:22:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.99 2009/12/23 02:35:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,6 +45,10 @@ extern char *makeObjectName(const char *name1, const char *name2,
const char *label);
extern char *ChooseRelationName(const char *name1, const char *name2,
const char *label, Oid namespaceid);
+extern char *ChooseIndexName(const char *tabname, Oid namespaceId,
+ List *colnames, List *exclusionOpNames,
+ bool primary, bool isconstraint);
+extern List *ChooseIndexColumnNames(List *indexElems);
extern Oid GetDefaultOpClass(Oid type_id, Oid am_id);
/* commands/functioncmds.c */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 265c4e2a18a..f93fff3892b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.419 2009/12/15 17:57:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.420 2009/12/23 02:35:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -501,6 +501,7 @@ typedef struct IndexElem
NodeTag type;
char *name; /* name of attribute to index, or NULL */
Node *expr; /* expression to index, or NULL */
+ char *indexcolname; /* name for index column; NULL = default */
List *opclass; /* name of desired opclass; NIL = default */
SortByDir ordering; /* ASC/DESC/default */
SortByNulls nulls_ordering; /* FIRST/LAST/default */
diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h
index 88aeb31e2f9..9b4202be003 100644
--- a/src/include/parser/parse_target.h
+++ b/src/include/parser/parse_target.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.44 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.45 2009/12/23 02:35:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,5 +37,6 @@ extern List *checkInsertTargets(ParseState *pstate, List *cols,
extern TupleDesc expandRecordVariable(ParseState *pstate, Var *var,
int levelsup);
extern char *FigureColname(Node *node);
+extern char *FigureIndexColname(Node *node);
#endif /* PARSE_TARGET_H */
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 20bf3de3bad..5aff44f23aa 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -159,7 +159,7 @@ CREATE TABLE tmp2 (a int primary key);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tmp2_pkey" for table "tmp2"
CREATE TABLE tmp3 (a int, b int);
CREATE TABLE tmp4 (a int, b int, unique(a,b));
-NOTICE: CREATE TABLE / UNIQUE will create implicit index "tmp4_a_key" for table "tmp4"
+NOTICE: CREATE TABLE / UNIQUE will create implicit index "tmp4_a_b_key" for table "tmp4"
CREATE TABLE tmp5 (a int, b int);
-- Insert rows into tmp2 (pktable)
INSERT INTO tmp2 values (1);
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 33e0edba03a..0367f532337 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -736,7 +736,7 @@ ERROR: table "fktable_fail2" does not exist
DROP TABLE PKTABLE;
-- Test for referencing column number smaller than referenced constraint
CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
-NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_ptest1_key" for table "pktable"
+NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_ptest1_ptest2_key" for table "pktable"
CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
ERROR: there is no unique constraint matching given keys for referenced table "pktable"
DROP TABLE FKTABLE_FAIL1;
@@ -860,7 +860,7 @@ DETAIL: Key columns "ptest4" and "ptest1" are of incompatible types: inet and i
create table pktable_base (base1 int not null);
create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
-NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_base1_key" for table "pktable"
+NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_base1_ptest1_key" for table "pktable"
create table fktable (ftest1 int references pktable(base1));
-- now some ins, upd, del
insert into pktable(base1) values (1);
@@ -1098,7 +1098,7 @@ CREATE TEMP TABLE pktable (
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_id2_key" for table "pktable"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_id3_key" for table "pktable"
-NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_id1_key" for table "pktable"
+NOTICE: CREATE TABLE / UNIQUE will create implicit index "pktable_id1_id2_id3_key" for table "pktable"
CREATE TEMP TABLE fktable (
x1 INT4 REFERENCES pktable(id1),
x2 VARCHAR(4) REFERENCES pktable(id2),
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index aa1eb4a4ddb..9c83a32f934 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1031,8 +1031,8 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_all_pkey" for
b | text | | extended | B
Indexes:
"t_all_pkey" PRIMARY KEY, btree (a)
- "t_all_b_key" btree (b)
- "t_all_key" btree ((a || b))
+ "t_all_b_idx" btree (b)
+ "t_all_expr_idx" btree ((a || b))
Check constraints:
"t1_a_check" CHECK (length(a) > 2)
Has OIDs: no
@@ -1040,7 +1040,7 @@ 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_b_idx | 0 | index b_key
t_all_pkey | 0 | index pkey
(2 rows)
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index 8928ca8beba..684394fd83d 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -359,12 +359,12 @@ SELECT '' AS five, * FROM UNIQUE_TBL;
DROP TABLE UNIQUE_TBL;
CREATE TABLE UNIQUE_TBL (i int, t text,
UNIQUE(i,t));
-NOTICE: CREATE TABLE / UNIQUE will create implicit index "unique_tbl_i_key" for table "unique_tbl"
+NOTICE: CREATE TABLE / UNIQUE will create implicit index "unique_tbl_i_t_key" for table "unique_tbl"
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
INSERT INTO UNIQUE_TBL VALUES (2, 'two');
INSERT INTO UNIQUE_TBL VALUES (1, 'three');
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
-ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
+ERROR: duplicate key value violates unique constraint "unique_tbl_i_t_key"
DETAIL: Key (i, t)=(1, one) already exists.
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
@@ -523,7 +523,7 @@ CREATE TABLE circles (
(c1 WITH &&, (c2::circle) WITH ~=)
WHERE (circle_center(c1) <> '(0,0)')
);
-NOTICE: CREATE TABLE / EXCLUDE will create implicit index "circles_c1_exclusion" for table "circles"
+NOTICE: CREATE TABLE / EXCLUDE will create implicit index "circles_c1_c2_exclusion" for table "circles"
-- these should succeed because they don't match the index predicate
INSERT INTO circles VALUES('<(0,0), 5>', '<(0,0), 5>');
INSERT INTO circles VALUES('<(0,0), 5>', '<(0,0), 5>');
@@ -531,7 +531,7 @@ INSERT INTO circles VALUES('<(0,0), 5>', '<(0,0), 5>');
INSERT INTO circles VALUES('<(10,10), 10>', '<(0,0), 5>');
-- fail, overlaps
INSERT INTO circles VALUES('<(20,20), 10>', '<(0,0), 5>');
-ERROR: conflicting key value violates exclusion constraint "circles_c1_exclusion"
+ERROR: conflicting key value violates exclusion constraint "circles_c1_c2_exclusion"
DETAIL: Key (c1, (c2::circle))=(<(20,20),10>, <(0,0),5>) conflicts with existing key (c1, (c2::circle))=(<(10,10),10>, <(0,0),5>).
-- succeed because c1 doesn't overlap
INSERT INTO circles VALUES('<(20,20), 1>', '<(0,0), 5>');
@@ -540,8 +540,8 @@ INSERT INTO circles VALUES('<(20,20), 10>', '<(1,1), 5>');
-- should fail on existing data without the WHERE clause
ALTER TABLE circles ADD EXCLUDE USING gist
(c1 WITH &&, (c2::circle) WITH ~=);
-NOTICE: ALTER TABLE / ADD EXCLUDE will create implicit index "circles_c1_exclusion1" for table "circles"
-ERROR: could not create exclusion constraint "circles_c1_exclusion1"
+NOTICE: ALTER TABLE / ADD EXCLUDE will create implicit index "circles_c1_c2_exclusion1" for table "circles"
+ERROR: could not create exclusion constraint "circles_c1_c2_exclusion1"
DETAIL: Key (c1, (c2::circle))=(<(0,0),5>, <(0,0),5>) conflicts with key (c1, (c2::circle))=(<(0,0),5>, <(0,0),5>).
DROP TABLE circles;
-- Check deferred exclusion constraint