Skip to content

Commit

Permalink
Make sure that all tables remain persistent.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vik Fearing committed Jul 30, 2019
1 parent 6d3934b commit 6b62f82
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 17 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ SELECT * FROM t__between_symmetric('...', '...');

This extension is pretty much feature complete, but there are still many
aspects that need to be handled. For example, there is currently no
management of access control. There should also be proper handling of
users modifying all the things we test for when creating our objects.
management of access control.

## Performance

Expand Down
43 changes: 42 additions & 1 deletion expected/periods.out
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ SELECT periods.add_foreign_key('no_unique_ref', ARRAY['system_time_end'], 'q', '

SELECT periods.add_system_time_period('no_unique_ref'); -- fails
ERROR: columns for SYSTEM_TIME must not be part of foreign keys
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 174 at RAISE
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 171 at RAISE
DROP TABLE no_unique, no_unique_ref;
/* DROP protection */
CREATE TYPE integerrange AS RANGE (SUBTYPE = integer);
Expand Down Expand Up @@ -1037,5 +1037,46 @@ DROP TABLE rename_test_ref;
/* system_versioning */
-- Nothing to do here
DROP TABLE rename_test;
/* Health checks */
CREATE UNLOGGED TABLE log (id bigint, s date, e date);
SELECT periods.add_period('log', 'p', 's', 'e'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_period(regclass,name,name,name,regtype) line 72 at RAISE
SELECT periods.add_system_time_period('log'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 77 at RAISE
ALTER TABLE log SET LOGGED;
SELECT periods.add_period('log', 'p', 's', 'e'); -- passes
add_period
------------
t
(1 row)

SELECT periods.add_system_time_period('log'); -- passes
add_system_time_period
------------------------
t
(1 row)

ALTER TABLE log SET UNLOGGED; -- fails
ERROR: table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 13 at RAISE
SELECT periods.add_system_versioning('log');
NOTICE: history table "log_history" created for "log", be sure to index it properly
add_system_versioning
-----------------------

(1 row)

ALTER TABLE log_history SET UNLOGGED; -- fails
ERROR: history table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 24 at RAISE
SELECT periods.drop_system_versioning('log', purge => true);
drop_system_versioning
------------------------
t
(1 row)

DROP TABLE log;
/* Clean up */
DROP EXTENSION periods;
43 changes: 42 additions & 1 deletion expected/periods_1.out
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ SELECT periods.add_foreign_key('no_unique_ref', ARRAY['system_time_end'], 'q', '

SELECT periods.add_system_time_period('no_unique_ref'); -- fails
ERROR: columns for SYSTEM_TIME must not be part of foreign keys
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 174 at RAISE
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 171 at RAISE
DROP TABLE no_unique, no_unique_ref;
/* DROP protection */
CREATE TYPE integerrange AS RANGE (SUBTYPE = integer);
Expand Down Expand Up @@ -1039,5 +1039,46 @@ DROP TABLE rename_test_ref;
/* system_versioning */
-- Nothing to do here
DROP TABLE rename_test;
/* Health checks */
CREATE UNLOGGED TABLE log (id bigint, s date, e date);
SELECT periods.add_period('log', 'p', 's', 'e'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_period(regclass,name,name,name,regtype) line 72 at RAISE
SELECT periods.add_system_time_period('log'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 77 at RAISE
ALTER TABLE log SET LOGGED;
SELECT periods.add_period('log', 'p', 's', 'e'); -- passes
add_period
------------
t
(1 row)

SELECT periods.add_system_time_period('log'); -- passes
add_system_time_period
------------------------
t
(1 row)

ALTER TABLE log SET UNLOGGED; -- fails
ERROR: table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 13 at RAISE
SELECT periods.add_system_versioning('log');
NOTICE: history table "log_history" created for "log", be sure to index it properly
add_system_versioning
-----------------------

(1 row)

ALTER TABLE log_history SET UNLOGGED; -- fails
ERROR: history table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 24 at RAISE
SELECT periods.drop_system_versioning('log', purge => true);
drop_system_versioning
------------------------
t
(1 row)

DROP TABLE log;
/* Clean up */
DROP EXTENSION periods;
43 changes: 42 additions & 1 deletion expected/periods_2.out
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ SELECT periods.add_foreign_key('no_unique_ref', ARRAY['system_time_end'], 'q', '

SELECT periods.add_system_time_period('no_unique_ref'); -- fails
ERROR: columns for SYSTEM_TIME must not be part of foreign keys
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 174 at RAISE
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 171 at RAISE
DROP TABLE no_unique, no_unique_ref;
/* DROP protection */
CREATE TYPE integerrange AS RANGE (SUBTYPE = integer);
Expand Down Expand Up @@ -1041,5 +1041,46 @@ DROP TABLE rename_test_ref;
/* system_versioning */
-- Nothing to do here
DROP TABLE rename_test;
/* Health checks */
CREATE UNLOGGED TABLE log (id bigint, s date, e date);
SELECT periods.add_period('log', 'p', 's', 'e'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_period(regclass,name,name,name,regtype) line 72 at RAISE
SELECT periods.add_system_time_period('log'); -- fails
ERROR: table "log" must be persistent
CONTEXT: PL/pgSQL function periods.add_system_time_period(regclass,name,name) line 77 at RAISE
ALTER TABLE log SET LOGGED;
SELECT periods.add_period('log', 'p', 's', 'e'); -- passes
add_period
------------
t
(1 row)

SELECT periods.add_system_time_period('log'); -- passes
add_system_time_period
------------------------
t
(1 row)

ALTER TABLE log SET UNLOGGED; -- fails
ERROR: table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 13 at RAISE
SELECT periods.add_system_versioning('log');
NOTICE: history table "log_history" created for "log", be sure to index it properly
add_system_versioning
-----------------------

(1 row)

ALTER TABLE log_history SET UNLOGGED; -- fails
ERROR: history table "log" must remain persistent because it has periods
CONTEXT: PL/pgSQL function periods.health_checks() line 24 at RAISE
SELECT periods.drop_system_versioning('log', purge => true);
drop_system_versioning
------------------------
t
(1 row)

DROP TABLE log;
/* Clean up */
DROP EXTENSION periods;
37 changes: 37 additions & 0 deletions expected/periods_3.out
Original file line number Diff line number Diff line change
Expand Up @@ -1003,5 +1003,42 @@ DROP TABLE rename_test_ref;
/* system_versioning */
-- Nothing to do here
DROP TABLE rename_test;
/* Health checks */
CREATE UNLOGGED TABLE log (id bigint, s date, e date);
SELECT periods.add_period('log', 'p', 's', 'e'); -- fails
ERROR: table "log" must be persistent
SELECT periods.add_system_time_period('log'); -- fails
ERROR: table "log" must be persistent
ALTER TABLE log SET LOGGED;
SELECT periods.add_period('log', 'p', 's', 'e'); -- passes
add_period
------------
t
(1 row)

SELECT periods.add_system_time_period('log'); -- passes
add_system_time_period
------------------------
t
(1 row)

ALTER TABLE log SET UNLOGGED; -- fails
ERROR: table "log" must remain persistent because it has periods
SELECT periods.add_system_versioning('log');
NOTICE: history table "log_history" created for "log", be sure to index it properly
add_system_versioning
-----------------------

(1 row)

ALTER TABLE log_history SET UNLOGGED; -- fails
ERROR: history table "log" must remain persistent because it has periods
SELECT periods.drop_system_versioning('log', purge => true);
drop_system_versioning
------------------------
t
(1 row)

DROP TABLE log;
/* Clean up */
DROP EXTENSION periods;
51 changes: 39 additions & 12 deletions periods--0.04.sql
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,8 @@ BEGIN
END IF;

IF persistence <> 'p' THEN
/*
* We could probably accept unlogged tables but what's the point?
TODO: in the health check, make sure this remains true
*/
RAISE EXCEPTION 'table must be persistent';
/* We could probably accept unlogged tables but what's the point? */
RAISE EXCEPTION 'table "%" must be persistent', table_name;
END IF;

/*
Expand Down Expand Up @@ -654,11 +651,8 @@ BEGIN
END IF;

IF persistence <> 'p' THEN
/*
* We could probably accept unlogged tables but what's the point?
TODO: in the health check, make sure this remains true
*/
RAISE EXCEPTION 'table must be persistent';
/* We could probably accept unlogged tables but what's the point? */
RAISE EXCEPTION 'table "%" must be persistent', table_class;
END IF;

/*
Expand Down Expand Up @@ -2178,9 +2172,8 @@ BEGIN
/*
* We could probably accept unlogged tables if the history table is
* also unlogged, but what's the point?
TODO: in the health check, make sure this remains true
*/
RAISE EXCEPTION 'table must be persistent';
RAISE EXCEPTION 'table "%" must be persistent', table_class;
END IF;

/* We need a SYSTEM_TIME period. SQL:2016 11.29 SR 4 */
Expand Down Expand Up @@ -2909,3 +2902,37 @@ $function$;

CREATE EVENT TRIGGER periods_rename_following ON ddl_command_end EXECUTE PROCEDURE periods.rename_following();

CREATE FUNCTION periods.health_checks()
RETURNS event_trigger
LANGUAGE plpgsql
AS
$function$
#variable_conflict use_variable
DECLARE
r record;
BEGIN
/* Make sure that all of our tables are still persistent */
FOR r IN
SELECT p.table_name
FROM periods.periods AS p
JOIN pg_catalog.pg_class AS c ON c.oid = p.table_name
WHERE c.relpersistence <> 'p'
LOOP
RAISE EXCEPTION 'table "%" must remain persistent because it has periods',
r.table_name;
END LOOP;

/* And the history tables, too */
FOR r IN
SELECT sv.table_name
FROM periods.system_versioning AS sv
JOIN pg_catalog.pg_class AS c ON c.oid = sv.history_table_name
WHERE c.relpersistence <> 'p'
LOOP
RAISE EXCEPTION 'history table "%" must remain persistent because it has periods',
r.table_name;
END LOOP;
END;
$function$;

CREATE EVENT TRIGGER periods_health_checks ON ddl_command_end EXECUTE PROCEDURE periods.health_checks();
14 changes: 14 additions & 0 deletions sql/periods.sql
Original file line number Diff line number Diff line change
Expand Up @@ -391,5 +391,19 @@ DROP TABLE rename_test_ref;
DROP TABLE rename_test;


/* Health checks */
CREATE UNLOGGED TABLE log (id bigint, s date, e date);
SELECT periods.add_period('log', 'p', 's', 'e'); -- fails
SELECT periods.add_system_time_period('log'); -- fails
ALTER TABLE log SET LOGGED;
SELECT periods.add_period('log', 'p', 's', 'e'); -- passes
SELECT periods.add_system_time_period('log'); -- passes
ALTER TABLE log SET UNLOGGED; -- fails
SELECT periods.add_system_versioning('log');
ALTER TABLE log_history SET UNLOGGED; -- fails
SELECT periods.drop_system_versioning('log', purge => true);
DROP TABLE log;


/* Clean up */
DROP EXTENSION periods;

0 comments on commit 6b62f82

Please sign in to comment.