Commit 3ce054b5 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Fix problem with multiple indices defined if using column- and table-

 constraints. Reported by Tom Lane.
Now, check for duplicate indices and retain the one which is a primary-key.
Adjust elog NOTICE messages to surround table and column names with single
 quotes.
parent 575c40a6
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.c,v 1.101 1999/02/23 07:44:44 thomas Exp $ * $Id: analyze.c,v 1.102 1999/05/12 07:17:18 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -513,7 +513,6 @@ static Query * ...@@ -513,7 +513,6 @@ static Query *
transformCreateStmt(ParseState *pstate, CreateStmt *stmt) transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
{ {
Query *q; Query *q;
int have_pkey = FALSE;
List *elements; List *elements;
Node *element; Node *element;
List *columns; List *columns;
...@@ -524,9 +523,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -524,9 +523,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
Constraint *constraint; Constraint *constraint;
List *keys; List *keys;
Ident *key; Ident *key;
List *blist = NIL; List *blist = NIL; /* "before list" of things to do before creating the table */
List *ilist = NIL; List *ilist = NIL; /* "index list" of things to do after creating the table */
IndexStmt *index; IndexStmt *index, *pkey = NULL;
IndexElem *iparam; IndexElem *iparam;
q = makeNode(Query); q = makeNode(Query);
...@@ -568,6 +567,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -568,6 +567,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
constraint->def = cstring; constraint->def = cstring;
constraint->keys = NULL; constraint->keys = NULL;
#if 0
/* The parser only allows PRIMARY KEY as a constraint for the SERIAL type. /* The parser only allows PRIMARY KEY as a constraint for the SERIAL type.
* So, if there is a constraint of any kind, assume it is that. * So, if there is a constraint of any kind, assume it is that.
* If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint * If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint
...@@ -580,7 +580,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -580,7 +580,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
} }
else else
{ {
column->constraints = lcons(constraint, NIL); #endif
column->constraints = lappend(column->constraints, constraint);
constraint = makeNode(Constraint); constraint = makeNode(Constraint);
constraint->contype = CONSTR_UNIQUE; constraint->contype = CONSTR_UNIQUE;
...@@ -590,13 +591,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -590,13 +591,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
"\n\tSum of lengths of '%s' and '%s' must be less than %d", "\n\tSum of lengths of '%s' and '%s' must be less than %d",
NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5)); NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5));
column->constraints = lappend(column->constraints, constraint); column->constraints = lappend(column->constraints, constraint);
#if 0
} }
#endif
sequence = makeNode(CreateSeqStmt); sequence = makeNode(CreateSeqStmt);
sequence->seqname = pstrdup(sname); sequence->seqname = pstrdup(sname);
sequence->options = NIL; sequence->options = NIL;
elog(NOTICE, "CREATE TABLE will create implicit sequence %s for SERIAL column %s.%s", elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
sequence->seqname, stmt->relname, column->colname); sequence->seqname, stmt->relname, column->colname);
blist = lcons(sequence, NIL); blist = lcons(sequence, NIL);
...@@ -735,32 +738,28 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -735,32 +738,28 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
while (dlist != NIL) while (dlist != NIL)
{ {
constraint = lfirst(dlist); constraint = lfirst(dlist);
if (nodeTag(constraint) != T_Constraint) Assert(nodeTag(constraint) == T_Constraint);
elog(ERROR, "parser: unrecognized deferred node (internal error)", NULL); Assert((constraint->contype == CONSTR_PRIMARY)
|| (constraint->contype == CONSTR_UNIQUE));
if (constraint->contype == CONSTR_PRIMARY) index = makeNode(IndexStmt);
index->unique = TRUE;
index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE:FALSE);
if (index->primary)
{ {
if (have_pkey) if (pkey != NULL)
elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys" elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
" for table %s are not legal", stmt->relname); " for table %s are not legal", stmt->relname);
else pkey = (IndexStmt *) index;
have_pkey = TRUE;
} }
else if (constraint->contype != CONSTR_UNIQUE)
elog(ERROR, "parser: unrecognized deferred constraint (internal error)", NULL);
index = makeNode(IndexStmt);
index->unique = TRUE;
index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE:FALSE);
if (constraint->name != NULL) if (constraint->name != NULL)
{
index->idxname = constraint->name; index->idxname = constraint->name;
}
else if (constraint->contype == CONSTR_PRIMARY) else if (constraint->contype == CONSTR_PRIMARY)
{ {
if (have_pkey)
elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
have_pkey = TRUE;
index->idxname = makeTableName(stmt->relname, "pkey", NULL); index->idxname = makeTableName(stmt->relname, "pkey", NULL);
if (index->idxname == NULL) if (index->idxname == NULL)
elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters" elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
...@@ -768,7 +767,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -768,7 +767,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
NAMEDATALEN, stmt->relname, (NAMEDATALEN-5)); NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
} }
else else
{
index->idxname = NULL; index->idxname = NULL;
}
index->relname = stmt->relname; index->relname = stmt->relname;
index->accessMethod = "btree"; index->accessMethod = "btree";
...@@ -812,15 +813,58 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -812,15 +813,58 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
if (index->idxname == NULL) if (index->idxname == NULL)
elog(ERROR, "CREATE TABLE unable to construct implicit index for table %s" elog(ERROR, "CREATE TABLE unable to construct implicit index for table %s"
"; name too long", stmt->relname); "; name too long", stmt->relname);
#if 0
else else
elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s", elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"), ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
index->idxname, stmt->relname); index->idxname, stmt->relname);
#endif
ilist = lappend(ilist, index); ilist = lappend(ilist, index);
dlist = lnext(dlist); dlist = lnext(dlist);
} }
/* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
* unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
* or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
* - thomas 1999-05-11
*/
if ((pkey != NULL) && (length(lfirst(pkey->indexParams)) == 1))
{
dlist = ilist;
ilist = NIL;
while (dlist != NIL)
{
int keep = TRUE;
index = lfirst(dlist);
/* has a single column argument, so might be a conflicting index... */
if ((index != pkey)
&& (length(index->indexParams) == 1))
{
char *pname = ((IndexElem *) lfirst(index->indexParams))->name;
char *iname = ((IndexElem *) lfirst(index->indexParams))->name;
/* same names? then don't keep... */
keep = (strcmp(iname, pname) != 0);
}
if (keep)
ilist = lappend(ilist, index);
dlist = lnext(dlist);
}
}
dlist = ilist;
while (dlist != NIL)
{
index = lfirst(dlist);
elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
(index->primary? "PRIMARY KEY": "UNIQUE"),
index->idxname, stmt->relname);
dlist = lnext(dlist);
}
q->utilityStmt = (Node *) stmt; q->utilityStmt = (Node *) stmt;
extras_before = blist; extras_before = blist;
extras_after = ilist; extras_after = ilist;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment