Skip to content

Commit 27e6839

Browse files
committed
Release 1.0.6. Workaround for 8.2 and 8.3.
1 parent 2f2fa14 commit 27e6839

File tree

5 files changed

+121
-36
lines changed

5 files changed

+121
-36
lines changed

lib/pgut/pgut-be.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include "postgres.h"
11+
#include "fmgr.h"
1112
#include "pgut-be.h"
1213

1314
#if PG_VERSION_NUM < 80400

lib/pgut/pgut-be.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
#define PageAddItem(page, item, size, offnum, overwrite, is_heap) \
3939
PageAddItem((page), (item), (size), (offnum), LP_USED)
4040

41-
typedef void *SPIPlanPtr;
42-
4341
#endif
4442

4543
#if PG_VERSION_NUM < 80400

lib/pgut/pgut-spi.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,33 @@
1010
#include "postgres.h"
1111
#include "pgut-spi.h"
1212

13+
#define EXEC_FAILED(ret, expected) \
14+
(((expected) > 0 && (ret) != (expected)) || (ret) < 0)
15+
1316
static void
1417
termStringInfo(StringInfo str)
1518
{
1619
if (str && str->data)
1720
pfree(str->data);
1821
}
1922

23+
/* appendStringInfoVA + automatic buffer extension */
24+
static void
25+
appendStringInfoVA_s(StringInfo str, const char *fmt, va_list args)
26+
{
27+
while (!appendStringInfoVA(str, fmt, args))
28+
{
29+
/* Double the buffer size and try again. */
30+
enlargeStringInfo(str, str->maxlen);
31+
}
32+
}
33+
2034
/* simple execute */
2135
void
2236
execute(int expected, const char *sql)
2337
{
2438
int ret = SPI_execute(sql, false, 0);
25-
if ((expected > 0 && ret != expected) || ret < 0)
39+
if EXEC_FAILED(ret, expected)
2640
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql, ret, expected);
2741
}
2842

@@ -31,7 +45,7 @@ void
3145
execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls)
3246
{
3347
int ret = SPI_execute_plan(plan, values, nulls, false, 0);
34-
if ((expected > 0 && ret != expected) || ret < 0)
48+
if EXEC_FAILED(ret, expected)
3549
elog(ERROR, "query failed: (code=%d, expected=%d)", ret, expected);
3650
}
3751

@@ -45,11 +59,13 @@ execute_with_format(int expected, const char *format, ...)
4559

4660
initStringInfo(&sql);
4761
va_start(ap, format);
48-
appendStringInfoVA(&sql, format, ap);
62+
appendStringInfoVA_s(&sql, format, ap);
4963
va_end(ap);
5064

65+
if (strlen(sql.data) == 0)
66+
elog(WARNING, "execute_with_format(%s)", format);
5167
ret = SPI_exec(sql.data, 0);
52-
if ((expected > 0 && ret != expected) || ret < 0)
68+
if EXEC_FAILED(ret, expected)
5369
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql.data, ret, expected);
5470

5571
termStringInfo(&sql);
@@ -66,7 +82,7 @@ execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datu
6682
c_nulls[i] = (nulls[i] ? 'n' : ' ');
6783

6884
ret = SPI_execute_with_args(src, nargs, argtypes, values, c_nulls, false, 0);
69-
if ((expected > 0 && ret != expected) || ret < 0)
85+
if EXEC_FAILED(ret, expected)
7086
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", src, ret, expected);
7187
}
7288

@@ -78,7 +94,7 @@ execute_with_format_args(int expected, const char *format, int nargs, Oid argtyp
7894

7995
initStringInfo(&sql);
8096
va_start(ap, nulls);
81-
appendStringInfoVA(&sql, format, ap);
97+
appendStringInfoVA_s(&sql, format, ap);
8298
va_end(ap);
8399

84100
execute_with_args(expected, sql.data, nargs, argtypes, values, nulls);

lib/pgut/pgut-spi.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@
1212

1313
#include "executor/spi.h"
1414

15-
extern void execute(int expected, const char *sql);
16-
extern void execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls);
17-
extern void execute_with_format(int expected, const char *format, ...)
18-
__attribute__((format(printf, 2, 3)));
19-
extern void execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datum values[], const bool nulls[]);
20-
extern void execute_with_format_args(int expected, const char *format, int nargs, Oid argtypes[], Datum values[], const bool nulls[], ...)
21-
__attribute__((format(printf, 2, 7)));
15+
#if PG_VERSION_NUM < 80300
16+
17+
typedef void *SPIPlanPtr;
18+
19+
#endif
2220

2321
#if PG_VERSION_NUM < 80400
2422

@@ -27,4 +25,12 @@ extern int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes,
2725

2826
#endif
2927

28+
extern void execute(int expected, const char *sql);
29+
extern void execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls);
30+
extern void execute_with_format(int expected, const char *format, ...)
31+
__attribute__((format(printf, 2, 3)));
32+
extern void execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datum values[], const bool nulls[]);
33+
extern void execute_with_format_args(int expected, const char *format, int nargs, Oid argtypes[], Datum values[], const bool nulls[], ...)
34+
__attribute__((format(printf, 2, 7)));
35+
3036
#endif /* PGUT_SPI_H */

lib/reorg.c

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
#include "utils/relcache.h"
2424
#include "utils/syscache.h"
2525

26-
#include "pgut/pgut-be.h"
2726
#include "pgut/pgut-spi.h"
27+
#include "pgut/pgut-be.h"
2828

2929
PG_MODULE_MAGIC;
3030

@@ -468,6 +468,89 @@ getint16(HeapTuple tuple, TupleDesc desc, int column)
468468
return isnull ? 0 : DatumGetInt16(datum);
469469
}
470470

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+
471554
/**
472555
* @fn Datum reorg_swap(PG_FUNCTION_ARGS)
473556
* @brief Swapping relfilenode of tables and relation ids of toast tables
@@ -635,26 +718,7 @@ reorg_swap(PG_FUNCTION_ARGS)
635718

636719
/* adjust attribute numbers if the target table has dropped columns */
637720
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);
658722

659723
/* drop reorg trigger */
660724
execute_with_format(

0 commit comments

Comments
 (0)