Supports CREATE EXTENSION.
I've changed lib/Makefile to support CREATE EXTENSION. In order to work with previeous PostgreSQL version (i.e. < 9.1), this implementation installs both pg_reorg--1.0.sql and pg_reorg.sql. This patch lacks regression testcases for CREATE EXTENSION, which I will commit soon.
This commit is contained in:
parent
d603c49b40
commit
e9d4ef2557
11
lib/Makefile
11
lib/Makefile
@ -1,14 +1,17 @@
|
||||
#
|
||||
# pg_reorg: lib/Makefile
|
||||
#
|
||||
# Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Portions Copyright (c) 2008-2012, 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)
|
||||
MODULE_big = pg_reorg
|
||||
OBJS = reorg.o pgut/pgut-be.o pgut/pgut-spi.o
|
||||
|
||||
EXTENSION = pg_reorg
|
||||
|
||||
#supports both EXTENSION (for >=9.1) and without_EXTENSION (for <PG 9.1)
|
||||
DATA_built = pg_reorg.sql
|
||||
DATA = uninstall_pg_reorg.sql
|
||||
DATA = pg_reorg--1.0.sql pg_reorg--unpackaged--1.0.sql uninstall_pg_reorg.sql
|
||||
|
||||
ifndef USE_PGXS
|
||||
top_builddir = ../../..
|
||||
|
224
lib/pg_reorg--1.0.sql
Normal file
224
lib/pg_reorg--1.0.sql
Normal file
@ -0,0 +1,224 @@
|
||||
/* pg_reorg/pg_reorg--1.0.sql */
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION pg_reorg" to load this file. \quit
|
||||
|
||||
CREATE FUNCTION reorg.version() RETURNS text AS
|
||||
'MODULE_PATHNAME', 'reorg_version'
|
||||
LANGUAGE C IMMUTABLE STRICT;
|
||||
|
||||
CREATE AGGREGATE reorg.array_accum (
|
||||
sfunc = array_append,
|
||||
basetype = anyelement,
|
||||
stype = anyarray,
|
||||
initcond = '{}'
|
||||
);
|
||||
|
||||
CREATE FUNCTION reorg.oid2text(oid) RETURNS text AS
|
||||
$$
|
||||
SELECT textin(regclassout($1));
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_index_columns(oid, text) RETURNS text AS
|
||||
$$
|
||||
SELECT array_to_string(reorg.array_accum(quote_ident(attname)), $2)
|
||||
FROM pg_attribute,
|
||||
(SELECT indrelid,
|
||||
indkey,
|
||||
generate_series(0, indnatts-1) AS i
|
||||
FROM pg_index
|
||||
WHERE indexrelid = $1
|
||||
) AS keys
|
||||
WHERE attrelid = indrelid
|
||||
AND attnum = indkey[i];
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_index_keys(oid, oid) RETURNS text AS
|
||||
'MODULE_PATHNAME', 'reorg_get_index_keys'
|
||||
LANGUAGE C STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_create_index_type(oid, name) RETURNS text AS
|
||||
$$
|
||||
SELECT 'CREATE TYPE ' || $2 || ' AS (' ||
|
||||
array_to_string(reorg.array_accum(quote_ident(attname) || ' ' ||
|
||||
pg_catalog.format_type(atttypid, atttypmod)), ', ') || ')'
|
||||
FROM pg_attribute,
|
||||
(SELECT indrelid,
|
||||
indkey,
|
||||
generate_series(0, indnatts-1) AS i
|
||||
FROM pg_index
|
||||
WHERE indexrelid = $1
|
||||
) AS keys
|
||||
WHERE attrelid = indrelid
|
||||
AND attnum = indkey[i];
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_create_trigger(relid oid, pkid oid)
|
||||
RETURNS text AS
|
||||
$$
|
||||
SELECT 'CREATE TRIGGER z_reorg_trigger' ||
|
||||
' BEFORE INSERT OR DELETE OR UPDATE ON ' || reorg.oid2text($1) ||
|
||||
' FOR EACH ROW EXECUTE PROCEDURE reorg.reorg_trigger(' ||
|
||||
'''INSERT INTO reorg.log_' || $1 || '(pk, row) VALUES(' ||
|
||||
' CASE WHEN $1 IS NULL THEN NULL ELSE (ROW($1.' ||
|
||||
reorg.get_index_columns($2, ', $1.') || ')::reorg.pk_' ||
|
||||
$1 || ') END, $2)'')';
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_assign(oid, text) RETURNS text AS
|
||||
$$
|
||||
SELECT '(' || array_to_string(reorg.array_accum(attname), ', ') ||
|
||||
') = (' || $2 || '.' ||
|
||||
array_to_string(reorg.array_accum(quote_ident(attname)), ', ' || $2 || '.') || ')'
|
||||
FROM (SELECT attname FROM pg_attribute
|
||||
WHERE attrelid = $1 AND attnum > 0 AND NOT attisdropped
|
||||
ORDER BY attnum) tmp;
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.get_compare_pkey(oid, text)
|
||||
RETURNS text AS
|
||||
$$
|
||||
SELECT '(' || array_to_string(reorg.array_accum(quote_ident(attname)), ', ') ||
|
||||
') = (' || $2 || '.' ||
|
||||
array_to_string(reorg.array_accum(quote_ident(attname)), ', ' || $2 || '.') || ')'
|
||||
FROM pg_attribute,
|
||||
(SELECT indrelid,
|
||||
indkey,
|
||||
generate_series(0, indnatts-1) AS i
|
||||
FROM pg_index
|
||||
WHERE indexrelid = $1
|
||||
) AS keys
|
||||
WHERE attrelid = indrelid
|
||||
AND attnum = indkey[i];
|
||||
$$
|
||||
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
|
||||
FROM (SELECT indrelid, indexrelid FROM pg_index
|
||||
WHERE indisunique
|
||||
AND 0 <> ALL(indkey)
|
||||
AND NOT EXISTS(
|
||||
SELECT 1 FROM pg_attribute
|
||||
WHERE attrelid = indrelid
|
||||
AND attnum = ANY(indkey)
|
||||
AND NOT attnotnull)
|
||||
ORDER BY indrelid, indisprimary DESC, indnatts, indkey) tmp
|
||||
GROUP BY indrelid;
|
||||
|
||||
CREATE VIEW reorg.tables AS
|
||||
SELECT R.oid::regclass AS relname,
|
||||
R.oid AS relid,
|
||||
R.reltoastrelid AS reltoastrelid,
|
||||
CASE WHEN R.reltoastrelid = 0 THEN 0 ELSE (SELECT reltoastidxid FROM pg_class WHERE oid = R.reltoastrelid) END AS reltoastidxid,
|
||||
PK.indexrelid AS pkid,
|
||||
CK.indexrelid AS ckid,
|
||||
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 ' || 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,
|
||||
'SELECT * FROM reorg.log_' || R.oid || ' ORDER BY id LIMIT $1' AS sql_peek,
|
||||
'INSERT INTO reorg.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert,
|
||||
'DELETE FROM reorg.table_' || R.oid || ' WHERE ' || reorg.get_compare_pkey(PK.indexrelid, '$1') AS sql_delete,
|
||||
'UPDATE reorg.table_' || R.oid || ' SET ' || reorg.get_assign(R.oid, '$2') || ' WHERE ' || reorg.get_compare_pkey(PK.indexrelid, '$1') AS sql_update,
|
||||
'DELETE FROM reorg.log_' || R.oid || ' WHERE id <= $1' AS sql_pop
|
||||
FROM pg_class R
|
||||
LEFT JOIN pg_class T ON R.reltoastrelid = T.oid
|
||||
LEFT JOIN reorg.primary_keys PK
|
||||
ON R.oid = PK.indrelid
|
||||
LEFT JOIN (SELECT CKI.* FROM pg_index CKI, pg_class CKT
|
||||
WHERE CKI.indisvalid
|
||||
AND CKI.indexrelid = CKT.oid
|
||||
AND CKI.indisclustered
|
||||
AND CKT.relam = 403) CK
|
||||
ON R.oid = CK.indrelid
|
||||
LEFT JOIN pg_namespace N ON N.oid = R.relnamespace
|
||||
LEFT JOIN pg_tablespace S ON S.oid = R.reltablespace
|
||||
WHERE R.relkind = 'r'
|
||||
AND N.nspname NOT IN ('pg_catalog', 'information_schema')
|
||||
AND N.nspname NOT LIKE E'pg\\_temp\\_%';
|
||||
|
||||
CREATE FUNCTION reorg.reorg_indexdef(oid, oid) RETURNS text AS
|
||||
'MODULE_PATHNAME', 'reorg_indexdef'
|
||||
LANGUAGE C STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.reorg_trigger() RETURNS trigger AS
|
||||
'MODULE_PATHNAME', 'reorg_trigger'
|
||||
LANGUAGE C VOLATILE STRICT SECURITY DEFINER;
|
||||
|
||||
CREATE FUNCTION reorg.conflicted_triggers(oid) RETURNS SETOF name AS
|
||||
$$
|
||||
SELECT tgname FROM pg_trigger
|
||||
WHERE tgrelid = $1 AND tgname >= 'z_reorg_trigger'
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.disable_autovacuum(regclass) RETURNS void AS
|
||||
'MODULE_PATHNAME', 'reorg_disable_autovacuum'
|
||||
LANGUAGE C VOLATILE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.reorg_apply(
|
||||
sql_peek cstring,
|
||||
sql_insert cstring,
|
||||
sql_delete cstring,
|
||||
sql_update cstring,
|
||||
sql_pop cstring,
|
||||
count integer)
|
||||
RETURNS integer AS
|
||||
'MODULE_PATHNAME', 'reorg_apply'
|
||||
LANGUAGE C VOLATILE;
|
||||
|
||||
CREATE FUNCTION reorg.reorg_swap(oid) RETURNS void AS
|
||||
'MODULE_PATHNAME', 'reorg_swap'
|
||||
LANGUAGE C VOLATILE STRICT;
|
||||
|
||||
CREATE FUNCTION reorg.reorg_drop(oid) RETURNS void AS
|
||||
'MODULE_PATHNAME', 'reorg_drop'
|
||||
LANGUAGE C VOLATILE STRICT;
|
25
lib/pg_reorg--unpackaged--1.0.sql
Normal file
25
lib/pg_reorg--unpackaged--1.0.sql
Normal file
@ -0,0 +1,25 @@
|
||||
/* pg_reorg/pg_reorg--unpackaged--1.0.sql */
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION pg_reorg" to load this file. \quit
|
||||
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.version();
|
||||
ALTER EXTENSION pg_reorg ADD AGGREGATE reorg.array_accum (array_append, anyelement, anyarray,'{}');
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.oid2text(oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_index_columns(oid, text);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_index_keys(oid, oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_create_index_type(oid, name);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_create_trigger(relid oid, pkid oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_assign(oid, text);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_compare_pkey(oid, text);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_columns_for_create_as(oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.get_drop_columns(oid, text);
|
||||
ALTER EXTENSION pg_reorg ADD VIEW reorg.primary_keys;
|
||||
ALTER EXTENSION pg_reorg ADD VIEW reorg.tables;
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.reorg_indexdef(oid, oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.reorg_trigger();
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.conflicted_triggers(oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.disable_autovacuum(regclass);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.reorg_apply((cstring,cstring,cstring,cstring,cstring,integer);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.reorg_swap(oid);
|
||||
ALTER EXTENSION pg_reorg ADD FUNCTION reorg.reorg_drop(oid);
|
6
lib/pg_reorg.control
Normal file
6
lib/pg_reorg.control
Normal file
@ -0,0 +1,6 @@
|
||||
# pg_reorg extension
|
||||
comment = 're-organizes a PostgreSQL database'
|
||||
default_version = '1.0'
|
||||
module_pathname = '$libdir/pg_reorg'
|
||||
relocatable = false
|
||||
schema = reorg
|
Loading…
x
Reference in New Issue
Block a user