From aab19c7db030a334ad478e826fef31d594d02aa2 Mon Sep 17 00:00:00 2001 From: Takahiro Itagaki Date: Fri, 23 Jan 2009 02:33:11 +0000 Subject: [PATCH] Fixed a bug reorganizing tables without toast tables. --- bin/expected/reorg.out | 99 +++++++++++++++++++++++------------------- bin/sql/reorg.sql | 31 +++++++++---- lib/reorg.c | 43 +++++++++++++----- 3 files changed, 110 insertions(+), 63 deletions(-) diff --git a/bin/expected/reorg.out b/bin/expected/reorg.out index 2f70acc..de7efb1 100755 --- a/bin/expected/reorg.out +++ b/bin/expected/reorg.out @@ -27,63 +27,68 @@ CREATE TABLE tbl_gistkey ( ); CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; +-- +-- insert data +-- INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); +INSERT INTO tbl_only_pkey VALUES(1, 'abc'); +INSERT INTO tbl_only_pkey VALUES(2, 'def'); +INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); +INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); +INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); +INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); -- -- do reorg -- +\! pg_reorg --dbname=contrib_regression --no-order +\! pg_reorg --dbname=contrib_regression \! pg_reorg --dbname=contrib_regression --table=tbl_cluster -- -- results -- -\d+ tbl_cluster - Table "public.tbl_cluster" - Column | Type | Modifiers | Storage | Description ---------+-----------------------------+-----------+----------+------------- - col1 | integer | not null | plain | - col2 | timestamp without time zone | | plain | - :-) | text | not null | extended | +\d tbl_cluster + Table "public.tbl_cluster" + Column | Type | Modifiers +--------+-----------------------------+----------- + col1 | integer | not null + col2 | timestamp without time zone | + :-) | text | not null Indexes: "tbl_cluster_pkey" PRIMARY KEY, btree (":-)", col1) "cidx_cluster" btree (col2, length(":-)")) CLUSTER -Has OIDs: no -Options: fillfactor=70 -\d+ tbl_gistkey - Table "public.tbl_gistkey" - Column | Type | Modifiers | Storage | Description ---------+---------+-----------+---------+------------- - id | integer | not null | plain | - c | circle | | plain | +\d tbl_gistkey + Table "public.tbl_gistkey" + Column | Type | Modifiers +--------+---------+----------- + id | integer | not null + c | circle | Indexes: "tbl_gistkey_pkey" PRIMARY KEY, btree (id) "cidx_circle" gist (c) CLUSTER -Has OIDs: no -\d+ tbl_only_ckey - Table "public.tbl_only_ckey" - Column | Type | Modifiers | Storage | Description ---------+-----------------------------+-----------+----------+------------- - col1 | integer | | plain | - col2 | timestamp without time zone | | plain | - :-) | text | | extended | +\d tbl_only_ckey + Table "public.tbl_only_ckey" + Column | Type | Modifiers +--------+-----------------------------+----------- + col1 | integer | + col2 | timestamp without time zone | + :-) | text | Indexes: "cidx_only_ckey" btree (col2, ":-)") CLUSTER -Has OIDs: no -Options: fillfactor=70 -\d+ tbl_only_pkey - Table "public.tbl_only_pkey" - Column | Type | Modifiers | Storage | Description ---------+---------+-----------+----------+------------- - col1 | integer | not null | plain | - :-) | text | | extended | +\d tbl_only_pkey + Table "public.tbl_only_pkey" + Column | Type | Modifiers +--------+---------+----------- + col1 | integer | not null + :-) | text | Indexes: "tbl_only_pkey_pkey" PRIMARY KEY, btree (col1) -Has OIDs: no SET synchronize_seqscans = off; SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster; @@ -96,27 +101,33 @@ SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster; 1 | 2008-12-31 10:00:00 | admin (5 rows) -SELECT * FROM tbl_gistkey; - id | c -----+--- -(0 rows) +SELECT * FROM tbl_only_ckey ORDER BY 1; + col1 | col2 | :-) +------+--------------------------+----- + 1 | Tue Jan 01 00:00:00 2008 | abc + 2 | Fri Feb 01 00:00:00 2008 | def +(2 rows) -SELECT * FROM tbl_only_ckey; - col1 | col2 | :-) -------+------+----- -(0 rows) - -SELECT * FROM tbl_only_pkey; +SELECT * FROM tbl_only_pkey ORDER BY 1; col1 | :-) ------+----- -(0 rows) + 1 | abc + 2 | def +(2 rows) + +SELECT * FROM tbl_gistkey ORDER BY 1; + id | c +----+----------- + 1 | <(1,2),3> + 2 | <(4,5),6> +(2 rows) RESET synchronize_seqscans; -- -- clean up -- DROP TABLE tbl_cluster; -DROP TABLE tbl_gistkey; DROP TABLE tbl_only_pkey; DROP TABLE tbl_only_ckey; +DROP TABLE tbl_gistkey; RESET client_min_messages; diff --git a/bin/sql/reorg.sql b/bin/sql/reorg.sql index 6aa546f..f085b4d 100755 --- a/bin/sql/reorg.sql +++ b/bin/sql/reorg.sql @@ -34,32 +34,47 @@ CREATE TABLE tbl_gistkey ( CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; +-- +-- insert data +-- + INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); +INSERT INTO tbl_only_pkey VALUES(1, 'abc'); +INSERT INTO tbl_only_pkey VALUES(2, 'def'); + +INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); +INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); + +INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); +INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); + -- -- do reorg -- +\! pg_reorg --dbname=contrib_regression --no-order +\! pg_reorg --dbname=contrib_regression \! pg_reorg --dbname=contrib_regression --table=tbl_cluster -- -- results -- -\d+ tbl_cluster -\d+ tbl_gistkey -\d+ tbl_only_ckey -\d+ tbl_only_pkey +\d tbl_cluster +\d tbl_gistkey +\d tbl_only_ckey +\d tbl_only_pkey SET synchronize_seqscans = off; SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster; -SELECT * FROM tbl_gistkey; -SELECT * FROM tbl_only_ckey; -SELECT * FROM tbl_only_pkey; +SELECT * FROM tbl_only_ckey ORDER BY 1; +SELECT * FROM tbl_only_pkey ORDER BY 1; +SELECT * FROM tbl_gistkey ORDER BY 1; RESET synchronize_seqscans; -- @@ -67,7 +82,7 @@ RESET synchronize_seqscans; -- DROP TABLE tbl_cluster; -DROP TABLE tbl_gistkey; DROP TABLE tbl_only_pkey; DROP TABLE tbl_only_ckey; +DROP TABLE tbl_gistkey; RESET client_min_messages; diff --git a/lib/reorg.c b/lib/reorg.c index bfd4cd1..49c81e4 100755 --- a/lib/reorg.c +++ b/lib/reorg.c @@ -25,16 +25,12 @@ #include "utils/relcache.h" #include "utils/syscache.h" -#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; -#endif -#if PG_VERSION_NUM < 80300 #if PG_VERSION_NUM < 80300 #define SET_VARSIZE(PTR, len) (VARATT_SIZEP((PTR)) = (len)) typedef void *SPIPlanPtr; #endif -#endif Datum reorg_trigger(PG_FUNCTION_ARGS); @@ -513,11 +509,10 @@ reorg_swap(PG_FUNCTION_ARGS) reorg_execd( "SELECT X.oid, X.reltoastrelid, TX.reltoastidxid," " Y.oid, Y.reltoastrelid, TY.reltoastidxid" - " FROM pg_class X, pg_class Y, pg_class TX, pg_class TY" + " FROM pg_class X LEFT JOIN pg_class TX ON X.reltoastrelid = TX.oid," + " pg_class Y LEFT JOIN pg_class TY ON Y.reltoastrelid = TY.oid" " WHERE X.oid = $1" - " AND X.reltoastrelid = TX.oid" - " AND Y.oid = ('reorg.table_' || X.oid)::regclass" - " AND Y.reltoastrelid = TY.oid", + " AND Y.oid = ('reorg.table_' || X.oid)::regclass", 1, argtypes, values, nulls, SPI_OK_SELECT); tuptable = SPI_tuptable; @@ -525,7 +520,7 @@ reorg_swap(PG_FUNCTION_ARGS) records = SPI_processed; if (records == 0) - elog(ERROR, "reorg_swap : unexpected"); + elog(ERROR, "reorg_swap : no swap target"); tuple = tuptable->vals[0]; @@ -535,6 +530,16 @@ reorg_swap(PG_FUNCTION_ARGS) reltoastrelid2 = getoid(tuple, desc, 5); reltoastidxid2 = getoid(tuple, desc, 6); + /* should be all-or-nothing */ + if ((reltoastrelid1 == InvalidOid || reltoastidxid1 == InvalidOid || + reltoastrelid2 == InvalidOid || reltoastidxid2 == InvalidOid) && + (reltoastrelid1 != InvalidOid || reltoastidxid1 != InvalidOid || + reltoastrelid2 != InvalidOid || reltoastidxid2 != InvalidOid)) + { + elog(ERROR, "reorg_swap : unexpected toast relations (T1=%u, I1=%u, T2=%u, I2=%u", + reltoastrelid1, reltoastidxid1, reltoastrelid2, reltoastidxid2); + } + swap_heap_or_index_files(oid, oid2); CommandCounterIncrement(); @@ -566,7 +571,7 @@ reorg_swap(PG_FUNCTION_ARGS) { char name[NAMEDATALEN]; int pid = getpid(); - + /* rename X to TEMP */ snprintf(name, NAMEDATALEN, "pg_toast_pid%d", pid); RenameRelationInternal(reltoastrelid1, name, PG_TOAST_NAMESPACE); @@ -886,6 +891,9 @@ swap_heap_or_index_files(Oid r1, Oid r2) } #if PG_VERSION_NUM < 80400 + +extern PGDLLIMPORT bool allowSystemTableMods; + static int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, @@ -918,6 +926,19 @@ cstring_to_text(const char * s) static void RenameRelationInternal(Oid myrelid, const char *newrelname, Oid namespaceId) { - renamerel(myrelid, newrelname, OBJECT_TABLE); + bool save_allowSystemTableMods = allowSystemTableMods; + + allowSystemTableMods = true; + PG_TRY(); + { + renamerel(myrelid, newrelname, OBJECT_TABLE); + allowSystemTableMods = save_allowSystemTableMods; + } + PG_CATCH(); + { + allowSystemTableMods = save_allowSystemTableMods; + PG_RE_THROW(); + } + PG_END_TRY(); } #endif