88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.269 2004/06/06 20:30:07 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.270 2004/06/10 17:55:53 tgl Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -1488,7 +1488,7 @@ AddRelationRawConstraints(Relation rel,
14881488ParseState * pstate ;
14891489RangeTblEntry * rte ;
14901490int numchecks ;
1491- int constr_name_ctr = 0 ;
1491+ List * checknames ;
14921492ListCell * cell ;
14931493Node * expr ;
14941494CookedConstraint * cooked ;
@@ -1547,6 +1547,7 @@ AddRelationRawConstraints(Relation rel,
15471547 * Process constraint expressions.
15481548 */
15491549numchecks = numoldchecks ;
1550+ checknames = NIL ;
15501551foreach (cell ,rawConstraints )
15511552{
15521553Constraint * cdef = (Constraint * )lfirst (cell );
@@ -1556,81 +1557,6 @@ AddRelationRawConstraints(Relation rel,
15561557continue ;
15571558Assert (cdef -> cooked_expr == NULL );
15581559
1559- /* Check name uniqueness, or generate a new name */
1560- if (cdef -> name != NULL )
1561- {
1562- ListCell * cell2 ;
1563-
1564- ccname = cdef -> name ;
1565- /* Check against pre-existing constraints */
1566- if (ConstraintNameIsUsed (CONSTRAINT_RELATION ,
1567- RelationGetRelid (rel ),
1568- RelationGetNamespace (rel ),
1569- ccname ))
1570- ereport (ERROR ,
1571- (errcode (ERRCODE_DUPLICATE_OBJECT ),
1572- errmsg ("constraint \"%s\" for relation \"%s\" already exists" ,
1573- ccname ,RelationGetRelationName (rel ))));
1574- /* Check against other new constraints */
1575- /* Needed because we don't do CommandCounterIncrement in loop */
1576- foreach (cell2 ,rawConstraints )
1577- {
1578- Constraint * cdef2 = (Constraint * )lfirst (cell2 );
1579-
1580- if (cdef2 == cdef ||
1581- cdef2 -> contype != CONSTR_CHECK ||
1582- cdef2 -> raw_expr == NULL ||
1583- cdef2 -> name == NULL )
1584- continue ;
1585- if (strcmp (cdef2 -> name ,ccname )== 0 )
1586- ereport (ERROR ,
1587- (errcode (ERRCODE_DUPLICATE_OBJECT ),
1588- errmsg ("check constraint \"%s\" already exists" ,
1589- ccname )));
1590- }
1591- }
1592- else
1593- {
1594- bool success ;
1595-
1596- do
1597- {
1598- ListCell * cell2 ;
1599-
1600- /*
1601- * Generate a name that does not conflict with
1602- * pre-existing constraints, nor with any auto-generated
1603- * names so far.
1604- */
1605- ccname = GenerateConstraintName (CONSTRAINT_RELATION ,
1606- RelationGetRelid (rel ),
1607- RelationGetNamespace (rel ),
1608- & constr_name_ctr );
1609-
1610- /*
1611- * Check against other new constraints, in case the user
1612- * has specified a name that looks like an auto-generated
1613- * name.
1614- */
1615- success = true;
1616- foreach (cell2 ,rawConstraints )
1617- {
1618- Constraint * cdef2 = (Constraint * )lfirst (cell2 );
1619-
1620- if (cdef2 == cdef ||
1621- cdef2 -> contype != CONSTR_CHECK ||
1622- cdef2 -> raw_expr == NULL ||
1623- cdef2 -> name == NULL )
1624- continue ;
1625- if (strcmp (cdef2 -> name ,ccname )== 0 )
1626- {
1627- success = false;
1628- break ;
1629- }
1630- }
1631- }while (!success );
1632- }
1633-
16341560/*
16351561 * Transform raw parsetree to executable expression.
16361562 */
@@ -1662,6 +1588,73 @@ AddRelationRawConstraints(Relation rel,
16621588(errcode (ERRCODE_GROUPING_ERROR ),
16631589errmsg ("cannot use aggregate function in check constraint" )));
16641590
1591+ /*
1592+ * Check name uniqueness, or generate a name if none was given.
1593+ */
1594+ if (cdef -> name != NULL )
1595+ {
1596+ ListCell * cell2 ;
1597+
1598+ ccname = cdef -> name ;
1599+ /* Check against pre-existing constraints */
1600+ if (ConstraintNameIsUsed (CONSTRAINT_RELATION ,
1601+ RelationGetRelid (rel ),
1602+ RelationGetNamespace (rel ),
1603+ ccname ))
1604+ ereport (ERROR ,
1605+ (errcode (ERRCODE_DUPLICATE_OBJECT ),
1606+ errmsg ("constraint \"%s\" for relation \"%s\" already exists" ,
1607+ ccname ,RelationGetRelationName (rel ))));
1608+ /* Check against other new constraints */
1609+ /* Needed because we don't do CommandCounterIncrement in loop */
1610+ foreach (cell2 ,checknames )
1611+ {
1612+ if (strcmp ((char * )lfirst (cell2 ),ccname )== 0 )
1613+ ereport (ERROR ,
1614+ (errcode (ERRCODE_DUPLICATE_OBJECT ),
1615+ errmsg ("check constraint \"%s\" already exists" ,
1616+ ccname )));
1617+ }
1618+ }
1619+ else
1620+ {
1621+ /*
1622+ * When generating a name, we want to create "tab_col_check"
1623+ * for a column constraint and "tab_check" for a table
1624+ * constraint. We no longer have any info about the
1625+ * syntactic positioning of the constraint phrase, so we
1626+ * approximate this by seeing whether the expression references
1627+ * more than one column. (If the user played by the rules,
1628+ * the result is the same...)
1629+ *
1630+ * Note: pull_var_clause() doesn't descend into sublinks,
1631+ * but we eliminated those above; and anyway this only needs
1632+ * to be an approximate answer.
1633+ */
1634+ List * vars ;
1635+ char * colname ;
1636+
1637+ vars = pull_var_clause (expr , false);
1638+
1639+ /* eliminate duplicates */
1640+ vars = list_union (NIL ,vars );
1641+
1642+ if (list_length (vars )== 1 )
1643+ colname = get_attname (RelationGetRelid (rel ),
1644+ ((Var * )linitial (vars ))-> varattno );
1645+ else
1646+ colname = NULL ;
1647+
1648+ ccname = ChooseConstraintName (RelationGetRelationName (rel ),
1649+ colname ,
1650+ "check" ,
1651+ RelationGetNamespace (rel ),
1652+ checknames );
1653+ }
1654+
1655+ /* save name for future checks */
1656+ checknames = lappend (checknames ,ccname );
1657+
16651658/*
16661659 * OK, store it.
16671660 */