5
5
*
6
6
* Copyright (c) 1994, Regents of the University of California
7
7
*
8
- * $Id: analyze.c,v 1.109 1999/05/25 22:04:25 momjian Exp $
8
+ * $Id: analyze.c,v 1.110 1999/06/05 20: 22:30 tgl Exp $
9
9
*
10
10
*-------------------------------------------------------------------------
11
11
*/
@@ -410,39 +410,79 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
410
410
}
411
411
412
412
/*
413
- * makeTableName()
414
- * Create a table name from a list of fields.
413
+ * makeObjectName()
414
+ *
415
+ * Create a name for an implicitly created index, sequence, constraint, etc.
416
+ *
417
+ * The parameters are: the original table name, the original field name, and
418
+ * a "type" string (such as "seq" or "pkey"). The field name and/or type
419
+ * can be NULL if not relevant.
420
+ *
421
+ * The result is a palloc'd string.
422
+ *
423
+ * The basic result we want is "name1_name2_type", omitting "_name2" or
424
+ * "_type" when those parameters are NULL. However, we must generate
425
+ * a name with less than NAMEDATALEN characters! So, we truncate one or
426
+ * both names if necessary to make a short-enough string. The type part
427
+ * is never truncated (so it had better be reasonably short).
428
+ *
429
+ * To reduce the probability of collisions, we might someday add more
430
+ * smarts to this routine, like including some "hash" characters computed
431
+ * from the truncated characters. Currently it seems best to keep it simple,
432
+ * so that the generated names are easily predictable by a person.
415
433
*/
416
434
static char *
417
- makeTableName ( void * elem ,... )
435
+ makeObjectName ( char * name1 , char * name2 , char * typename )
418
436
{
419
- va_list args ;
420
-
421
437
char * name ;
422
- char buf [ NAMEDATALEN + 1 ];
423
-
424
- buf [ 0 ] = '\0' ;
425
-
426
- va_start ( args , elem ) ;
427
-
428
- name = elem ;
429
- while ( name != NULL )
438
+ int overhead = 0 ; /* chars needed for type and underscores */
439
+ int availchars ; /* chars available for name(s) */
440
+ int name1chars ; /* chars allocated to name1 */
441
+ int name2chars ; /* chars allocated to name2 */
442
+ int ndx ;
443
+
444
+ name1chars = strlen ( name1 ) ;
445
+ if ( name2 )
430
446
{
431
- /* not enough room for next part? then return nothing */
432
- if ((strlen (buf ) + strlen (name )) >= (sizeof (buf ) - 1 ))
433
- return NULL ;
447
+ name2chars = strlen (name2 );
448
+ overhead ++ ; /* allow for separating underscore */
449
+ }
450
+ else
451
+ name2chars = 0 ;
452
+ if (typename )
453
+ overhead += strlen (typename ) + 1 ;
434
454
435
- if (strlen (buf ) > 0 )
436
- strcat (buf , "_" );
437
- strcat (buf , name );
455
+ availchars = NAMEDATALEN - 1 - overhead ;
438
456
439
- name = va_arg (args , void * );
457
+ /* If we must truncate, preferentially truncate the longer name.
458
+ * This logic could be expressed without a loop, but it's simple and
459
+ * obvious as a loop.
460
+ */
461
+ while (name1chars + name2chars > availchars )
462
+ {
463
+ if (name1chars > name2chars )
464
+ name1chars -- ;
465
+ else
466
+ name2chars -- ;
440
467
}
441
468
442
- va_end (args );
443
-
444
- name = palloc (strlen (buf ) + 1 );
445
- strcpy (name , buf );
469
+ /* Now construct the string using the chosen lengths */
470
+ name = palloc (name1chars + name2chars + overhead + 1 );
471
+ strncpy (name , name1 , name1chars );
472
+ ndx = name1chars ;
473
+ if (name2 )
474
+ {
475
+ name [ndx ++ ] = '_' ;
476
+ strncpy (name + ndx , name2 , name2chars );
477
+ ndx += name2chars ;
478
+ }
479
+ if (typename )
480
+ {
481
+ name [ndx ++ ] = '_' ;
482
+ strcpy (name + ndx , typename );
483
+ }
484
+ else
485
+ name [ndx ] = '\0' ;
446
486
447
487
return name ;
448
488
}
@@ -453,36 +493,32 @@ CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
453
493
int pass = 0 ;
454
494
char * iname = NULL ;
455
495
List * ilist ;
456
- IndexStmt * index ;
457
- char name2 [NAMEDATALEN + 1 ];
496
+ char typename [NAMEDATALEN ];
497
+
498
+ /* The type name for makeObjectName is label, or labelN if that's
499
+ * necessary to prevent collisions among multiple indexes for the same
500
+ * table. Note there is no check for collisions with already-existing
501
+ * indexes; this ought to be rethought someday.
502
+ */
503
+ strcpy (typename , label );
458
504
459
- /* use working storage, since we might be trying several possibilities */
460
- strcpy (name2 , column_name );
461
- while (iname == NULL )
505
+ for (;;)
462
506
{
463
- iname = makeTableName (table_name , name2 , label , NULL );
464
- /* unable to make a name at all? then quit */
465
- if (iname == NULL )
466
- break ;
507
+ iname = makeObjectName (table_name , column_name , typename );
467
508
468
- ilist = indices ;
469
- while (ilist != NIL )
509
+ foreach (ilist , indices )
470
510
{
471
- index = lfirst (ilist );
511
+ IndexStmt * index = lfirst (ilist );
472
512
if (strcasecmp (iname , index -> idxname ) == 0 )
473
513
break ;
474
-
475
- ilist = lnext (ilist );
476
514
}
477
515
/* ran through entire list? then no name conflict found so done */
478
516
if (ilist == NIL )
479
517
break ;
480
518
481
519
/* the last one conflicted, so try a new name component */
482
520
pfree (iname );
483
- iname = NULL ;
484
- pass ++ ;
485
- sprintf (name2 , "%s_%d" , column_name , (pass + 1 ));
521
+ sprintf (typename , "%s%d" , label , ++ pass );
486
522
}
487
523
488
524
return iname ;
@@ -542,12 +578,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
542
578
char * cstring ;
543
579
CreateSeqStmt * sequence ;
544
580
545
- sname = makeTableName (stmt -> relname , column -> colname , "seq" , NULL );
546
- if (sname == NULL )
547
- elog (ERROR , "CREATE TABLE/SERIAL implicit sequence name must be less than %d characters"
548
- "\n\tSum of lengths of '%s' and '%s' must be less than %d" ,
549
- NAMEDATALEN , stmt -> relname , column -> colname , (NAMEDATALEN - 5 ));
550
-
581
+ sname = makeObjectName (stmt -> relname , column -> colname ,
582
+ "seq" );
551
583
constraint = makeNode (Constraint );
552
584
constraint -> contype = CONSTR_DEFAULT ;
553
585
constraint -> name = sname ;
@@ -562,11 +594,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
562
594
563
595
constraint = makeNode (Constraint );
564
596
constraint -> contype = CONSTR_UNIQUE ;
565
- constraint -> name = makeTableName (stmt -> relname , column -> colname , "key" , NULL );
566
- if (constraint -> name == NULL )
567
- elog (ERROR , "CREATE TABLE/SERIAL implicit index name must be less than %d characters"
568
- "\n\tSum of lengths of '%s' and '%s' must be less than %d" ,
569
- NAMEDATALEN , stmt -> relname , column -> colname , (NAMEDATALEN - 5 ));
597
+ constraint -> name = makeObjectName (stmt -> relname ,
598
+ column -> colname ,
599
+ "key" );
570
600
column -> constraints = lappend (column -> constraints , constraint );
571
601
572
602
sequence = makeNode (CreateSeqStmt );
@@ -616,23 +646,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
616
646
617
647
case CONSTR_PRIMARY :
618
648
if (constraint -> name == NULL )
619
- constraint -> name = makeTableName (stmt -> relname , "pkey" , NULL );
620
- if (constraint -> name == NULL )
621
- elog (ERROR , "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
622
- "\n\tLength of '%s' must be less than %d" ,
623
- NAMEDATALEN , stmt -> relname , (NAMEDATALEN - 6 ));
649
+ constraint -> name = makeObjectName (stmt -> relname , NULL , "pkey" );
624
650
if (constraint -> keys == NIL )
625
651
constraint -> keys = lappend (constraint -> keys , column );
626
652
dlist = lappend (dlist , constraint );
627
653
break ;
628
654
629
655
case CONSTR_UNIQUE :
630
656
if (constraint -> name == NULL )
631
- constraint -> name = makeTableName (stmt -> relname , column -> colname , "key" , NULL );
632
- if (constraint -> name == NULL )
633
- elog (ERROR , "CREATE TABLE/UNIQUE implicit index name must be less than %d characters"
634
- "\n\tLength of '%s' must be less than %d" ,
635
- NAMEDATALEN , stmt -> relname , (NAMEDATALEN - 5 ));
657
+ constraint -> name = makeObjectName (stmt -> relname , column -> colname , "key" );
636
658
if (constraint -> keys == NIL )
637
659
constraint -> keys = lappend (constraint -> keys , column );
638
660
dlist = lappend (dlist , constraint );
@@ -641,11 +663,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
641
663
case CONSTR_CHECK :
642
664
constraints = lappend (constraints , constraint );
643
665
if (constraint -> name == NULL )
644
- constraint -> name = makeTableName (stmt -> relname , column -> colname , NULL );
645
- if (constraint -> name == NULL )
646
- elog (ERROR , "CREATE TABLE/CHECK implicit constraint name must be less than %d characters"
647
- "\n\tSum of lengths of '%s' and '%s' must be less than %d" ,
648
- NAMEDATALEN , stmt -> relname , column -> colname , (NAMEDATALEN - 1 ));
666
+ constraint -> name = makeObjectName (stmt -> relname , column -> colname , NULL );
649
667
break ;
650
668
651
669
default :
@@ -663,11 +681,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
663
681
{
664
682
case CONSTR_PRIMARY :
665
683
if (constraint -> name == NULL )
666
- constraint -> name = makeTableName (stmt -> relname , "pkey" , NULL );
667
- if (constraint -> name == NULL )
668
- elog (ERROR , "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
669
- "\n\tLength of '%s' must be less than %d" ,
670
- NAMEDATALEN , stmt -> relname , (NAMEDATALEN - 5 ));
684
+ constraint -> name = makeObjectName (stmt -> relname , NULL , "pkey" );
671
685
dlist = lappend (dlist , constraint );
672
686
break ;
673
687
@@ -728,15 +742,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
728
742
}
729
743
730
744
if (constraint -> name != NULL )
731
- index -> idxname = constraint -> name ;
745
+ index -> idxname = pstrdup ( constraint -> name ) ;
732
746
else if (constraint -> contype == CONSTR_PRIMARY )
733
- {
734
- index -> idxname = makeTableName (stmt -> relname , "pkey" , NULL );
735
- if (index -> idxname == NULL )
736
- elog (ERROR , "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
737
- "\n\tLength of '%s' must be less than %d" ,
738
- NAMEDATALEN , stmt -> relname , (NAMEDATALEN - 5 ));
739
- }
747
+ index -> idxname = makeObjectName (stmt -> relname , NULL , "pkey" );
740
748
else
741
749
index -> idxname = NULL ;
742
750
@@ -767,7 +775,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
767
775
if (constraint -> contype == CONSTR_PRIMARY )
768
776
column -> is_not_null = TRUE;
769
777
iparam = makeNode (IndexElem );
770
- iparam -> name = strcpy ( palloc ( strlen ( column -> colname ) + 1 ), column -> colname );
778
+ iparam -> name = pstrdup ( column -> colname );
771
779
iparam -> args = NIL ;
772
780
iparam -> class = NULL ;
773
781
iparam -> typename = NULL ;
@@ -779,9 +787,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
779
787
keys = lnext (keys );
780
788
}
781
789
782
- if (index -> idxname == NULL )
783
- elog (ERROR , "CREATE TABLE unable to construct implicit index for table '%s'"
784
- "; name too long" , stmt -> relname );
790
+ if (index -> idxname == NULL ) /* should not happen */
791
+ elog (ERROR , "CREATE TABLE: failed to make implicit index name" );
785
792
786
793
ilist = lappend (ilist , index );
787
794
dlist = lnext (dlist );
0 commit comments