55 *
66 * Copyright (c) 1994, Regents of the University of California
77 *
8- * $Id: analyze.c,v 1.101 1999/02/23 07:44:44 thomas Exp $
8+ * $Id: analyze.c,v 1.102 1999/05/12 07:17:18 thomas Exp $
99 *
1010 *-------------------------------------------------------------------------
1111 */
@@ -513,7 +513,6 @@ static Query *
513513transformCreateStmt (ParseState * pstate ,CreateStmt * stmt )
514514{
515515Query * q ;
516- int have_pkey = FALSE;
517516List * elements ;
518517Node * element ;
519518List * columns ;
@@ -524,9 +523,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
524523Constraint * constraint ;
525524List * keys ;
526525Ident * key ;
527- List * blist = NIL ;
528- List * ilist = NIL ;
529- IndexStmt * index ;
526+ List * blist = NIL ;/* "before list" of things to do before creating the table */
527+ List * ilist = NIL ;/* "index list" of things to do after creating the table */
528+ IndexStmt * index , * pkey = NULL ;
530529IndexElem * iparam ;
531530
532531q = makeNode (Query );
@@ -568,6 +567,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
568567constraint -> def = cstring ;
569568constraint -> keys = NULL ;
570569
570+ #if 0
571571/* The parser only allows PRIMARY KEY as a constraint for the SERIAL type.
572572 * So, if there is a constraint of any kind, assume it is that.
573573 * If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint
@@ -580,7 +580,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
580580}
581581else
582582{
583- column -> constraints = lcons (constraint ,NIL );
583+ #endif
584+ column -> constraints = lappend (column -> constraints ,constraint );
584585
585586constraint = makeNode (Constraint );
586587constraint -> contype = CONSTR_UNIQUE ;
@@ -590,13 +591,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
590591"\n\tSum of lengths of '%s' and '%s' must be less than %d" ,
591592NAMEDATALEN ,stmt -> relname ,column -> colname , (NAMEDATALEN - 5 ));
592593column -> constraints = lappend (column -> constraints ,constraint );
594+ #if 0
593595}
596+ #endif
594597
595598sequence = makeNode (CreateSeqStmt );
596599sequence -> seqname = pstrdup (sname );
597600sequence -> options = NIL ;
598601
599- elog (NOTICE ,"CREATE TABLE will create implicit sequence%s for SERIAL column %s.%s" ,
602+ elog (NOTICE ,"CREATE TABLE will create implicit sequence'%s' for SERIAL column' %s.%s' " ,
600603sequence -> seqname ,stmt -> relname ,column -> colname );
601604
602605blist = lcons (sequence ,NIL );
@@ -735,40 +738,38 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
735738while (dlist != NIL )
736739{
737740constraint = lfirst (dlist );
738- if (nodeTag (constraint )!= T_Constraint )
739- elog (ERROR ,"parser: unrecognized deferred node (internal error)" ,NULL );
741+ Assert (nodeTag (constraint )== T_Constraint );
742+ Assert ((constraint -> contype == CONSTR_PRIMARY )
743+ || (constraint -> contype == CONSTR_UNIQUE ));
740744
741- if (constraint -> contype == CONSTR_PRIMARY )
745+ index = makeNode (IndexStmt );
746+
747+ index -> unique = TRUE;
748+ index -> primary = (constraint -> contype == CONSTR_PRIMARY ? TRUE:FALSE);
749+ if (index -> primary )
742750{
743- if (have_pkey )
751+ if (pkey != NULL )
744752elog (ERROR ,"CREATE TABLE/PRIMARY KEY multiple primary keys"
745753" for table %s are not legal" ,stmt -> relname );
746- else
747- have_pkey = TRUE;
754+ pkey = (IndexStmt * )index ;
748755}
749- else if (constraint -> contype != CONSTR_UNIQUE )
750- elog (ERROR ,"parser: unrecognized deferred constraint (internal error)" ,NULL );
751756
752- index = makeNode (IndexStmt );
753-
754- index -> unique = TRUE;
755- index -> primary = (constraint -> contype == CONSTR_PRIMARY ? TRUE:FALSE);
756757if (constraint -> name != NULL )
758+ {
757759index -> idxname = constraint -> name ;
760+ }
758761else if (constraint -> contype == CONSTR_PRIMARY )
759762{
760- if (have_pkey )
761- elog (ERROR ,"CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal" ,stmt -> relname );
762-
763- have_pkey = TRUE;
764763index -> idxname = makeTableName (stmt -> relname ,"pkey" ,NULL );
765764if (index -> idxname == NULL )
766765elog (ERROR ,"CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
767766"\n\tLength of '%s' must be less than %d" ,
768767NAMEDATALEN ,stmt -> relname , (NAMEDATALEN - 5 ));
769768}
770769else
770+ {
771771index -> idxname = NULL ;
772+ }
772773
773774index -> relname = stmt -> relname ;
774775index -> accessMethod = "btree" ;
@@ -812,15 +813,58 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
812813if (index -> idxname == NULL )
813814elog (ERROR ,"CREATE TABLE unable to construct implicit index for table %s"
814815"; name too long" ,stmt -> relname );
816+ #if 0
815817else
816- elog (NOTICE ,"CREATE TABLE/%s will create implicit index%s for table%s " ,
818+ elog (NOTICE ,"CREATE TABLE/%s will create implicit index'%s' for table'%s' " ,
817819 ((constraint -> contype == CONSTR_PRIMARY ) ?"PRIMARY KEY" :"UNIQUE" ),
818820index -> idxname ,stmt -> relname );
821+ #endif
819822
820823ilist = lappend (ilist ,index );
821824dlist = lnext (dlist );
822825}
823826
827+ /* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
828+ * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
829+ * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
830+ * - thomas 1999-05-11
831+ */
832+ if ((pkey != NULL )&& (length (lfirst (pkey -> indexParams ))== 1 ))
833+ {
834+ dlist = ilist ;
835+ ilist = NIL ;
836+ while (dlist != NIL )
837+ {
838+ int keep = TRUE;
839+
840+ index = lfirst (dlist );
841+
842+ /* has a single column argument, so might be a conflicting index... */
843+ if ((index != pkey )
844+ && (length (index -> indexParams )== 1 ))
845+ {
846+ char * pname = ((IndexElem * )lfirst (index -> indexParams ))-> name ;
847+ char * iname = ((IndexElem * )lfirst (index -> indexParams ))-> name ;
848+ /* same names? then don't keep... */
849+ keep = (strcmp (iname ,pname )!= 0 );
850+ }
851+
852+ if (keep )
853+ ilist = lappend (ilist ,index );
854+ dlist = lnext (dlist );
855+ }
856+ }
857+
858+ dlist = ilist ;
859+ while (dlist != NIL )
860+ {
861+ index = lfirst (dlist );
862+ elog (NOTICE ,"CREATE TABLE/%s will create implicit index '%s' for table '%s'" ,
863+ (index -> primary ?"PRIMARY KEY" :"UNIQUE" ),
864+ index -> idxname ,stmt -> relname );
865+ dlist = lnext (dlist );
866+ }
867+
824868q -> utilityStmt = (Node * )stmt ;
825869extras_before = blist ;
826870extras_after = ilist ;