Fixed database corruption when target tables have dropped columns, and
there are views or functions depending on columns after dropped ones. The issue was reported by depesz, and original patch by Denish Patel. Improved documentation how to build binaries from source. COPYRIGHT updated.
This commit is contained in:
parent
830ef422ad
commit
960930b645
10
COPYRIGHT
10
COPYRIGHT
@ -1,4 +1,5 @@
|
||||
Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -9,10 +10,9 @@ modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
(NTT) nor the names of its contributors may be used to endorse or
|
||||
promote products derived from this software without specific prior
|
||||
written permission.
|
||||
* Neither the name of the authors nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
3
Makefile
3
Makefile
@ -1,7 +1,8 @@
|
||||
#
|
||||
# pg_reorg: Makefile
|
||||
#
|
||||
# Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
#
|
||||
ifndef USE_PGXS
|
||||
top_builddir = ../..
|
||||
|
@ -1,7 +1,8 @@
|
||||
#
|
||||
# pg_reorg: bin/Makefile
|
||||
#
|
||||
# Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
#
|
||||
SRCS = pg_reorg.c pgut/pgut.c pgut/pgut-fe.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
@ -66,6 +66,8 @@ ALTER TABLE tbl_with_dropped_column DROP COLUMN d1;
|
||||
ALTER TABLE tbl_with_dropped_column DROP COLUMN d2;
|
||||
ALTER TABLE tbl_with_dropped_column DROP COLUMN d3;
|
||||
ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text;
|
||||
CREATE VIEW view_for_dropped_column AS
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc');
|
||||
INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text);
|
||||
ALTER TABLE tbl_with_dropped_toast DROP COLUMN t;
|
||||
@ -79,6 +81,13 @@ SELECT * FROM tbl_with_dropped_column;
|
||||
c1 | 1 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
c1 | id | c2 | c3
|
||||
----+----+----+----
|
||||
c1 | 2 | c2 |
|
||||
c1 | 1 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
i | j
|
||||
---+----
|
||||
@ -188,6 +197,8 @@ SELECT * FROM tbl_gistkey ORDER BY 1;
|
||||
2 | <(4,5),6>
|
||||
(2 rows)
|
||||
|
||||
SET enable_seqscan = on;
|
||||
SET enable_indexscan = off;
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
c1 | id | c2 | c3
|
||||
----+----+----+----
|
||||
@ -195,6 +206,13 @@ SELECT * FROM tbl_with_dropped_column;
|
||||
c1 | 2 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
c1 | id | c2 | c3
|
||||
----+----+----+----
|
||||
c1 | 1 | c2 |
|
||||
c1 | 2 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
i | j
|
||||
---+----
|
||||
@ -202,6 +220,31 @@ SELECT * FROM tbl_with_dropped_toast;
|
||||
2 | 20
|
||||
(2 rows)
|
||||
|
||||
SET enable_seqscan = off;
|
||||
SET enable_indexscan = on;
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
c1 | id | c2 | c3
|
||||
----+----+----+----
|
||||
c1 | 1 | c2 |
|
||||
c1 | 2 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
c1 | id | c2 | c3
|
||||
----+----+----+----
|
||||
c1 | 1 | c2 |
|
||||
c1 | 2 | c2 |
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
i | j
|
||||
---+----
|
||||
1 | 10
|
||||
2 | 20
|
||||
(2 rows)
|
||||
|
||||
RESET enable_seqscan;
|
||||
RESET enable_indexscan;
|
||||
--
|
||||
-- check broken links or orphan toast relations
|
||||
--
|
||||
|
@ -1,14 +1,15 @@
|
||||
/*
|
||||
* pg_reorg.c: bin/pg_reorg.c
|
||||
*
|
||||
* Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Client Modules
|
||||
*/
|
||||
|
||||
const char *PROGRAM_VERSION = "1.1.5";
|
||||
const char *PROGRAM_VERSION = "1.1.6";
|
||||
const char *PROGRAM_URL = "http://reorg.projects.postgresql.org/";
|
||||
const char *PROGRAM_EMAIL = "reorg-general@lists.pgfoundry.org";
|
||||
|
||||
@ -19,6 +20,10 @@ const char *PROGRAM_EMAIL = "reorg-general@lists.pgfoundry.org";
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* APPLY_COUNT: Number of applied logs per transaction. Larger values
|
||||
* could be faster, but will be long transactions in the REDO phase.
|
||||
*/
|
||||
#define APPLY_COUNT 1000
|
||||
|
||||
#define SQL_XID_SNAPSHOT_80300 \
|
||||
@ -60,6 +65,7 @@ typedef struct reorg_table
|
||||
const char *create_log; /* CREATE TABLE log */
|
||||
const char *create_trigger; /* CREATE TRIGGER z_reorg_trigger */
|
||||
const char *create_table; /* CREATE TABLE table AS SELECT */
|
||||
const char *drop_columns; /* ALTER TABLE DROP COLUMNs */
|
||||
const char *delete_log; /* DELETE FROM log */
|
||||
const char *lock_table; /* LOCK TABLE table */
|
||||
const char *sql_peek; /* SQL used in flush */
|
||||
@ -300,6 +306,7 @@ reorg_one_database(const char *orderby, const char *table)
|
||||
table.create_trigger = getstr(res, i, c++);
|
||||
|
||||
create_table = getstr(res, i, c++);
|
||||
table.drop_columns = getstr(res, i, c++);
|
||||
table.delete_log = getstr(res, i, c++);
|
||||
table.lock_table = getstr(res, i, c++);
|
||||
ckey = getstr(res, i, c++);
|
||||
@ -393,6 +400,7 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
||||
elog(DEBUG2, "create_log : %s", table->create_log);
|
||||
elog(DEBUG2, "create_trigger : %s", table->create_trigger);
|
||||
elog(DEBUG2, "create_table : %s", table->create_table);
|
||||
elog(DEBUG2, "drop_columns : %s", table->drop_columns ? table->drop_columns : "(skipped)");
|
||||
elog(DEBUG2, "delete_log : %s", table->delete_log);
|
||||
elog(DEBUG2, "lock_table : %s", table->lock_table);
|
||||
elog(DEBUG2, "sql_peek : %s", table->sql_peek);
|
||||
@ -450,6 +458,8 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
||||
command(table->delete_log, 0, NULL);
|
||||
command(table->create_table, 0, NULL);
|
||||
printfStringInfo(&sql, "SELECT reorg.disable_autovacuum('reorg.table_%u')", table->target_oid);
|
||||
if (table->drop_columns)
|
||||
command(table->drop_columns, 0, NULL);
|
||||
command(sql.data, 0, NULL);
|
||||
command("COMMIT", 0, NULL);
|
||||
|
||||
@ -635,7 +645,7 @@ reorg_cleanup(bool fatal, void *userdata)
|
||||
|
||||
if (fatal)
|
||||
{
|
||||
fprintf(stderr, "!!!FATAL ERROR!!! Please refer to a manual.\n\n");
|
||||
fprintf(stderr, "!!!FATAL ERROR!!! Please refer to the manual.\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -671,6 +681,6 @@ pgut_help(bool details)
|
||||
printf(" -t, --table=TABLE reorg specific table only\n");
|
||||
printf(" -n, --no-order do vacuum full instead of cluster\n");
|
||||
printf(" -o, --order-by=columns order by columns instead of cluster keys\n");
|
||||
printf(" -T, --wait-timeout=secs timeout to cancel other backends on conflict.\n");
|
||||
printf(" -T, --wait-timeout=secs timeout to cancel other backends on conflict\n");
|
||||
printf(" -Z, --no-analyze don't analyze at end\n");
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-fe.c
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-fe.h
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut.c
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut.h
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -80,6 +80,8 @@ ALTER TABLE tbl_with_dropped_column DROP COLUMN d1;
|
||||
ALTER TABLE tbl_with_dropped_column DROP COLUMN d2;
|
||||
ALTER TABLE tbl_with_dropped_column DROP COLUMN d3;
|
||||
ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text;
|
||||
CREATE VIEW view_for_dropped_column AS
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
|
||||
INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc');
|
||||
INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text);
|
||||
@ -89,6 +91,7 @@ ALTER TABLE tbl_with_dropped_toast DROP COLUMN t;
|
||||
--
|
||||
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
|
||||
--
|
||||
@ -114,8 +117,19 @@ SELECT col1, to_char("time", 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster;
|
||||
SELECT * FROM tbl_only_ckey ORDER BY 1;
|
||||
SELECT * FROM tbl_only_pkey ORDER BY 1;
|
||||
SELECT * FROM tbl_gistkey ORDER BY 1;
|
||||
|
||||
SET enable_seqscan = on;
|
||||
SET enable_indexscan = off;
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
SET enable_seqscan = off;
|
||||
SET enable_indexscan = on;
|
||||
SELECT * FROM tbl_with_dropped_column;
|
||||
SELECT * FROM view_for_dropped_column;
|
||||
SELECT * FROM tbl_with_dropped_toast;
|
||||
RESET enable_seqscan;
|
||||
RESET enable_indexscan;
|
||||
|
||||
--
|
||||
-- check broken links or orphan toast relations
|
||||
|
@ -121,7 +121,10 @@ CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||
<p class="footer">
|
||||
Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION<br />
|
||||
Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
|
@ -122,7 +122,10 @@ CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
|
||||
</center>
|
||||
|
||||
<hr />
|
||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||
<p class="footer">
|
||||
Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION<br />
|
||||
Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
|
@ -8,7 +8,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="pg_reorg">pg_reorg 1.1.3</h1>
|
||||
<h1 id="pg_reorg">pg_reorg 1.1.6</h1>
|
||||
<div class="navigation">
|
||||
<a href="index-ja.html">Top</a> >
|
||||
<a href="pg_reorg-ja.html">pg_reorg</a>
|
||||
@ -291,20 +291,29 @@ pg_reorg の実行中には、VACUUM と ANALYZE <STRONG>以外</STRONG> のDDL
|
||||
最後にシステムカタログを直接書き換えることで、元のテーブルと名前を交換しています。</p>
|
||||
|
||||
<h2 id="install">インストール方法</h2>
|
||||
<p>pgxs を使ってビルドできます。</p>
|
||||
<p>
|
||||
UNIX や Linux では、make を実行すると自動的に pgxs を使ってビルドできます。
|
||||
前もって PostgreSQL 開発用パッケージ (postgresql-devel 等) をインストールし、pg_config にパスを通してください。
|
||||
</p>
|
||||
<pre>$ cd pg_reorg
|
||||
$ make USE_PGXS=1
|
||||
$ make
|
||||
$ su
|
||||
$ make USE_PGXS=1 install</pre>
|
||||
$ make install</pre>
|
||||
<p>
|
||||
Windows では Microsoft Visual C++ 2010 でビルドできます。
|
||||
msvc フォルダ内にプロジェクトファイルがあります。
|
||||
</p>
|
||||
|
||||
<p>その後、データベースに関数を登録します。</p>
|
||||
<pre>$ pg_ctl start
|
||||
$ psql -f $PGSHARE/contrib/pg_reorg.sql your_database</pre>
|
||||
$ psql -f $PGSHARE/contrib/pg_reorg.sql -d your_database</pre>
|
||||
|
||||
<p>(注意: <code>CREATE EXTENSION</code> はまだサポートしていません。)</p>
|
||||
|
||||
<h2 id="requirement">動作環境</h2>
|
||||
<dl>
|
||||
<dt>PostgreSQLバージョン</dt>
|
||||
<dd>PostgreSQL 8.3, 8.4, 9.0</dd>
|
||||
<dd>PostgreSQL 8.2, 8.3, 8.4, 9.0, 9.1</dd>
|
||||
<dt>OS</dt>
|
||||
<dd>RHEL 5.2, Windows XP SP3</dd>
|
||||
<dt>ディスク容量</dt>
|
||||
@ -320,7 +329,10 @@ $ psql -f $PGSHARE/contrib/pg_reorg.sql your_database</pre>
|
||||
<a href="index-ja.html">Top</a> >
|
||||
<a href="pg_reorg-ja.html">pg_reorg</a>
|
||||
<div>
|
||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||
<p class="footer">
|
||||
Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION<br />
|
||||
Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
|
@ -8,7 +8,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="pg_reorg">pg_reorg 1.1.3</h1>
|
||||
<h1 id="pg_reorg">pg_reorg 1.1.6</h1>
|
||||
<div class="navigation">
|
||||
<a href="index.html">Top</a> >
|
||||
<a href="pg_reorg.html">pg_reorg</a>
|
||||
@ -279,20 +279,31 @@ In many case pg_reorg would fail and rollback collectly, but there are some case
|
||||
Then, it updates system catalog directly to swap the work table and the original one.</p>
|
||||
|
||||
<h2 id="install">Installations</h2>
|
||||
<p>pg_reorg can be built with pgxs.</p>
|
||||
<p>
|
||||
pg_reorg can be built with "make" on UNIX or Linux.
|
||||
pgxs build framework is used automatically.
|
||||
Before build, you might need to install postgres packages for developper (postgresql-devel, etc.)
|
||||
and add <code>pg_config</code> to your $PATH.
|
||||
</p>
|
||||
<pre>$ cd pg_reorg
|
||||
$ make USE_PGXS=1
|
||||
$ make
|
||||
$ su
|
||||
$ make USE_PGXS=1 install</pre>
|
||||
$ make install</pre>
|
||||
<p>
|
||||
You can also use Microsoft Visual C++ 2010 to build the program on Windows.
|
||||
There are project files in the msvc folder.
|
||||
</p>
|
||||
|
||||
<p>Start PostgreSQL and execute the script to register functions to your database.</p>
|
||||
<pre>$ pg_ctl start
|
||||
$ psql -f $PGSHARE/contrib/pg_reorg.sql your_database</pre>
|
||||
$ psql -f $PGSHARE/contrib/pg_reorg.sql -d your_database</pre>
|
||||
|
||||
<p>(NOTE: <code>CREATE EXTENSION</code> is not supported yet.)</p>
|
||||
|
||||
<h2 id="requirement">Requirements</h2>
|
||||
<dl>
|
||||
<dt>PostgreSQL version</dt>
|
||||
<dd>PostgreSQL 8.3, 8.4, 9.0</dd>
|
||||
<dd>PostgreSQL 8.2, 8.3, 8.4, 9.0, 9.1</dd>
|
||||
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
|
||||
<dt>Disks</dt><dd>Requires amount of disks twice larger than target table and indexes. (If the total size of targets are 1GB, additional 2GB of disks are required.)</dd>
|
||||
</dl>
|
||||
@ -306,7 +317,10 @@ $ psql -f $PGSHARE/contrib/pg_reorg.sql your_database</pre>
|
||||
<a href="index.html">Top</a> >
|
||||
<a href="pg_reorg.html">pg_reorg</a>
|
||||
<div>
|
||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||
<p class="footer">
|
||||
Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION<br />
|
||||
Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
|
@ -1,7 +1,8 @@
|
||||
#
|
||||
# pg_reorg: lib/Makefile
|
||||
#
|
||||
# Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
#
|
||||
SRCS = reorg.c pgut/pgut-be.c pgut/pgut-spi.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* pg_reorg: lib/pg_reorg.sql.in
|
||||
*
|
||||
* Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*/
|
||||
|
||||
-- Adjust this setting to control where the objects get created.
|
||||
@ -106,6 +107,43 @@ $$
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
-- Get a column list for SELECT all columns including dropped ones.
|
||||
-- We use NULLs of integer types for dropped columns (types are not important).
|
||||
CREATE FUNCTION reorg.get_columns_for_create_as(oid)
|
||||
RETURNS text AS
|
||||
$$
|
||||
SELECT array_to_string(reorg.array_accum(c), ',') FROM (SELECT
|
||||
CASE WHEN attisdropped
|
||||
THEN 'NULL::integer AS ' || quote_ident(attname)
|
||||
ELSE quote_ident(attname)
|
||||
END AS c
|
||||
FROM pg_attribute
|
||||
WHERE attrelid = $1 AND attnum > 0 ORDER BY attnum
|
||||
) AS COL
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
-- Get a SQL text to DROP dropped columns for the table,
|
||||
-- or NULL if it has no dropped columns.
|
||||
CREATE FUNCTION reorg.get_drop_columns(oid, text)
|
||||
RETURNS text AS
|
||||
$$
|
||||
SELECT
|
||||
'ALTER TABLE ' || $2 || ' ' || array_to_string(dropped_columns, ', ')
|
||||
FROM (
|
||||
SELECT
|
||||
reorg.array_accum('DROP COLUMN ' || quote_ident(attname)) AS dropped_columns
|
||||
FROM (
|
||||
SELECT * FROM pg_attribute
|
||||
WHERE attrelid = $1 AND attnum > 0 AND attisdropped
|
||||
ORDER BY attnum
|
||||
) T
|
||||
) T
|
||||
WHERE
|
||||
array_upper(dropped_columns, 1) > 0
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
-- includes not only PRIMARY KEYS but also UNIQUE NOT NULL keys
|
||||
CREATE VIEW reorg.primary_keys AS
|
||||
SELECT indrelid, (reorg.array_accum(indexrelid))[1] AS indexrelid
|
||||
@ -130,7 +168,8 @@ CREATE VIEW reorg.tables AS
|
||||
reorg.get_create_index_type(PK.indexrelid, 'reorg.pk_' || R.oid) AS create_pktype,
|
||||
'CREATE TABLE reorg.log_' || R.oid || ' (id bigserial PRIMARY KEY, pk reorg.pk_' || R.oid || ', row ' || reorg.oid2text(R.oid) || ')' AS create_log,
|
||||
reorg.get_create_trigger(R.oid, PK.indexrelid) AS create_trigger,
|
||||
'CREATE TABLE reorg.table_' || R.oid || ' WITH (' || array_to_string(array_append(R.reloptions, 'oids=' || CASE WHEN R.relhasoids THEN 'true' ELSE 'false' END), ',') || ') TABLESPACE ' || coalesce(quote_ident(S.spcname), 'pg_default') || ' AS SELECT * FROM ONLY ' || reorg.oid2text(R.oid) AS create_table,
|
||||
'CREATE TABLE reorg.table_' || R.oid || ' WITH (' || array_to_string(array_append(R.reloptions, 'oids=' || CASE WHEN R.relhasoids THEN 'true' ELSE 'false' END), ',') || ') TABLESPACE ' || coalesce(quote_ident(S.spcname), 'pg_default') || ' AS SELECT ' || reorg.get_columns_for_create_as(R.oid) || ' FROM ONLY ' || reorg.oid2text(R.oid) AS create_table,
|
||||
reorg.get_drop_columns(R.oid, 'reorg.table_' || R.oid) AS drop_columns,
|
||||
'DELETE FROM reorg.log_' || R.oid AS delete_log,
|
||||
'LOCK TABLE ' || reorg.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE' AS lock_table,
|
||||
reorg.get_index_keys(CK.indexrelid, R.oid) AS ckey,
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-be.c
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-be.h
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-spi.c
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgut-spi.h
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
125
lib/reorg.c
125
lib/reorg.c
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* pg_reorg: lib/reorg.c
|
||||
*
|
||||
* Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
@ -75,7 +76,7 @@ static void RenameRelationInternal(Oid myrelid, const char *newrelname, Oid name
|
||||
Datum
|
||||
reorg_version(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return CStringGetTextDatum("pg_reorg 1.1.5");
|
||||
return CStringGetTextDatum("pg_reorg 1.1.6");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -592,101 +593,6 @@ 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 >= 90000
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_attribute m"
|
||||
" SET attnum = (SELECT count(*) FROM pg_attribute a"
|
||||
" WHERE m.attrelid = a.attrelid"
|
||||
" AND m.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);
|
||||
#elif 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
|
||||
@ -799,27 +705,6 @@ reorg_swap(PG_FUNCTION_ARGS)
|
||||
idx2 = getoid(tuple, desc, 2);
|
||||
swap_heap_or_index_files(idx1, idx2);
|
||||
|
||||
/* adjust key attnum if the target table has dropped columns */
|
||||
if (natts1 != natts2)
|
||||
{
|
||||
#if PG_VERSION_NUM >= 90000
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_index m SET indkey = n.indkey"
|
||||
" FROM pg_catalog.pg_index n"
|
||||
" WHERE m.indexrelid = %u"
|
||||
" AND n.indexrelid = 'reorg.index_%u'::regclass",
|
||||
idx1, idx1);
|
||||
#else
|
||||
execute_with_format(SPI_OK_UPDATE,
|
||||
"UPDATE pg_catalog.pg_index SET indkey = n.indkey"
|
||||
" FROM pg_catalog.pg_index n"
|
||||
" WHERE pg_catalog.pg_index.indexrelid = %u"
|
||||
" AND n.indexrelid = 'reorg.index_%u'::regclass",
|
||||
idx1, idx1);
|
||||
#endif
|
||||
if (SPI_processed != 1)
|
||||
elog(ERROR, "failed to update pg_index.indkey (%u rows updated)", SPI_processed);
|
||||
}
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
@ -876,10 +761,6 @@ reorg_swap(PG_FUNCTION_ARGS)
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
/* adjust attribute numbers if the target table has dropped columns */
|
||||
if (natts1 != natts2)
|
||||
remove_dropped_columns_and_adjust_attnum(oid, natts1, natts2);
|
||||
|
||||
/* drop reorg trigger */
|
||||
execute_with_format(
|
||||
SPI_OK_UTILITY,
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* pg_reorg: lib/uninstall_reorg.sql
|
||||
*
|
||||
* Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Portions Copyright (c) 2011, Itagaki Takahiro
|
||||
*/
|
||||
|
||||
DROP SCHEMA IF EXISTS reorg CASCADE;
|
||||
|
@ -312,11 +312,13 @@
|
||||
<None Include="..\bin\Makefile" />
|
||||
<None Include="..\bin\sql\init.sql" />
|
||||
<None Include="..\bin\sql\reorg.sql" />
|
||||
<None Include="..\COPYRIGHT" />
|
||||
<None Include="..\doc\index-ja.html" />
|
||||
<None Include="..\doc\index.html" />
|
||||
<None Include="..\doc\pg_reorg-ja.html" />
|
||||
<None Include="..\doc\pg_reorg.html" />
|
||||
<None Include="..\doc\style.css" />
|
||||
<None Include="..\Makefile" />
|
||||
<None Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -54,6 +54,10 @@
|
||||
<None Include="..\bin\sql\reorg.sql">
|
||||
<Filter>regress\sql</Filter>
|
||||
</None>
|
||||
<None Include="..\COPYRIGHT">
|
||||
<Filter>doc</Filter>
|
||||
</None>
|
||||
<None Include="..\Makefile" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\bin\pg_reorg.c">
|
||||
|
Loading…
x
Reference in New Issue
Block a user