Skip to content

Commit 6053417

Browse files
Fix compression policy error message.
Co-authored-by: Fabrízio de Royes Mello <[email protected]>
1 parent f59b176 commit 6053417

File tree

5 files changed

+273
-4
lines changed

5 files changed

+273
-4
lines changed

.unreleased/pr_8008

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #8008 Fix compression policy error message that shows number of successes

sql/policy_internal.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ AS $$
4848
DECLARE
4949
htoid REGCLASS;
5050
chunk_rec RECORD;
51-
numchunks INTEGER := 1;
51+
numchunks_compressed INTEGER := 0;
5252
_message text;
5353
_detail text;
5454
_sqlstate text;
@@ -106,7 +106,7 @@ BEGIN
106106
BEGIN
107107
IF chunk_rec.status = bit_compressed OR recompress_enabled IS TRUE THEN
108108
PERFORM @[email protected]_chunk(chunk_rec.oid, hypercore_use_access_method => useam);
109-
numchunks := numchunks + 1;
109+
numchunks_compressed := numchunks_compressed + 1;
110110
END IF;
111111
EXCEPTION WHEN OTHERS THEN
112112
GET STACKED DIAGNOSTICS
@@ -127,14 +127,14 @@ BEGIN
127127
IF verbose_log THEN
128128
RAISE LOG 'job % completed processing chunk %.%', job_id, chunk_rec.schema_name, chunk_rec.table_name;
129129
END IF;
130-
IF maxchunks > 0 AND numchunks >= maxchunks THEN
130+
IF maxchunks > 0 AND numchunks_compressed >= maxchunks THEN
131131
EXIT;
132132
END IF;
133133
END LOOP;
134134

135135
IF chunks_failure > 0 THEN
136136
RAISE EXCEPTION 'compression policy failure'
137-
USING DETAIL = format('Failed to compress %L chunks. Successfully compressed %L chunks.', chunks_failure, numchunks - chunks_failure);
137+
USING DETAIL = format('Failed to compress %L chunks. Successfully compressed %L chunks.', chunks_failure, numchunks_compressed);
138138
END IF;
139139
END;
140140
$$ LANGUAGE PLPGSQL;

sql/updates/reverse-dev.sql

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,108 @@ CREATE FUNCTION @[email protected]_continuous_aggregate_policy(
3131
RETURNS INTEGER
3232
AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
3333
LANGUAGE C VOLATILE;
34+
35+
CREATE OR REPLACE PROCEDURE
36+
_timescaledb_functions.policy_compression_execute(
37+
job_id INTEGER,
38+
htid INTEGER,
39+
lag ANYELEMENT,
40+
maxchunks INTEGER,
41+
verbose_log BOOLEAN,
42+
recompress_enabled BOOLEAN,
43+
use_creation_time BOOLEAN,
44+
useam BOOLEAN = NULL)
45+
AS $$
46+
DECLARE
47+
htoid REGCLASS;
48+
chunk_rec RECORD;
49+
numchunks INTEGER := 1;
50+
_message text;
51+
_detail text;
52+
_sqlstate text;
53+
-- fully compressed chunk status
54+
status_fully_compressed int := 1;
55+
-- chunk status bits:
56+
bit_compressed int := 1;
57+
bit_compressed_unordered int := 2;
58+
bit_frozen int := 4;
59+
bit_compressed_partial int := 8;
60+
creation_lag INTERVAL := NULL;
61+
chunks_failure INTEGER := 0;
62+
BEGIN
63+
64+
-- procedures with SET clause cannot execute transaction
65+
-- control so we adjust search_path in procedure body
66+
SET LOCAL search_path TO pg_catalog, pg_temp;
67+
68+
SELECT format('%I.%I', schema_name, table_name) INTO htoid
69+
FROM _timescaledb_catalog.hypertable
70+
WHERE id = htid;
71+
72+
-- for the integer cases, we have to compute the lag w.r.t
73+
-- the integer_now function and then pass on to show_chunks
74+
IF pg_typeof(lag) IN ('BIGINT'::regtype, 'INTEGER'::regtype, 'SMALLINT'::regtype) THEN
75+
-- cannot have use_creation_time set with this
76+
IF use_creation_time IS TRUE THEN
77+
RAISE EXCEPTION 'job % cannot use creation time with integer_now function', job_id;
78+
END IF;
79+
lag := _timescaledb_functions.subtract_integer_from_now(htoid, lag::BIGINT);
80+
END IF;
81+
82+
-- if use_creation_time has been specified then the lag needs to be used with the
83+
-- "compress_created_before" argument. Otherwise the usual "older_than" argument
84+
-- is good enough
85+
IF use_creation_time IS TRUE THEN
86+
creation_lag := lag;
87+
lag := NULL;
88+
END IF;
89+
90+
FOR chunk_rec IN
91+
SELECT
92+
show.oid, ch.schema_name, ch.table_name, ch.status
93+
FROM
94+
@[email protected]_chunks(htoid, older_than => lag, created_before => creation_lag) AS show(oid)
95+
INNER JOIN pg_class pgc ON pgc.oid = show.oid
96+
INNER JOIN pg_namespace pgns ON pgc.relnamespace = pgns.oid
97+
INNER JOIN _timescaledb_catalog.chunk ch ON ch.table_name = pgc.relname AND ch.schema_name = pgns.nspname AND ch.hypertable_id = htid
98+
WHERE NOT ch.dropped
99+
AND NOT ch.osm_chunk
100+
-- Checking for chunks which are not fully compressed and not frozen
101+
AND ch.status != status_fully_compressed
102+
AND ch.status & bit_frozen = 0
103+
LOOP
104+
BEGIN
105+
IF chunk_rec.status = bit_compressed OR recompress_enabled IS TRUE THEN
106+
PERFORM @[email protected]_chunk(chunk_rec.oid, hypercore_use_access_method => useam);
107+
numchunks := numchunks + 1;
108+
END IF;
109+
EXCEPTION WHEN OTHERS THEN
110+
GET STACKED DIAGNOSTICS
111+
_message = MESSAGE_TEXT,
112+
_detail = PG_EXCEPTION_DETAIL,
113+
_sqlstate = RETURNED_SQLSTATE;
114+
RAISE WARNING 'compressing chunk "%" failed when compression policy is executed', chunk_rec.oid::regclass::text
115+
USING DETAIL = format('Message: (%s), Detail: (%s).', _message, _detail),
116+
ERRCODE = _sqlstate;
117+
chunks_failure := chunks_failure + 1;
118+
END;
119+
COMMIT;
120+
-- SET LOCAL is only active until end of transaction.
121+
-- While we could use SET at the start of the function we do not
122+
-- want to bleed out search_path to caller, so we do SET LOCAL
123+
-- again after COMMIT
124+
SET LOCAL search_path TO pg_catalog, pg_temp;
125+
IF verbose_log THEN
126+
RAISE LOG 'job % completed processing chunk %.%', job_id, chunk_rec.schema_name, chunk_rec.table_name;
127+
END IF;
128+
IF maxchunks > 0 AND numchunks >= maxchunks THEN
129+
EXIT;
130+
END IF;
131+
END LOOP;
132+
133+
IF chunks_failure > 0 THEN
134+
RAISE EXCEPTION 'compression policy failure'
135+
USING DETAIL = format('Failed to compress %L chunks. Successfully compressed %L chunks.', chunks_failure, numchunks - chunks_failure);
136+
END IF;
137+
END;
138+
$$ LANGUAGE PLPGSQL;

tsl/test/expected/compression_bgw.out

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,99 @@ LIMIT 1;
771771
69 | 1
772772
(1 row)
773773

774+
--TEST 8
775+
--compression policy errors
776+
CREATE TABLE test_compression_policy_errors(time TIMESTAMPTZ, val SMALLINT);
777+
SELECT create_hypertable('test_compression_policy_errors', 'time', chunk_time_interval => '1 day'::interval);
778+
NOTICE: adding not-null constraint to column "time"
779+
create_hypertable
780+
----------------------------------------------
781+
(20,public,test_compression_policy_errors,t)
782+
(1 row)
783+
784+
ALTER TABLE test_compression_policy_errors SET (timescaledb.compress, timescaledb.compress_segmentby = 'val', timescaledb.compress_orderby = 'time');
785+
INSERT INTO test_compression_policy_errors SELECT time, (random()*10)::smallint
786+
FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '10 min') AS time;
787+
SELECT
788+
add_compression_policy(
789+
'test_compression_policy_errors',
790+
compress_after=> '1 day'::interval,
791+
initial_start => now() - interval '1 day'
792+
) as compressjob_id \gset
793+
SELECT config AS compressjob_config FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id \gset
794+
SELECT FROM alter_job(:compressjob_id, config => jsonb_set(:'compressjob_config'::jsonb, '{recompress}', 'true'));
795+
--
796+
(1 row)
797+
798+
-- 31 uncompressed chunks (0 - uncompressed, 1 - compressed)
799+
SELECT c.status, count(*)
800+
FROM _timescaledb_catalog.chunk c
801+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
802+
WHERE h.table_name = 'test_compression_policy_errors'
803+
GROUP BY c.status
804+
ORDER BY 2 DESC;
805+
status | count
806+
--------+-------
807+
0 | 31
808+
(1 row)
809+
810+
\c :TEST_DBNAME :ROLE_SUPERUSER
811+
-- Let's mess with the chunk status to for an error when executing the job
812+
WITH chunks AS (
813+
SELECT c.id, c.status
814+
FROM _timescaledb_catalog.chunk c
815+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
816+
WHERE h.table_name = 'test_compression_policy_errors'
817+
ORDER BY c.id LIMIT 20
818+
)
819+
UPDATE _timescaledb_catalog.chunk
820+
SET status = 3
821+
FROM chunks
822+
WHERE chunk.id = chunks.id
823+
AND chunk.status = 0;
824+
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
825+
-- After the mess 20 = status 3 and 11 = status 0
826+
SELECT c.status, count(*)
827+
FROM _timescaledb_catalog.chunk c
828+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
829+
WHERE h.table_name = 'test_compression_policy_errors'
830+
GROUP BY c.status
831+
ORDER BY 2 DESC;
832+
status | count
833+
--------+-------
834+
3 | 20
835+
0 | 11
836+
(2 rows)
837+
838+
\set ON_ERROR_STOP 0
839+
SET client_min_messages TO ERROR;
840+
\set VERBOSITY default
841+
-- This should fail with
842+
-- 20 chunks failed to compress and 11 chunks compressed successfully
843+
CALL run_job(:compressjob_id);
844+
ERROR: compression policy failure
845+
DETAIL: Failed to compress '20' chunks. Successfully compressed '11' chunks.
846+
CONTEXT: PL/pgSQL function _timescaledb_functions.policy_compression_execute(integer,integer,anyelement,integer,boolean,boolean,boolean,boolean) line 90 at RAISE
847+
SQL statement "CALL _timescaledb_functions.policy_compression_execute(
848+
job_id, htid, lag_value::INTERVAL,
849+
maxchunks, verbose_log, recompress_enabled, use_creation_time, hypercore_use_access_method
850+
)"
851+
PL/pgSQL function _timescaledb_functions.policy_compression(integer,jsonb) line 63 at CALL
852+
\set VERBOSITY terse
853+
\set ON_ERROR_STOP 1
854+
-- 31 uncompressed chunks (0 - uncompressed, 1 - compressed)
855+
SELECT c.status, count(*)
856+
FROM _timescaledb_catalog.chunk c
857+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
858+
WHERE h.table_name = 'test_compression_policy_errors'
859+
GROUP BY c.status
860+
ORDER BY 2 DESC;
861+
status | count
862+
--------+-------
863+
3 | 20
864+
1 | 11
865+
(2 rows)
866+
774867
-- Teardown test
775868
\c :TEST_DBNAME :ROLE_SUPERUSER
776869
REVOKE CREATE ON SCHEMA public FROM NOLOGIN_ROLE;

tsl/test/sql/compression_bgw.sql

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,76 @@ WHERE h.table_name = 'test_table_frozen'
279279
ORDER BY c.id
280280
LIMIT 1;
281281

282+
--TEST 8
283+
--compression policy errors
284+
CREATE TABLE test_compression_policy_errors(time TIMESTAMPTZ, val SMALLINT);
285+
SELECT create_hypertable('test_compression_policy_errors', 'time', chunk_time_interval => '1 day'::interval);
286+
ALTER TABLE test_compression_policy_errors SET (timescaledb.compress, timescaledb.compress_segmentby = 'val', timescaledb.compress_orderby = 'time');
287+
288+
INSERT INTO test_compression_policy_errors SELECT time, (random()*10)::smallint
289+
FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '10 min') AS time;
290+
291+
SELECT
292+
add_compression_policy(
293+
'test_compression_policy_errors',
294+
compress_after=> '1 day'::interval,
295+
initial_start => now() - interval '1 day'
296+
) as compressjob_id \gset
297+
298+
SELECT config AS compressjob_config FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id \gset
299+
SELECT FROM alter_job(:compressjob_id, config => jsonb_set(:'compressjob_config'::jsonb, '{recompress}', 'true'));
300+
301+
-- 31 uncompressed chunks (0 - uncompressed, 1 - compressed)
302+
SELECT c.status, count(*)
303+
FROM _timescaledb_catalog.chunk c
304+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
305+
WHERE h.table_name = 'test_compression_policy_errors'
306+
GROUP BY c.status
307+
ORDER BY 2 DESC;
308+
309+
\c :TEST_DBNAME :ROLE_SUPERUSER
310+
311+
-- Let's mess with the chunk status to for an error when executing the job
312+
WITH chunks AS (
313+
SELECT c.id, c.status
314+
FROM _timescaledb_catalog.chunk c
315+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
316+
WHERE h.table_name = 'test_compression_policy_errors'
317+
ORDER BY c.id LIMIT 20
318+
)
319+
UPDATE _timescaledb_catalog.chunk
320+
SET status = 3
321+
FROM chunks
322+
WHERE chunk.id = chunks.id
323+
AND chunk.status = 0;
324+
325+
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
326+
327+
-- After the mess 20 = status 3 and 11 = status 0
328+
SELECT c.status, count(*)
329+
FROM _timescaledb_catalog.chunk c
330+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
331+
WHERE h.table_name = 'test_compression_policy_errors'
332+
GROUP BY c.status
333+
ORDER BY 2 DESC;
334+
335+
\set ON_ERROR_STOP 0
336+
SET client_min_messages TO ERROR;
337+
\set VERBOSITY default
338+
-- This should fail with
339+
-- 20 chunks failed to compress and 11 chunks compressed successfully
340+
CALL run_job(:compressjob_id);
341+
\set VERBOSITY terse
342+
\set ON_ERROR_STOP 1
343+
344+
-- 31 uncompressed chunks (0 - uncompressed, 1 - compressed)
345+
SELECT c.status, count(*)
346+
FROM _timescaledb_catalog.chunk c
347+
INNER JOIN _timescaledb_catalog.hypertable h on (h.id = c.hypertable_id)
348+
WHERE h.table_name = 'test_compression_policy_errors'
349+
GROUP BY c.status
350+
ORDER BY 2 DESC;
351+
282352
-- Teardown test
283353
\c :TEST_DBNAME :ROLE_SUPERUSER
284354
REVOKE CREATE ON SCHEMA public FROM NOLOGIN_ROLE;

0 commit comments

Comments
 (0)