|
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: |
|