|
23 | 23 | #include "utils/relcache.h"
|
24 | 24 | #include "utils/syscache.h"
|
25 | 25 |
|
26 |
| -#include "pgut/pgut-be.h" |
27 | 26 | #include "pgut/pgut-spi.h"
|
| 27 | +#include "pgut/pgut-be.h" |
28 | 28 |
|
29 | 29 | PG_MODULE_MAGIC;
|
30 | 30 |
|
@@ -468,6 +468,89 @@ getint16(HeapTuple tuple, TupleDesc desc, int column)
|
468 | 468 | return isnull ? 0 : DatumGetInt16(datum);
|
469 | 469 | }
|
470 | 470 |
|
| 471 | +static void |
| 472 | +remove_dropped_columns_and_adjust_attnum(Oid oid, int16 natts1, int16 natts2) |
| 473 | +{ |
| 474 | + /* delete dropped columns */ |
| 475 | + execute_with_format(SPI_OK_DELETE, |
| 476 | + "DELETE FROM pg_catalog.pg_attribute" |
| 477 | + " WHERE attrelid = %u AND attisdropped", |
| 478 | + oid); |
| 479 | + if (SPI_processed != natts1 - natts2) |
| 480 | + elog(ERROR, "cannot remove %d dropped columns (%u columns removed)", |
| 481 | + natts2 - natts1, SPI_processed); |
| 482 | + |
| 483 | + /* renumber attnum */ |
| 484 | +#if PG_VERSION_NUM >= 80300 |
| 485 | + execute_with_format(SPI_OK_UPDATE, |
| 486 | + "UPDATE pg_catalog.pg_attribute" |
| 487 | + " SET attnum = (SELECT count(*) FROM pg_attribute a" |
| 488 | + " WHERE pg_catalog.pg_attribute.attrelid = a.attrelid" |
| 489 | + " AND pg_catalog.pg_attribute.attnum >= a.attnum" |
| 490 | + " AND a.attnum > 0 AND NOT a.attisdropped)" |
| 491 | + " WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped", |
| 492 | + oid); |
| 493 | + if (SPI_processed != natts2) |
| 494 | + elog(ERROR, "cannot update %d columns (%u columns updated)", |
| 495 | + natts2, SPI_processed); |
| 496 | +#else |
| 497 | + /* |
| 498 | + * Use count(*) in subquery because 8.2 doesn't support aggregates |
| 499 | + * in UPDATE SET. |
| 500 | + */ |
| 501 | + do |
| 502 | + { |
| 503 | + uint32 i; |
| 504 | + uint32 ntuples; |
| 505 | + SPITupleTable *tuptable; |
| 506 | + TupleDesc desc; |
| 507 | + |
| 508 | + execute_with_format(SPI_OK_SELECT, |
| 509 | + "SELECT attnum FROM pg_catalog.pg_attribute" |
| 510 | + " WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped" |
| 511 | + " ORDER BY attnum", |
| 512 | + oid); |
| 513 | + if (SPI_processed != natts2) |
| 514 | + elog(ERROR, "number of columns should be %d (%d returned)", |
| 515 | + natts2, SPI_processed); |
| 516 | + |
| 517 | + ntuples = SPI_processed; |
| 518 | + tuptable = SPI_tuptable; |
| 519 | + desc = tuptable->tupdesc; |
| 520 | + |
| 521 | + for (i = 0; i < ntuples; i++) |
| 522 | + { |
| 523 | + int attnum; |
| 524 | + int count; |
| 525 | + |
| 526 | + attnum = getint16(tuptable->vals[i], desc, 1); |
| 527 | + |
| 528 | + execute_with_format(SPI_OK_SELECT, |
| 529 | + "SELECT count(*)::smallint FROM pg_catalog.pg_attribute" |
| 530 | + " WHERE attrelid = %u AND attnum > 0 AND attnum <= %d", |
| 531 | + oid, attnum); |
| 532 | + if (SPI_processed != 1) |
| 533 | + elog(ERROR, "cannot adjust column %d", attnum); |
| 534 | + |
| 535 | + count = getint16(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); |
| 536 | + |
| 537 | + execute_with_format(SPI_OK_UPDATE, |
| 538 | + "UPDATE pg_catalog.pg_attribute" |
| 539 | + " SET attnum = %d" |
| 540 | + " WHERE attrelid = %u AND attnum = %d", |
| 541 | + count, oid, attnum); |
| 542 | + if (SPI_processed != 1) |
| 543 | + elog(ERROR, "cannot update column %d", attnum); |
| 544 | + } |
| 545 | + } while(0); |
| 546 | +#endif |
| 547 | + |
| 548 | + /* adjust attribute number of the table */ |
| 549 | + execute_with_format(SPI_OK_UPDATE, |
| 550 | + "UPDATE pg_catalog.pg_class SET relnatts = %d WHERE oid = %u", |
| 551 | + natts2, oid); |
| 552 | +} |
| 553 | + |
471 | 554 | /**
|
472 | 555 | * @fn Datum reorg_swap(PG_FUNCTION_ARGS)
|
473 | 556 | * @brief Swapping relfilenode of tables and relation ids of toast tables
|
@@ -635,26 +718,7 @@ reorg_swap(PG_FUNCTION_ARGS)
|
635 | 718 |
|
636 | 719 | /* adjust attribute numbers if the target table has dropped columns */
|
637 | 720 | if (natts1 != natts2)
|
638 |
| - { |
639 |
| - /* delete dropped columns */ |
640 |
| - execute_with_format(SPI_OK_DELETE, |
641 |
| - "DELETE FROM pg_catalog.pg_attribute" |
642 |
| - " WHERE attrelid = %u AND attisdropped", |
643 |
| - oid); |
644 |
| - /* renumber attnum */ |
645 |
| - execute_with_format(SPI_OK_UPDATE, |
646 |
| - "UPDATE pg_catalog.pg_attribute" |
647 |
| - " SET attnum = (SELECT count(*) FROM pg_attribute a" |
648 |
| - " WHERE pg_catalog.pg_attribute.attrelid = a.attrelid" |
649 |
| - " AND pg_catalog.pg_attribute.attnum >= a.attnum" |
650 |
| - " AND a.attnum > 0 AND NOT a.attisdropped)" |
651 |
| - " WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped", |
652 |
| - oid); |
653 |
| - /* adjust attribute number of the table */ |
654 |
| - execute_with_format(SPI_OK_UPDATE, |
655 |
| - "UPDATE pg_catalog.pg_class SET relnatts = %d WHERE oid = %u", |
656 |
| - natts2, oid); |
657 |
| - } |
| 721 | + remove_dropped_columns_and_adjust_attnum(oid, natts1, natts2); |
658 | 722 |
|
659 | 723 | /* drop reorg trigger */
|
660 | 724 | execute_with_format(
|
|
0 commit comments