|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.150 2001/11/05 17:46:24 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.151 2001/12/04 17:19:48 tgl Exp $ |
12 | 12 | *
|
13 | 13 | * NOTES
|
14 | 14 | * The PerformAddAttribute() code, like most of the relation
|
@@ -1246,6 +1246,12 @@ AlterTableAddConstraint(char *relationName,
|
1246 | 1246 | {
|
1247 | 1247 | Constraint*constr= (Constraint*)newConstraint;
|
1248 | 1248 |
|
| 1249 | +/* |
| 1250 | + * Currently, we only expect to see CONSTR_CHECK nodes |
| 1251 | + * arriving here (see the preprocessing done in |
| 1252 | + * parser/analyze.c). Use a switch anyway to make it |
| 1253 | + * easier to add more code later. |
| 1254 | + */ |
1249 | 1255 | switch (constr->contype)
|
1250 | 1256 | {
|
1251 | 1257 | caseCONSTR_CHECK:
|
@@ -1351,178 +1357,6 @@ AlterTableAddConstraint(char *relationName,
|
1351 | 1357 | AddRelationRawConstraints(rel,NIL,
|
1352 | 1358 | makeList1(constr));
|
1353 | 1359 |
|
1354 |
| -break; |
1355 |
| -} |
1356 |
| -caseCONSTR_UNIQUE: |
1357 |
| -{ |
1358 |
| -char*iname=constr->name; |
1359 |
| -boolistemp=is_temp_rel_name(relationName); |
1360 |
| -List*indexoidlist; |
1361 |
| -List*indexoidscan; |
1362 |
| -intnum_keys; |
1363 |
| -boolindex_found= false; |
1364 |
| -boolindex_found_unique= false; |
1365 |
| -boolindex_found_primary= false; |
1366 |
| - |
1367 |
| -/* |
1368 |
| - * If the constraint name is not |
1369 |
| - * specified, generate a name |
1370 |
| - */ |
1371 |
| -if (iname==NULL) |
1372 |
| -{ |
1373 |
| -Oidindoid; |
1374 |
| -intpass=0; |
1375 |
| -char*typename=palloc(NAMEDATALEN); |
1376 |
| -Ident*key; |
1377 |
| - |
1378 |
| -/* |
1379 |
| - * Assume that the length of the attr |
1380 |
| - * list is already > 0 |
1381 |
| - */ |
1382 |
| - |
1383 |
| -/* |
1384 |
| - * Get the first attribute so we can |
1385 |
| - * use its name |
1386 |
| - */ |
1387 |
| -key= (Ident*)lfirst(constr->keys); |
1388 |
| - |
1389 |
| -/* Initialise typename to 'key' */ |
1390 |
| -snprintf(typename,NAMEDATALEN,"key"); |
1391 |
| - |
1392 |
| -for (;;) |
1393 |
| -{ |
1394 |
| -iname=makeObjectName(relationName,key->name,typename); |
1395 |
| - |
1396 |
| -/* Check for a conflict */ |
1397 |
| -indoid=RelnameFindRelid(iname); |
1398 |
| - |
1399 |
| -/* |
1400 |
| - * If the oid was not found, then |
1401 |
| - * we have a safe name |
1402 |
| - */ |
1403 |
| -if ((!istemp&& !OidIsValid(indoid))|| |
1404 |
| -(istemp&& !is_temp_rel_name(iname))) |
1405 |
| -break; |
1406 |
| - |
1407 |
| -/* |
1408 |
| - * Found a conflict, so try a new |
1409 |
| - * name component |
1410 |
| - */ |
1411 |
| -pfree(iname); |
1412 |
| -snprintf(typename,NAMEDATALEN,"key%d",++pass); |
1413 |
| -} |
1414 |
| -} |
1415 |
| - |
1416 |
| -/* |
1417 |
| - * Need to check for unique key already on |
1418 |
| - * field(s) |
1419 |
| - */ |
1420 |
| - |
1421 |
| -/* |
1422 |
| - * First we check for limited correctness |
1423 |
| - * of the constraint |
1424 |
| - */ |
1425 |
| - |
1426 |
| -/* Loop over all indices on the relation */ |
1427 |
| -indexoidlist=RelationGetIndexList(rel); |
1428 |
| - |
1429 |
| -foreach(indexoidscan,indexoidlist) |
1430 |
| -{ |
1431 |
| -Oidindexoid=lfirsti(indexoidscan); |
1432 |
| -HeapTupleindexTuple; |
1433 |
| -Form_pg_indexindexStruct; |
1434 |
| -List*keyl; |
1435 |
| -inti; |
1436 |
| - |
1437 |
| -indexTuple=SearchSysCache(INDEXRELID, |
1438 |
| -ObjectIdGetDatum(indexoid), |
1439 |
| -0,0,0); |
1440 |
| - |
1441 |
| -if (!HeapTupleIsValid(indexTuple)) |
1442 |
| -elog(ERROR,"ALTER TABLE / ADD CONSTRAINT: Index \"%u\" not found", |
1443 |
| -indexoid); |
1444 |
| -indexStruct= (Form_pg_index)GETSTRUCT(indexTuple); |
1445 |
| - |
1446 |
| -/* |
1447 |
| - * Make sure this index has the same |
1448 |
| - * number of keys as the constraint -- |
1449 |
| - * It obviously won't match otherwise. |
1450 |
| - */ |
1451 |
| -for (i=0;i<INDEX_MAX_KEYS&&indexStruct->indkey[i]!=0;i++) |
1452 |
| -; |
1453 |
| -num_keys=length(constr->keys); |
1454 |
| - |
1455 |
| -if (i==num_keys) |
1456 |
| -{ |
1457 |
| -/* |
1458 |
| - * Loop over each key in the |
1459 |
| - * constraint and check that there |
1460 |
| - * is a corresponding key in the |
1461 |
| - * index. |
1462 |
| - */ |
1463 |
| -intkeys_matched=0; |
1464 |
| - |
1465 |
| -i=0; |
1466 |
| -foreach(keyl,constr->keys) |
1467 |
| -{ |
1468 |
| -Ident*key=lfirst(keyl); |
1469 |
| -intkeyno=indexStruct->indkey[i]; |
1470 |
| - |
1471 |
| -/* |
1472 |
| - * Look at key[i] in the index |
1473 |
| - * and check that it is over |
1474 |
| - * the same column as key[i] |
1475 |
| - * in the constraint. This is |
1476 |
| - * to differentiate between |
1477 |
| - * (a,b) and (b,a) |
1478 |
| - */ |
1479 |
| -if (namestrcmp(attnumAttName(rel,keyno), |
1480 |
| -key->name)==0) |
1481 |
| -keys_matched++; |
1482 |
| -else |
1483 |
| -break; |
1484 |
| -i++; |
1485 |
| -} |
1486 |
| -if (keys_matched==num_keys) |
1487 |
| -{ |
1488 |
| -index_found= true; |
1489 |
| -index_found_unique=indexStruct->indisunique; |
1490 |
| -index_found_primary=indexStruct->indisprimary; |
1491 |
| -} |
1492 |
| -} |
1493 |
| -ReleaseSysCache(indexTuple); |
1494 |
| -if (index_found_unique||index_found_primary) |
1495 |
| -break; |
1496 |
| -} |
1497 |
| - |
1498 |
| -freeList(indexoidlist); |
1499 |
| - |
1500 |
| -if (index_found_primary) |
1501 |
| -elog(ERROR,"Unique primary key already defined on relation \"%s\"",relationName); |
1502 |
| -elseif (index_found_unique) |
1503 |
| -elog(ERROR,"Unique constraint already defined on the specified attributes in relation \"%s\"",relationName); |
1504 |
| - |
1505 |
| -/* |
1506 |
| - * If everything is ok, create the new |
1507 |
| - * index (constraint) |
1508 |
| - */ |
1509 |
| -DefineIndex( |
1510 |
| -relationName, |
1511 |
| -iname, |
1512 |
| -"btree", |
1513 |
| -constr->keys, |
1514 |
| -true, |
1515 |
| -false, |
1516 |
| -NULL, |
1517 |
| -NIL); |
1518 |
| - |
1519 |
| -/* Issue notice */ |
1520 |
| -elog(NOTICE,"ALTER TABLE / ADD UNIQUE will create implicit index '%s' for table '%s'", |
1521 |
| -iname,relationName); |
1522 |
| -if (index_found) |
1523 |
| -elog(NOTICE,"Unique constraint supercedes existing index on relation \"%s\". Drop the existing index to remove redundancy.",relationName); |
1524 |
| -pfree(iname); |
1525 |
| - |
1526 | 1360 | break;
|
1527 | 1361 | }
|
1528 | 1362 | default:
|
|