Release 1.0.6. Workaround for 8.2 and 8.3.
This commit is contained in:
parent
2f2fa142b8
commit
27e6839132
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
#include "fmgr.h"
|
||||
#include "pgut-be.h"
|
||||
|
||||
#if PG_VERSION_NUM < 80400
|
||||
|
@ -38,8 +38,6 @@
|
||||
#define PageAddItem(page, item, size, offnum, overwrite, is_heap) \
|
||||
PageAddItem((page), (item), (size), (offnum), LP_USED)
|
||||
|
||||
typedef void *SPIPlanPtr;
|
||||
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM < 80400
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "postgres.h"
|
||||
#include "pgut-spi.h"
|
||||
|
||||
#define EXEC_FAILED(ret, expected) \
|
||||
(((expected) > 0 && (ret) != (expected)) || (ret) < 0)
|
||||
|
||||
static void
|
||||
termStringInfo(StringInfo str)
|
||||
{
|
||||
@ -17,12 +20,23 @@ termStringInfo(StringInfo str)
|
||||
pfree(str->data);
|
||||
}
|
||||
|
||||
/* appendStringInfoVA + automatic buffer extension */
|
||||
static void
|
||||
appendStringInfoVA_s(StringInfo str, const char *fmt, va_list args)
|
||||
{
|
||||
while (!appendStringInfoVA(str, fmt, args))
|
||||
{
|
||||
/* Double the buffer size and try again. */
|
||||
enlargeStringInfo(str, str->maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
/* simple execute */
|
||||
void
|
||||
execute(int expected, const char *sql)
|
||||
{
|
||||
int ret = SPI_execute(sql, false, 0);
|
||||
if ((expected > 0 && ret != expected) || ret < 0)
|
||||
if EXEC_FAILED(ret, expected)
|
||||
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql, ret, expected);
|
||||
}
|
||||
|
||||
@ -31,7 +45,7 @@ void
|
||||
execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls)
|
||||
{
|
||||
int ret = SPI_execute_plan(plan, values, nulls, false, 0);
|
||||
if ((expected > 0 && ret != expected) || ret < 0)
|
||||
if EXEC_FAILED(ret, expected)
|
||||
elog(ERROR, "query failed: (code=%d, expected=%d)", ret, expected);
|
||||
}
|
||||
|
||||
@ -45,11 +59,13 @@ execute_with_format(int expected, const char *format, ...)
|
||||
|
||||
initStringInfo(&sql);
|
||||
va_start(ap, format);
|
||||
appendStringInfoVA(&sql, format, ap);
|
||||
appendStringInfoVA_s(&sql, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (strlen(sql.data) == 0)
|
||||
elog(WARNING, "execute_with_format(%s)", format);
|
||||
ret = SPI_exec(sql.data, 0);
|
||||
if ((expected > 0 && ret != expected) || ret < 0)
|
||||
if EXEC_FAILED(ret, expected)
|
||||
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql.data, ret, expected);
|
||||
|
||||
termStringInfo(&sql);
|
||||
@ -66,7 +82,7 @@ execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datu
|
||||
c_nulls[i] = (nulls[i] ? 'n' : ' ');
|
||||
|
||||
ret = SPI_execute_with_args(src, nargs, argtypes, values, c_nulls, false, 0);
|
||||
if ((expected > 0 && ret != expected) || ret < 0)
|
||||
if EXEC_FAILED(ret, expected)
|
||||
elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", src, ret, expected);
|
||||
}
|
||||
|
||||
@ -78,7 +94,7 @@ execute_with_format_args(int expected, const char *format, int nargs, Oid argtyp
|
||||
|
||||
initStringInfo(&sql);
|
||||
va_start(ap, nulls);
|
||||
appendStringInfoVA(&sql, format, ap);
|
||||
appendStringInfoVA_s(&sql, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
execute_with_args(expected, sql.data, nargs, argtypes, values, nulls);
|
||||
|
@ -12,13 +12,11 @@
|
||||
|
||||
#include "executor/spi.h"
|
||||
|
||||
extern void execute(int expected, const char *sql);
|
||||
extern void execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls);
|
||||
extern void execute_with_format(int expected, const char *format, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
extern void execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datum values[], const bool nulls[]);
|
||||
extern void execute_with_format_args(int expected, const char *format, int nargs, Oid argtypes[], Datum values[], const bool nulls[], ...)
|
||||
__attribute__((format(printf, 2, 7)));
|
||||
#if PG_VERSION_NUM < 80300
|
||||
|
||||
typedef void *SPIPlanPtr;
|
||||
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM < 80400
|
||||
|
||||
@ -27,4 +25,12 @@ extern int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes,
|
||||
|
||||
#endif
|
||||
|
||||
extern void execute(int expected, const char *sql);
|
||||
extern void execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls);
|
||||
extern void execute_with_format(int expected, const char *format, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
extern void execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datum values[], const bool nulls[]);
|
||||
extern void execute_with_format_args(int expected, const char *format, int nargs, Oid argtypes[], Datum values[], const bool nulls[], ...)
|
||||
__attribute__((format(printf, 2, 7)));
|
||||
|
||||
#endif /* PGUT_SPI_H */
|
||||
|
106
lib/reorg.c
106
lib/reorg.c
@ -23,8 +23,8 @@
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
#include "pgut/pgut-be.h"
|
||||
#include "pgut/pgut-spi.h"
|
||||
#include "pgut/pgut-be.h"
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
@ -468,6 +468,89 @@ getint16(HeapTuple tuple, TupleDesc desc, int column)
|
||||
return isnull ? 0 : DatumGetInt16(datum);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_dropped_columns_and_adjust_attnum(Oid oid, int16 natts1, int16 natts2)
|
||||
{
|
||||
/* delete dropped columns */
|
||||
execute_with_format(SPI_OK_DELETE,
|
||||
"DELETE FROM pg_catalog.pg_attribute"
|
||||
" WHERE attrelid = %u AND attisdropped",
|
||||
oid);
|
||||
if (SPI_processed != natts1 - natts2)
|
||||
elog(ERROR, "cannot remove %d dropped columns (%u columns removed)",
|
||||
natts2 - natts1, SPI_processed);
|
||||
|
||||
/* renumber attnum */
|
||||
#if PG_VERSION_NUM >= 80300
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_attribute"
|
||||
" SET attnum = (SELECT count(*) FROM pg_attribute a"
|
||||
" WHERE pg_catalog.pg_attribute.attrelid = a.attrelid"
|
||||
" AND pg_catalog.pg_attribute.attnum >= a.attnum"
|
||||
" AND a.attnum > 0 AND NOT a.attisdropped)"
|
||||
" WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped",
|
||||
oid);
|
||||
if (SPI_processed != natts2)
|
||||
elog(ERROR, "cannot update %d columns (%u columns updated)",
|
||||
natts2, SPI_processed);
|
||||
#else
|
||||
/*
|
||||
* Use count(*) in subquery because 8.2 doesn't support aggregates
|
||||
* in UPDATE SET.
|
||||
*/
|
||||
do
|
||||
{
|
||||
uint32 i;
|
||||
uint32 ntuples;
|
||||
SPITupleTable *tuptable;
|
||||
TupleDesc desc;
|
||||
|
||||
execute_with_format(SPI_OK_SELECT,
|
||||
"SELECT attnum FROM pg_catalog.pg_attribute"
|
||||
" WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped"
|
||||
" ORDER BY attnum",
|
||||
oid);
|
||||
if (SPI_processed != natts2)
|
||||
elog(ERROR, "number of columns should be %d (%d returned)",
|
||||
natts2, SPI_processed);
|
||||
|
||||
ntuples = SPI_processed;
|
||||
tuptable = SPI_tuptable;
|
||||
desc = tuptable->tupdesc;
|
||||
|
||||
for (i = 0; i < ntuples; i++)
|
||||
{
|
||||
int attnum;
|
||||
int count;
|
||||
|
||||
attnum = getint16(tuptable->vals[i], desc, 1);
|
||||
|
||||
execute_with_format(SPI_OK_SELECT,
|
||||
"SELECT count(*)::smallint FROM pg_catalog.pg_attribute"
|
||||
" WHERE attrelid = %u AND attnum > 0 AND attnum <= %d",
|
||||
oid, attnum);
|
||||
if (SPI_processed != 1)
|
||||
elog(ERROR, "cannot adjust column %d", attnum);
|
||||
|
||||
count = getint16(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
|
||||
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_attribute"
|
||||
" SET attnum = %d"
|
||||
" WHERE attrelid = %u AND attnum = %d",
|
||||
count, oid, attnum);
|
||||
if (SPI_processed != 1)
|
||||
elog(ERROR, "cannot update column %d", attnum);
|
||||
}
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
/* adjust attribute number of the table */
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_class SET relnatts = %d WHERE oid = %u",
|
||||
natts2, oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn Datum reorg_swap(PG_FUNCTION_ARGS)
|
||||
* @brief Swapping relfilenode of tables and relation ids of toast tables
|
||||
@ -635,26 +718,7 @@ reorg_swap(PG_FUNCTION_ARGS)
|
||||
|
||||
/* adjust attribute numbers if the target table has dropped columns */
|
||||
if (natts1 != natts2)
|
||||
{
|
||||
/* delete dropped columns */
|
||||
execute_with_format(SPI_OK_DELETE,
|
||||
"DELETE FROM pg_catalog.pg_attribute"
|
||||
" WHERE attrelid = %u AND attisdropped",
|
||||
oid);
|
||||
/* renumber attnum */
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_attribute"
|
||||
" SET attnum = (SELECT count(*) FROM pg_attribute a"
|
||||
" WHERE pg_catalog.pg_attribute.attrelid = a.attrelid"
|
||||
" AND pg_catalog.pg_attribute.attnum >= a.attnum"
|
||||
" AND a.attnum > 0 AND NOT a.attisdropped)"
|
||||
" WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped",
|
||||
oid);
|
||||
/* adjust attribute number of the table */
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_class SET relnatts = %d WHERE oid = %u",
|
||||
natts2, oid);
|
||||
}
|
||||
remove_dropped_columns_and_adjust_attnum(oid, natts1, natts2);
|
||||
|
||||
/* drop reorg trigger */
|
||||
execute_with_format(
|
||||
|
Loading…
x
Reference in New Issue
Block a user