-- Regression test for the receive function tdigest_recv(), which parses the -- binary representation of a t-digest. -- -- The input is user supplied, so it has to be validated just like the text -- input. The queries exercise all the error checks in the receive function, -- one by one. -- -- Test through a binary COPY, which goes through the receive function. We -- build the input with the send functions of the individual fields. \set VERBOSITY terse CREATE TABLE tdigest_dst (s tdigest); -- a valid value, to make sure the checks don't reject correct input COPY (SELECT int4send(1) -- flags || int8send(3::bigint) -- count || int4send(10) -- compression || int4send(2) -- ncentroids || float8send(1) || int8send(1::bigint) || float8send(2) || int8send(2::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); -- -- sanity checks on the header -- -- unknown flags COPY (SELECT int4send(2) || int8send(1::bigint) || int4send(10) || int4send(1) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: unsupported t-digest on-disk format -- compression out of the supported range COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(9) || int4send(1) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: compression for t-digest must be in [10, 10000] COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10001) || int4send(1) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: compression for t-digest must be in [10, 10000] -- non-positive total count COPY (SELECT int4send(1) || int8send(0::bigint) || int4send(10) || int4send(1) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: count value for the t-digest must be positive -- non-positive number of centroids COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(0)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: number of centroids for the t-digest must be positive -- more centroids than fit into the buffer (10 * compression) COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(101)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: number of centroids for the t-digest exceeds buffer size -- -- sanity checks on the centroids -- -- centroid mean that is not a valid number COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(1) || float8send('NaN') || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: mean value for all centroids in a t-digest must be valid COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(1) || float8send('Infinity') || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: mean value for all centroids in a t-digest must be valid -- non-positive centroid count COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(1) || float8send(1) || int8send(0::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: count value for all centroids in a t-digest must be positive -- centroid count exceeding the total count COPY (SELECT int4send(1) || int8send(1::bigint) || int4send(10) || int4send(1) || float8send(1) || int8send(2::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: count value of a centroid exceeds total count -- centroids not sorted by mean COPY (SELECT int4send(1) || int8send(3::bigint) || int4send(10) || int4send(2) || float8send(2) || int8send(2::bigint) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); -- centroids not sorted by mean, in the old on-disk format storing sums -- instead of means (the sums are sorted, but the means are not) COPY (SELECT int4send(0) || int8send(3::bigint) || int4send(10) || int4send(2) || float8send(4) || int8send(1::bigint) || float8send(6) || int8send(2::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); -- centroid counts overflowing the total count COPY (SELECT int4send(1) || int8send(9223372036854775807::bigint) || int4send(10) || int4send(2) || float8send(1) || int8send(9223372036854775807::bigint) || float8send(2) || int8send(9223372036854775807::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: tdigest count overflow -- -- sanity checks on the value as a whole -- -- centroid counts not adding up to the total count COPY (SELECT int4send(1) || int8send(3::bigint) || int4send(10) || int4send(1) || float8send(1) || int8send(1::bigint)) TO '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); COPY tdigest_dst FROM '/tmp/tdigest_recv_checks.bin' WITH (FORMAT binary); ERROR: total count does not match the data (1 != 3) -- only the valid value should have made it into the table SELECT s FROM tdigest_dst; s ---------------------------------------------------------- flags 1 count 3 compression 10 centroids 2 (1, 1) (2, 2) flags 1 count 3 compression 10 centroids 2 (2, 2) (1, 1) flags 1 count 3 compression 10 centroids 2 (4, 1) (3, 2) (3 rows) DROP TABLE tdigest_dst;