diff --git a/sql/functions/run_maintenance.sql b/sql/functions/run_maintenance.sql index 032cfbb..1410c83 100644 --- a/sql/functions/run_maintenance.sql +++ b/sql/functions/run_maintenance.sql @@ -111,6 +111,7 @@ v_tables_list_sql := 'SELECT parent_table , ignore_default_data , datetime_string , maintenance_order + , date_trunc_interval FROM @extschema@.part_config WHERE undo_in_progress = false'; @@ -207,8 +208,14 @@ LOOP SELECT child_start_time INTO v_last_partition_timestamp FROM @extschema@.show_partition_info(v_parent_schema||'.'||v_last_partition, v_row.partition_interval, v_row.parent_table); + -- Do not create child tables if they would be dropped by retention anyway. Edge case where maintenance was missed for + -- an extended period of time IF v_row.retention IS NOT NULL THEN v_last_partition_timestamp := greatest(v_last_partition_timestamp, CURRENT_TIMESTAMP - v_row.retention::interval); + -- Need to properly truncate the interval and account for custom date truncation + SELECT base_timestamp + INTO v_last_partition_timestamp + FROM @extschema@.calculate_time_partition_info(v_row.partition_interval::interval, v_last_partition_timestamp, v_row.date_trunc_interval); END IF; -- Must be reset to null otherwise if the next partition set in the loop is empty, the previous partition set's value could be used @@ -260,8 +267,8 @@ LOOP v_drop_count := v_drop_count + @extschema@.drop_partition_time(v_row.parent_table); END IF; - UPDATE @extschema@.part_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table; -- Nothing else to do + UPDATE @extschema@.part_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table; CONTINUE; END IF; RAISE DEBUG 'run_maint: v_child_timestamp: %, v_current_partition_timestamp: %, v_max_time_default: %', v_child_timestamp, v_current_partition_timestamp, v_max_time_default; @@ -359,7 +366,14 @@ LOOP END IF; RAISE DEBUG 'run_maint: v_max_id: %, v_current_partition_id: %, v_max_id_default: %', v_max_id, v_current_partition_id, v_max_id_default; IF v_current_partition_id IS NULL AND v_max_id_default IS NULL THEN - -- Partition set is completely empty. Nothing to do + -- Partition set is completely empty. + + -- Still need to run retention if needed. Note similar call below for non-empty sets. Keep in sync. + IF v_row.retention IS NOT NULL THEN + v_drop_count := v_drop_count + @extschema@.drop_partition_id(v_row.parent_table); + END IF; + + -- Nothing else to do UPDATE @extschema@.part_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table; CONTINUE; END IF; @@ -402,7 +416,7 @@ LOOP v_premade_count := ((v_next_partition_id - v_current_partition_id) / v_row.partition_interval::bigint); END LOOP; - -- Run retention if needed + -- Run retention if needed. Note similar call above when partition set is empty. Keep in sync. IF v_row.retention IS NOT NULL THEN v_drop_count := v_drop_count + @extschema@.drop_partition_id(v_row.parent_table); END IF; diff --git a/test/test-time-monthly.sql b/test/test-time-monthly.sql new file mode 100644 index 0000000..29703d4 --- /dev/null +++ b/test/test-time-monthly.sql @@ -0,0 +1,307 @@ +-- ########## TIME MONTHLY ########## +-- Other tests: + -- Ensure partitions that would be dropped by retention are not created during maintenance + +\set ON_ERROR_ROLLBACK 1 +\set ON_ERROR_STOP true + +BEGIN; +SELECT set_config('search_path','partman, public',false); + +SELECT plan(122); +CREATE SCHEMA partman_test; +CREATE SCHEMA partman_retention_test; + +CREATE TABLE partman_test.time_taptest_table + (col1 int + , col2 text + , col3 timestamptz DEFAULT now() NOT NULL) + PARTITION BY RANGE (col3); +CREATE TABLE partman_test.time_taptest_table_template (LIKE partman_test.time_taptest_table INCLUDING ALL); +ALTER TABLE partman_test.time_taptest_table_template ADD PRIMARY KEY (col1); +CREATE TABLE partman_test.undo_taptest (LIKE partman_test.time_taptest_table INCLUDING ALL); + +CREATE INDEX ON partman_test.time_taptest_table (col3); + +SELECT create_parent('partman_test.time_taptest_table', 'col3', '1 month', p_template_table => 'partman_test.time_taptest_table_template', p_start_partition := date_trunc('month', (CURRENT_TIMESTAMP-'12 months'::interval))::text ); + +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(1,10), CURRENT_TIMESTAMP); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(1,10), CURRENT_TIMESTAMP-'12 month'::interval); + +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')||' exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'23 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'12 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'24 month'::interval, 'YYYYMMDD')||' exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'13 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'13 month'::interval, 'YYYYMMDD')||' does not exist'); + +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')); + +-- Tests to ensure that old tables are not recreated if they would be included in the retention period + +UPDATE part_config SET retention = '5 months', infinite_time_partitions = true, retention_keep_table = false WHERE parent_table = 'partman_test.time_taptest_table'; + +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD') ); +SELECT lives_ok('DROP TABLE partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), 'Drop table time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD') ); + +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'12 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'12 month'::interval, 'YYYYMMDD')||' still exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')||' does not exist'); + +SELECT run_maintenance(); + +-- Tables older than months should not have been created, 12 month old table should have been dropped and default premade tables should have been remade +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'12 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'12 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'11 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'10 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'9 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'8 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'7 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'6 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'5 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')||' exists'); +-- For some reason, edge case of re-creating child tables goes one beyond premake. Not too worried about why or how in this situation +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')||' exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD')||' does not exist'); + +-- Reinsert original data +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(1,10), CURRENT_TIMESTAMP); + +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), + ARRAY[10], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')); + +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(11,20), CURRENT_TIMESTAMP + '1 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(21,25), CURRENT_TIMESTAMP + '2 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(26,30), CURRENT_TIMESTAMP + '3 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(31,37), CURRENT_TIMESTAMP + '4 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(40,49), CURRENT_TIMESTAMP - '1 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(50,70), CURRENT_TIMESTAMP - '2 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(71,85), CURRENT_TIMESTAMP - '3 month'::interval); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(86,100), CURRENT_TIMESTAMP - '4 month'::interval); + +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), + ARRAY[10], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), + ARRAY[5], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), + ARRAY[5], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), + ARRAY[7], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), + ARRAY[10], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), + ARRAY[21], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + ARRAY[15], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), + ARRAY[15], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')); + +UPDATE part_config SET premake = 5 WHERE parent_table = 'partman_test.time_taptest_table'; +SELECT run_maintenance(); + +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(101,122), CURRENT_TIMESTAMP + '5 month'::interval); + +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD')||' exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD')); + +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), + ARRAY[22], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')); + +UPDATE part_config SET premake = 6 WHERE parent_table = 'partman_test.time_taptest_table'; +SELECT run_maintenance(); +INSERT INTO partman_test.time_taptest_table (col1, col3) VALUES (generate_series(123,150), CURRENT_TIMESTAMP + '6 month'::interval); + +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table', ARRAY[148], 'Check count from parent table'); +SELECT results_eq('SELECT count(*)::int FROM partman_test.time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD'), + ARRAY[28], 'Check count from time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD')); + +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD')||' exists'); +SELECT has_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD')||' exists'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'12 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'12 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD')); +SELECT col_is_pk('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD'), ARRAY['col1'], + 'Check for primary key in time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD')); + + + + +SELECT drop_partition_time('partman_test.time_taptest_table', '3 month', p_keep_table := false); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'4 month'::interval, 'YYYYMMDD')||' does not exist'); + +UPDATE part_config SET retention = '2 month'::interval WHERE parent_table = 'partman_test.time_taptest_table'; +SELECT drop_partition_time('partman_test.time_taptest_table', p_retention_schema := 'partman_retention_test'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT has_table('partman_retention_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'3 month'::interval, 'YYYYMMDD')||' got moved to new schema'); + +SELECT undo_partition('partman_test.time_taptest_table', p_loop_count => 20, p_target_table := 'partman_test.undo_taptest', p_keep_table := false); +SELECT results_eq('SELECT count(*)::int FROM partman_test.undo_taptest', ARRAY[118], 'Check count from target table after undo'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP), 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'1 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)-'2 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'1 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'2 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'3 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'4 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'5 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'6 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'7 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'8 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'9 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'10 month'::interval, 'YYYYMMDD')||' does not exist'); +SELECT hasnt_table('partman_test', 'time_taptest_table_p'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD'), + 'Check time_taptest_table_'||to_char(date_trunc('month', CURRENT_TIMESTAMP)+'11 month'::interval, 'YYYYMMDD')||' does not exist'); + + +SELECT hasnt_table('partman_test', 'time_taptest_table_template', 'Check that template table was dropped'); + +SELECT * FROM finish(); +ROLLBACK; diff --git a/updates/pg_partman--5.1.0--5.2.0.sql b/updates/pg_partman--5.1.0--5.2.0.sql index 7654c77..b4605ec 100644 --- a/updates/pg_partman--5.1.0--5.2.0.sql +++ b/updates/pg_partman--5.1.0--5.2.0.sql @@ -1178,6 +1178,7 @@ v_tables_list_sql := 'SELECT parent_table , ignore_default_data , datetime_string , maintenance_order + , date_trunc_interval FROM @extschema@.part_config WHERE undo_in_progress = false'; @@ -1274,8 +1275,14 @@ LOOP SELECT child_start_time INTO v_last_partition_timestamp FROM @extschema@.show_partition_info(v_parent_schema||'.'||v_last_partition, v_row.partition_interval, v_row.parent_table); + -- Do not create child tables if they would be dropped by retention anyway. Edge case where maintenance was missed for + -- an extended period of time IF v_row.retention IS NOT NULL THEN v_last_partition_timestamp := greatest(v_last_partition_timestamp, CURRENT_TIMESTAMP - v_row.retention::interval); + -- Need to properly truncate the interval and account for custom date truncation + SELECT base_timestamp + INTO v_last_partition_timestamp + FROM @extschema@.calculate_time_partition_info(v_row.partition_interval::interval, v_last_partition_timestamp, v_row.date_trunc_interval); END IF; -- Must be reset to null otherwise if the next partition set in the loop is empty, the previous partition set's value could be used @@ -1321,7 +1328,13 @@ LOOP RAISE DEBUG 'run_maint: v_current_partition_timestamp: %, v_max_time_default: %', v_current_partition_timestamp, v_max_time_default; IF v_current_partition_timestamp IS NULL AND v_max_time_default IS NULL THEN -- Partition set is completely empty and infinite time partitions not set - -- Nothing to do + + -- Still need to run retention if needed. Note similar call below for non-empty sets. Keep in sync. + IF v_row.retention IS NOT NULL THEN + v_drop_count := v_drop_count + @extschema@.drop_partition_time(v_row.parent_table); + END IF; + + -- Nothing else to do UPDATE @extschema@.part_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table; CONTINUE; END IF; @@ -1381,7 +1394,7 @@ LOOP v_premade_count = round(EXTRACT('epoch' FROM age(v_next_partition_timestamp, v_current_partition_timestamp)) / EXTRACT('epoch' FROM v_row.partition_interval::interval)); END LOOP; - -- Run retention if needed + -- Run retention if needed. Note similar call above when partition set is empty. Keep in sync. IF v_row.retention IS NOT NULL THEN v_drop_count := v_drop_count + @extschema@.drop_partition_time(v_row.parent_table); END IF; @@ -1420,7 +1433,14 @@ LOOP END IF; RAISE DEBUG 'run_maint: v_max_id: %, v_current_partition_id: %, v_max_id_default: %', v_max_id, v_current_partition_id, v_max_id_default; IF v_current_partition_id IS NULL AND v_max_id_default IS NULL THEN - -- Partition set is completely empty. Nothing to do + -- Partition set is completely empty. + + -- Still need to run retention if needed. Note similar call below for non-empty sets. Keep in sync. + IF v_row.retention IS NOT NULL THEN + v_drop_count := v_drop_count + @extschema@.drop_partition_id(v_row.parent_table); + END IF; + + -- Nothing else to do UPDATE @extschema@.part_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table; CONTINUE; END IF; @@ -1463,7 +1483,7 @@ LOOP v_premade_count := ((v_next_partition_id - v_current_partition_id) / v_row.partition_interval::bigint); END LOOP; - -- Run retention if needed + -- Run retention if needed. Note similar call above when partition set is empty. Keep in sync. IF v_row.retention IS NOT NULL THEN v_drop_count := v_drop_count + @extschema@.drop_partition_id(v_row.parent_table); END IF;