diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 9bc2d9d6b7e0482d79cb9cd346514090ff560ee5..3f093f885d5be3a53cb629167a3160fbb6feb195 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: analyze.c,v 1.109 1999/05/25 22:04:25 momjian Exp $
+ *	$Id: analyze.c,v 1.110 1999/06/05 20:22:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -410,39 +410,79 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 }
 
 /*
- *	makeTableName()
- *	Create a table name from a list of fields.
+ *	makeObjectName()
+ *
+ *	Create a name for an implicitly created index, sequence, constraint, etc.
+ *
+ *	The parameters are: the original table name, the original field name, and
+ *	a "type" string (such as "seq" or "pkey").  The field name and/or type
+ *	can be NULL if not relevant.
+ *
+ *	The result is a palloc'd string.
+ *
+ *	The basic result we want is "name1_name2_type", omitting "_name2" or
+ *	"_type" when those parameters are NULL.  However, we must generate
+ *	a name with less than NAMEDATALEN characters!  So, we truncate one or
+ *	both names if necessary to make a short-enough string.  The type part
+ *	is never truncated (so it had better be reasonably short).
+ *
+ *	To reduce the probability of collisions, we might someday add more
+ *	smarts to this routine, like including some "hash" characters computed
+ *	from the truncated characters.  Currently it seems best to keep it simple,
+ *	so that the generated names are easily predictable by a person.
  */
 static char *
-makeTableName(void *elem,...)
+makeObjectName(char *name1, char *name2, char *typename)
 {
-	va_list		args;
-
 	char	   *name;
-	char		buf[NAMEDATALEN + 1];
-
-	buf[0] = '\0';
-
-	va_start(args, elem);
-
-	name = elem;
-	while (name != NULL)
+	int			overhead = 0;	/* chars needed for type and underscores */
+	int			availchars;		/* chars available for name(s) */
+	int			name1chars;		/* chars allocated to name1 */
+	int			name2chars;		/* chars allocated to name2 */
+	int			ndx;
+
+	name1chars = strlen(name1);
+	if (name2)
 	{
-		/* not enough room for next part? then return nothing */
-		if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
-			return NULL;
+		name2chars = strlen(name2);
+		overhead++;				/* allow for separating underscore */
+	}
+	else
+		name2chars = 0;
+	if (typename)
+		overhead += strlen(typename) + 1;
 
-		if (strlen(buf) > 0)
-			strcat(buf, "_");
-		strcat(buf, name);
+	availchars = NAMEDATALEN-1 - overhead;
 
-		name = va_arg(args, void *);
+	/* If we must truncate,  preferentially truncate the longer name.
+	 * This logic could be expressed without a loop, but it's simple and
+	 * obvious as a loop.
+	 */
+	while (name1chars + name2chars > availchars)
+	{
+		if (name1chars > name2chars)
+			name1chars--;
+		else
+			name2chars--;
 	}
 
-	va_end(args);
-
-	name = palloc(strlen(buf) + 1);
-	strcpy(name, buf);
+	/* Now construct the string using the chosen lengths */
+	name = palloc(name1chars + name2chars + overhead + 1);
+	strncpy(name, name1, name1chars);
+	ndx = name1chars;
+	if (name2)
+	{
+		name[ndx++] = '_';
+		strncpy(name+ndx, name2, name2chars);
+		ndx += name2chars;
+	}
+	if (typename)
+	{
+		name[ndx++] = '_';
+		strcpy(name+ndx, typename);
+	}
+	else
+		name[ndx] = '\0';
 
 	return name;
 }
@@ -453,26 +493,24 @@ CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
 	int			pass = 0;
 	char	   *iname = NULL;
 	List	   *ilist;
-	IndexStmt  *index;
-	char		name2[NAMEDATALEN + 1];
+	char		typename[NAMEDATALEN];
+
+	/* The type name for makeObjectName is label, or labelN if that's
+	 * necessary to prevent collisions among multiple indexes for the same
+	 * table.  Note there is no check for collisions with already-existing
+	 * indexes; this ought to be rethought someday.
+	 */
+	strcpy(typename, label);
 
-	/* use working storage, since we might be trying several possibilities */
-	strcpy(name2, column_name);
-	while (iname == NULL)
+	for (;;)
 	{
-		iname = makeTableName(table_name, name2, label, NULL);
-		/* unable to make a name at all? then quit */
-		if (iname == NULL)
-			break;
+		iname = makeObjectName(table_name, column_name, typename);
 
-		ilist = indices;
-		while (ilist != NIL)
+		foreach(ilist, indices)
 		{
-			index = lfirst(ilist);
+			IndexStmt  *index = lfirst(ilist);
 			if (strcasecmp(iname, index->idxname) == 0)
 				break;
-
-			ilist = lnext(ilist);
 		}
 		/* ran through entire list? then no name conflict found so done */
 		if (ilist == NIL)
@@ -480,9 +518,7 @@ CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
 
 		/* the last one conflicted, so try a new name component */
 		pfree(iname);
-		iname = NULL;
-		pass++;
-		sprintf(name2, "%s_%d", column_name, (pass + 1));
+		sprintf(typename, "%s%d", label, ++pass);
 	}
 
 	return iname;
@@ -542,12 +578,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 					char	   *cstring;
 					CreateSeqStmt *sequence;
 
-					sname = makeTableName(stmt->relname, column->colname, "seq", NULL);
-					if (sname == NULL)
-						elog(ERROR, "CREATE TABLE/SERIAL implicit sequence name must be less than %d characters"
-							 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
-							 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN - 5));
-
+					sname = makeObjectName(stmt->relname, column->colname,
+										   "seq");
 					constraint = makeNode(Constraint);
 					constraint->contype = CONSTR_DEFAULT;
 					constraint->name = sname;
@@ -562,11 +594,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 
 					constraint = makeNode(Constraint);
 					constraint->contype = CONSTR_UNIQUE;
-					constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
-					if (constraint->name == NULL)
-						elog(ERROR, "CREATE TABLE/SERIAL implicit index name must be less than %d characters"
-							 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
-							 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN - 5));
+					constraint->name = makeObjectName(stmt->relname,
+													  column->colname,
+													  "key");
 					column->constraints = lappend(column->constraints, constraint);
 
 					sequence = makeNode(CreateSeqStmt);
@@ -616,11 +646,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 
 							case CONSTR_PRIMARY:
 								if (constraint->name == NULL)
-									constraint->name = makeTableName(stmt->relname, "pkey", NULL);
-								if (constraint->name == NULL)
-									elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
-										 "\n\tLength of '%s' must be less than %d",
-										 NAMEDATALEN, stmt->relname, (NAMEDATALEN - 6));
+									constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
 								if (constraint->keys == NIL)
 									constraint->keys = lappend(constraint->keys, column);
 								dlist = lappend(dlist, constraint);
@@ -628,11 +654,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 
 							case CONSTR_UNIQUE:
 								if (constraint->name == NULL)
-									constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
-								if (constraint->name == NULL)
-									elog(ERROR, "CREATE TABLE/UNIQUE implicit index name must be less than %d characters"
-										 "\n\tLength of '%s' must be less than %d",
-										 NAMEDATALEN, stmt->relname, (NAMEDATALEN - 5));
+									constraint->name = makeObjectName(stmt->relname, column->colname, "key");
 								if (constraint->keys == NIL)
 									constraint->keys = lappend(constraint->keys, column);
 								dlist = lappend(dlist, constraint);
@@ -641,11 +663,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 							case CONSTR_CHECK:
 								constraints = lappend(constraints, constraint);
 								if (constraint->name == NULL)
-									constraint->name = makeTableName(stmt->relname, column->colname, NULL);
-								if (constraint->name == NULL)
-									elog(ERROR, "CREATE TABLE/CHECK implicit constraint name must be less than %d characters"
-										 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
-										 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN - 1));
+									constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
 								break;
 
 							default:
@@ -663,11 +681,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 				{
 					case CONSTR_PRIMARY:
 						if (constraint->name == NULL)
-							constraint->name = makeTableName(stmt->relname, "pkey", NULL);
-						if (constraint->name == NULL)
-							elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
-							   "\n\tLength of '%s' must be less than %d",
-								 NAMEDATALEN, stmt->relname, (NAMEDATALEN - 5));
+							constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
 						dlist = lappend(dlist, constraint);
 						break;
 
@@ -728,15 +742,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 		}
 
 		if (constraint->name != NULL)
-			index->idxname = constraint->name;
+			index->idxname = pstrdup(constraint->name);
 		else if (constraint->contype == CONSTR_PRIMARY)
-		{
-			index->idxname = makeTableName(stmt->relname, "pkey", NULL);
-			if (index->idxname == NULL)
-				elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
-					 "\n\tLength of '%s' must be less than %d",
-					 NAMEDATALEN, stmt->relname, (NAMEDATALEN - 5));
-		}
+			index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
 		else
 			index->idxname = NULL;
 
@@ -767,7 +775,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 			if (constraint->contype == CONSTR_PRIMARY)
 				column->is_not_null = TRUE;
 			iparam = makeNode(IndexElem);
-			iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
+			iparam->name = pstrdup(column->colname);
 			iparam->args = NIL;
 			iparam->class = NULL;
 			iparam->typename = NULL;
@@ -779,9 +787,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
 			keys = lnext(keys);
 		}
 
-		if (index->idxname == NULL)
-			elog(ERROR, "CREATE TABLE unable to construct implicit index for table '%s'"
-				 "; name too long", stmt->relname);
+		if (index->idxname == NULL)	/* should not happen */
+			elog(ERROR, "CREATE TABLE: failed to make implicit index name");
 
 		ilist = lappend(ilist, index);
 		dlist = lnext(dlist);