Add more tests for compression

Unit tests for different data sequences, and SQL test for float4.
This commit is contained in:
Alexander Kuzmenkov 2023-03-09 14:34:28 +04:00
parent f5db023152
commit e92d5ba748
7 changed files with 631 additions and 119 deletions

View File

@ -155,8 +155,6 @@ deltadelta_compressor_append_null_value(Compressor *compressor)
delta_delta_compressor_append_null(extended->internal);
}
static void *delta_delta_compressor_finish(DeltaDeltaCompressor *compressor);
static void *
deltadelta_compressor_finish_and_reset(Compressor *compressor)
{
@ -331,7 +329,7 @@ delta_delta_from_parts(uint64 last_value, uint64 last_delta, Simple8bRleSerializ
return compressed;
}
static void *
void *
delta_delta_compressor_finish(DeltaDeltaCompressor *compressor)
{
Simple8bRleSerialized *deltas = simple8brle_compressor_finish(&compressor->delta_delta);

View File

@ -32,6 +32,7 @@ extern Compressor *delta_delta_compressor_for_type(Oid element_type);
extern DeltaDeltaCompressor *delta_delta_compressor_alloc(void);
extern void delta_delta_compressor_append_null(DeltaDeltaCompressor *compressor);
extern void delta_delta_compressor_append_value(DeltaDeltaCompressor *compressor, int64 next_val);
extern void *delta_delta_compressor_finish(DeltaDeltaCompressor *compressor);
extern DecompressionIterator *
delta_delta_decompression_iterator_from_datum_forward(Datum deltadelta_compressed,

View File

@ -262,13 +262,13 @@ gorilla_compressor_alloc(void)
return compressor;
}
/* This function is used for testing only. */
Datum
tsl_gorilla_compressor_append(PG_FUNCTION_ARGS)
{
MemoryContext old_context;
MemoryContext agg_context;
GorillaCompressor *compressor =
(GorillaCompressor *) (PG_ARGISNULL(0) ? NULL : PG_GETARG_POINTER(0));
Compressor *compressor = (Compressor *) (PG_ARGISNULL(0) ? NULL : PG_GETARG_POINTER(0));
if (!AggCheckCallContext(fcinfo, &agg_context))
{
@ -279,20 +279,38 @@ tsl_gorilla_compressor_append(PG_FUNCTION_ARGS)
old_context = MemoryContextSwitchTo(agg_context);
if (compressor == NULL)
compressor = gorilla_compressor_alloc();
{
compressor = gorilla_compressor_for_type(get_fn_expr_argtype(fcinfo->flinfo, 1));
}
if (PG_ARGISNULL(1))
gorilla_compressor_append_null(compressor);
compressor->append_null(compressor);
else
{
double next_val = PG_GETARG_FLOAT8(1);
gorilla_compressor_append_value(compressor, double_get_bits(next_val));
compressor->append_val(compressor, PG_GETARG_DATUM(1));
}
MemoryContextSwitchTo(old_context);
PG_RETURN_POINTER(compressor);
}
/* This function is used for testing only. */
Datum
tsl_gorilla_compressor_finish(PG_FUNCTION_ARGS)
{
Compressor *compressor = (Compressor *) (PG_ARGISNULL(0) ? NULL : PG_GETARG_POINTER(0));
if (compressor == NULL)
PG_RETURN_NULL();
void *compressed = compressor->finish(compressor);
if (compressed == NULL)
PG_RETURN_NULL();
PG_RETURN_POINTER(compressed);
}
void
gorilla_compressor_append_null(GorillaCompressor *compressor)
{
@ -440,22 +458,6 @@ gorilla_compressor_finish(GorillaCompressor *compressor)
return compressed_gorilla_data_serialize(&data);
}
Datum
tsl_gorilla_compressor_finish(PG_FUNCTION_ARGS)
{
GorillaCompressor *compressor =
(GorillaCompressor *) (PG_ARGISNULL(0) ? NULL : PG_GETARG_POINTER(0));
void *compressed;
if (compressor == NULL)
PG_RETURN_NULL();
compressed = gorilla_compressor_finish(compressor);
if (compressed == NULL)
PG_RETURN_NULL();
PG_RETURN_POINTER(compressed);
}
/*******************************
*** DecompressionIterator ***
*******************************/

File diff suppressed because one or more lines are too long

View File

@ -9,14 +9,16 @@ AS :TSL_MODULE_PATHNAME LANGUAGE C VOLATILE;
\ir include/compression_utils.sql
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
-- helper function: float -> pseudorandom float [0..1].
create or replace function mix(x float4) returns float4 as $$ select ((hashfloat4(x) / (pow(2., 31) - 1) + 1) / 2)::float4 $$ language sql;
create or replace function mix(x timestamptz) returns float4 as $$ select mix(extract(epoch from x)::float4) $$ language sql;
------------------
-- C unit tests --
------------------
SELECT ts_test_compression();
\ir include/rand_generator.sql
------------------------
-- BIGINT Compression --
------------------------
@ -32,7 +34,7 @@ SELECT
\set DECOMPRESS_REVERSE_CMD _timescaledb_internal.decompress_reverse(c::_timescaledb_internal.compressed_data, NULL::BIGINT)
-- random order
CREATE TABLE base_ints AS SELECT row_number() OVER() as rn, item::bigint FROM (select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY gen_rand_minstd()) sub;
CREATE TABLE base_ints AS SELECT row_number() OVER() as rn, item::bigint FROM (select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
DROP TABLE base_ints;
@ -90,7 +92,7 @@ DROP TABLE base_ints;
-- INT Compression --
------------------------
CREATE TABLE base_ints AS SELECT row_number() OVER() as rn, item::int FROM (select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY gen_rand_minstd()) sub;
CREATE TABLE base_ints AS SELECT row_number() OVER() as rn, item::int FROM (select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY mix(item)) sub;
SELECT
$$
select item::bigint from base_ints order by rn
@ -117,11 +119,74 @@ SELECT
\set DECOMPRESS_REVERSE_CMD _timescaledb_internal.decompress_reverse(c::_timescaledb_internal.compressed_data, NULL::TIMESTAMPTZ)
CREATE TABLE base_time AS SELECT row_number() OVER() as rn, item FROM
(select sub.item from (SELECT generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
DROP TABLE base_time;
------------------------
-- FLOAT4 Compression --
------------------------
SELECT
$$
select item from base_floats order by rn
$$ AS "QUERY"
\gset
\set TABLE_NAME base_floats
SELECT 'real' as "TYPE" \gset
\set COMPRESSION_CMD _timescaledb_internal.compress_gorilla(item)
SELECT '_timescaledb_internal.decompress_forward(c::_timescaledb_internal.compressed_data, NULL::float4)' AS "DECOMPRESS_FORWARD_CMD" \gset
SELECT '_timescaledb_internal.decompress_reverse(c::_timescaledb_internal.compressed_data, NULL::float4)' AS "DECOMPRESS_REVERSE_CMD" \gset
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, item::float4 FROM
(select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
SELECT c gorilla_text FROM compressed;
DROP TABLE base_floats;
-- single element
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, item::float4 FROM (SELECT generate_series(1, 1) item) sub;
\ir include/compression_test.sql
DROP TABLE base_floats;
--special values
CREATE TABLE base_floats AS SELECT row_number() over () as rn, item FROM
(
VALUES
--special
(0::float4), ('Infinity'), ('-Infinity'), ('NaN'),
--big deltas
(0), ('Infinity'), ('-Infinity'), ('Infinity'), ('-Infinity'),
(0), ('-Infinity'), (32), (5), ('-Infinity'), (-52), ('Infinity'),
(1000),
--big delta_deltas
(0), ('Infinity'), ('Infinity'), ('-Infinity'), ('-Infinity'), ('Infinity'), ('Infinity')
) as t(item);
\ir include/compression_test.sql
DROP TABLE base_floats;
-- all 0s
CREATE TABLE base_floats AS SELECT row_number() over () as rn, 0::float4 as item FROM (SELECT generate_series(1, 1000) ) j;
\ir include/compression_test.sql
DROP TABLE base_floats;
-- NULLs
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, NULLIF(i, 5)::float4 item FROM generate_series(1, 10) i;
\ir include/compression_test.sql
DROP TABLE base_floats;
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, NULLIF(i, 1)::float4 item FROM generate_series(1, 10) i;
\ir include/compression_test.sql
DROP TABLE base_floats;
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, NULLIF(i, 10)::float4 item FROM generate_series(1, 10) i;
\ir include/compression_test.sql
DROP TABLE base_floats;
CREATE TABLE base_floats AS SELECT row_number() OVER() as rn, NULLIF(NULLIF(NULLIF(NULLIF(i, 2), 4), 5), 8)::float4 item FROM generate_series(1, 10) i;
\ir include/compression_test.sql
DROP TABLE base_floats;
------------------------
-- DOUBLE Compression --
------------------------
@ -138,7 +203,7 @@ SELECT '_timescaledb_internal.decompress_forward(c::_timescaledb_internal.compre
SELECT '_timescaledb_internal.decompress_reverse(c::_timescaledb_internal.compressed_data, NULL::DOUBLE PRECISION)' AS "DECOMPRESS_REVERSE_CMD" \gset
CREATE TABLE base_doubles AS SELECT row_number() OVER() as rn, item::double precision FROM
(select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
SELECT c gorilla_text FROM compressed;
DROP TABLE base_doubles;
@ -204,7 +269,7 @@ SELECT 'TEXT' as "TYPE" \gset
-- high cardinality
CREATE TABLE base_texts AS SELECT row_number() OVER() as rn, item::text FROM
(select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series(1, 1000) item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
SELECT c from compressed;
DROP TABLE base_texts;
@ -212,7 +277,7 @@ DROP TABLE base_texts;
-- low cardinality
CREATE TABLE base_texts AS SELECT row_number() OVER() as rn, item::text FROM
(SELECT i as item FROM generate_series(1, 10) i, generate_series(1, 100) j ORDER BY gen_rand_minstd()) sub;
(SELECT i as item FROM generate_series(1, 10) i, generate_series(1, 100) j ORDER BY mix(i + j)) sub;
\ir include/compression_test.sql
DROP TABLE base_texts;
@ -224,7 +289,7 @@ DROP TABLE base_texts;
-- high cardinality with toasted values
CREATE TABLE base_texts AS SELECT row_number() OVER() as rn, repeat(item::text, 100000) as item FROM
(select sub.item from (SELECT generate_series(1, 10) item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series(1, 10) item) as sub ORDER BY mix(item)) sub;
--make sure it's toasted
SELECT pg_total_relation_size(reltoastrelid)
FROM pg_class c
@ -267,7 +332,7 @@ SELECT 'TEXT' as "TYPE" \gset
--basic test
CREATE TABLE base_texts AS SELECT row_number() OVER() as rn, item::text FROM
(select sub.item from (SELECT generate_series(1, 100) item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series(1, 100) item) as sub ORDER BY mix(item)) sub;
\ir include/compression_test.sql
SELECT c from compressed;
DROP TABLE base_texts;
@ -279,7 +344,7 @@ DROP TABLE base_texts;
-- toasted values
CREATE TABLE base_texts AS SELECT row_number() OVER() as rn, repeat(item::text, 100000) as item FROM
(select sub.item from (SELECT generate_series(1, 10) item) as sub ORDER BY gen_rand_minstd()) sub;
(select sub.item from (SELECT generate_series(1, 10) item) as sub ORDER BY mix(item)) sub;
--make sure it's toasted
SELECT pg_total_relation_size(reltoastrelid)
FROM pg_class c

View File

@ -34,7 +34,7 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.deltadelta_compressor_finish(in
AS :MODULE_PATHNAME, 'ts_deltadelta_compressor_finish'
LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.gorilla_compressor_append(internal, DOUBLE PRECISION)
CREATE OR REPLACE FUNCTION _timescaledb_internal.gorilla_compressor_append(internal, ANYELEMENT)
RETURNS internal
AS :MODULE_PATHNAME, 'ts_gorilla_compressor_append'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
@ -86,7 +86,7 @@ CREATE AGGREGATE _timescaledb_internal.compress_deltadelta(timestamptz) (
FINALFUNC = _timescaledb_internal.timestamptz_compress_finish
);
CREATE AGGREGATE _timescaledb_internal.compress_gorilla(DOUBLE PRECISION) (
CREATE AGGREGATE _timescaledb_internal.compress_gorilla(ANYELEMENT) (
STYPE = internal,
SFUNC = _timescaledb_internal.gorilla_compressor_append,
FINALFUNC = _timescaledb_internal.gorilla_compressor_finish

View File

@ -38,6 +38,8 @@
#define VEC_SCOPE static inline
#include <adts/vec.h>
#define TEST_ELEMENTS 1015
TS_FUNCTION_INFO_V1(ts_test_compression);
TS_FUNCTION_INFO_V1(ts_compress_table);
TS_FUNCTION_INFO_V1(ts_decompress_table);
@ -49,7 +51,7 @@ test_int_array()
ArrayCompressed *compressed;
DecompressionIterator *iter;
int i;
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
array_compressor_append(compressor, Int32GetDatum(i));
compressed = array_compressor_finish(compressor);
@ -65,7 +67,7 @@ test_int_array()
TestAssertInt64Eq(DatumGetInt32(r.val), i);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
iter =
tsl_array_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), INT4OID);
@ -91,7 +93,7 @@ test_string_array()
for (i = 0; i < 5; i++)
texts[i] = cstring_to_text(strings[i]);
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
array_compressor_append(compressor, PointerGetDatum(texts[i % 5]));
compressed = array_compressor_finish(compressor);
@ -113,7 +115,7 @@ test_string_array()
__LINE__);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
iter =
tsl_array_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), TEXTOID);
@ -140,7 +142,7 @@ test_int_dictionary()
DictionaryCompressed *compressed;
DecompressionIterator *iter;
int i;
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
dictionary_compressor_append(compressor, Int32GetDatum(i % 15));
compressed = dictionary_compressor_finish(compressor);
@ -156,7 +158,7 @@ test_int_dictionary()
TestAssertInt64Eq(DatumGetInt32(r.val), i % 15);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
}
static void
@ -222,7 +224,7 @@ test_gorilla_int()
GorillaCompressed *compressed;
DecompressionIterator *iter;
uint32 i;
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
gorilla_compressor_append_value(compressor, i);
compressed = gorilla_compressor_finish(compressor);
@ -238,7 +240,7 @@ test_gorilla_int()
TestAssertInt64Eq(DatumGetInt64(r.val), i);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
iter = gorilla_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), INT8OID);
for (DecompressResult r = gorilla_decompression_iterator_try_next_reverse(iter); !r.is_done;
@ -277,7 +279,7 @@ test_gorilla_int()
TestAssertInt64Eq(DatumGetInt64(r.val), i);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
}
}
@ -288,7 +290,7 @@ test_gorilla_float()
GorillaCompressed *compressed;
DecompressionIterator *iter;
float i;
for (i = 0.0; i < 1015.0; i++)
for (i = 0.0; i < TEST_ELEMENTS; i++)
gorilla_compressor_append_value(compressor, float_get_bits(i));
compressed = gorilla_compressor_finish(compressor);
@ -305,7 +307,7 @@ test_gorilla_float()
TestAssertDoubleEq(DatumGetFloat4(r.val), i);
i += 1.0;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
iter =
gorilla_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), FLOAT4OID);
@ -319,42 +321,112 @@ test_gorilla_float()
TestAssertInt64Eq(i, 0);
}
static uint64
test_hash64(uint64 x)
{
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9U;
x ^= x >> 27;
x *= 0x94d049bb133111ebU;
x ^= x >> 31;
return x;
}
static void
test_gorilla_double()
test_gorilla_double(bool have_nulls, bool have_random)
{
GorillaCompressor *compressor = gorilla_compressor_alloc();
GorillaCompressed *compressed;
DecompressionIterator *iter;
double i;
for (i = 0.0; i < 1015.0; i++)
gorilla_compressor_append_value(compressor, double_get_bits(i));
double values[TEST_ELEMENTS];
bool nulls[TEST_ELEMENTS];
for (int i = 0; i < TEST_ELEMENTS; i++)
{
if (have_random)
{
/* Also add some stretches of equal numbers. */
int base = i;
if (i % 37 < 3)
{
base = 1;
}
else if (i % 53 < 2)
{
base = 2;
}
values[i] = (test_hash64(base) / (double) PG_UINT64_MAX) * 100.;
}
else
{
values[i] = i;
}
if (have_nulls && i % 29 == 0)
{
nulls[i] = true;
}
else
{
nulls[i] = false;
}
if (nulls[i])
{
gorilla_compressor_append_null(compressor);
}
else
{
gorilla_compressor_append_value(compressor, double_get_bits(values[i]));
}
}
compressed = gorilla_compressor_finish(compressor);
TestAssertTrue(compressed != NULL);
TestAssertInt64Eq(VARSIZE(compressed), 1200);
i = 0;
iter =
gorilla_decompression_iterator_from_datum_forward(PointerGetDatum(compressed), FLOAT8OID);
for (DecompressResult r = gorilla_decompression_iterator_try_next_forward(iter); !r.is_done;
r = gorilla_decompression_iterator_try_next_forward(iter))
if (!have_nulls && !have_random)
{
TestAssertTrue(!r.is_null);
TestAssertDoubleEq(DatumGetFloat8(r.val), i);
i += 1.0;
TestAssertInt64Eq(VARSIZE(compressed), 1200);
}
TestAssertInt64Eq(i, 1015);
/* Forward decompression. */
DecompressionIterator *iter =
gorilla_decompression_iterator_from_datum_forward(PointerGetDatum(compressed), FLOAT8OID);
for (int i = 0; i < TEST_ELEMENTS; i++)
{
DecompressResult r = gorilla_decompression_iterator_try_next_forward(iter);
TestAssertTrue(!r.is_done);
if (r.is_null)
{
TestAssertTrue(nulls[i]);
}
else
{
TestAssertTrue(!nulls[i]);
TestAssertTrue(values[i] == DatumGetFloat8(r.val));
}
}
DecompressResult r = gorilla_decompression_iterator_try_next_forward(iter);
TestAssertTrue(r.is_done);
/* Reverse decompression. */
iter =
gorilla_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), FLOAT8OID);
for (DecompressResult r = gorilla_decompression_iterator_try_next_reverse(iter); !r.is_done;
r = gorilla_decompression_iterator_try_next_reverse(iter))
for (int i = TEST_ELEMENTS - 1; i >= 0; i--)
{
TestAssertTrue(!r.is_null);
TestAssertDoubleEq(DatumGetFloat8(r.val), i - 1);
i -= 1;
DecompressResult r = gorilla_decompression_iterator_try_next_reverse(iter);
TestAssertTrue(!r.is_done);
if (r.is_null)
{
TestAssertTrue(nulls[i]);
}
else
{
TestAssertTrue(!nulls[i]);
TestAssertTrue(values[i] == DatumGetFloat8(r.val));
}
}
TestAssertInt64Eq(i, 0);
r = gorilla_decompression_iterator_try_next_reverse(iter);
TestAssertTrue(r.is_done);
}
static void
@ -364,7 +436,7 @@ test_delta()
Datum compressed;
DecompressionIterator *iter;
int i;
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
delta_delta_compressor_append_value(compressor, i);
compressed = DirectFunctionCall1(tsl_deltadelta_compressor_finish, PointerGetDatum(compressor));
@ -380,7 +452,7 @@ test_delta()
TestAssertInt64Eq(DatumGetInt64(r.val), i);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
}
static void
@ -390,7 +462,7 @@ test_delta2()
Datum compressed;
DecompressionIterator *iter;
int i;
for (i = 0; i < 1015; i++)
for (i = 0; i < TEST_ELEMENTS; i++)
{
/* prevent everything from being rle'd away */
if (i % 2 != 0)
@ -415,7 +487,100 @@ test_delta2()
TestAssertInt64Eq(DatumGetInt64(r.val), i);
i += 1;
}
TestAssertInt64Eq(i, 1015);
TestAssertInt64Eq(i, TEST_ELEMENTS);
}
static void
test_delta3(bool have_nulls, bool have_random)
{
DeltaDeltaCompressor *compressor = delta_delta_compressor_alloc();
Datum compressed;
int64 values[TEST_ELEMENTS];
bool nulls[TEST_ELEMENTS];
for (int i = 0; i < TEST_ELEMENTS; i++)
{
if (have_random)
{
/* Also add some stretches of equal numbers. */
int base = i;
if (i % 37 < 4)
{
base = 1;
}
else if (i % 53 < 2)
{
base = 2;
}
values[i] = test_hash64(base);
}
else
{
values[i] = i;
}
if (have_nulls && i % 29 == 0)
{
nulls[i] = true;
}
else
{
nulls[i] = false;
}
if (nulls[i])
{
delta_delta_compressor_append_null(compressor);
}
else
{
delta_delta_compressor_append_value(compressor, values[i]);
}
}
compressed = PointerGetDatum(delta_delta_compressor_finish(compressor));
TestAssertTrue(DatumGetPointer(compressed) != NULL);
/* Forward decompression. */
DecompressionIterator *iter =
delta_delta_decompression_iterator_from_datum_forward(PointerGetDatum(compressed), INT8OID);
for (int i = 0; i < TEST_ELEMENTS; i++)
{
DecompressResult r = delta_delta_decompression_iterator_try_next_forward(iter);
TestAssertTrue(!r.is_done);
if (r.is_null)
{
TestAssertTrue(nulls[i]);
}
else
{
TestAssertTrue(!nulls[i]);
TestAssertTrue(values[i] == DatumGetInt64(r.val));
}
}
DecompressResult r = delta_delta_decompression_iterator_try_next_forward(iter);
TestAssertTrue(r.is_done);
/* Reverse decompression. */
iter =
delta_delta_decompression_iterator_from_datum_reverse(PointerGetDatum(compressed), INT8OID);
for (int i = TEST_ELEMENTS - 1; i >= 0; i--)
{
DecompressResult r = delta_delta_decompression_iterator_try_next_reverse(iter);
TestAssertTrue(!r.is_done);
if (r.is_null)
{
TestAssertTrue(nulls[i]);
}
else
{
TestAssertTrue(!nulls[i]);
TestAssertTrue(values[i] == DatumGetInt64(r.val));
}
}
r = delta_delta_decompression_iterator_try_next_reverse(iter);
TestAssertTrue(r.is_done);
}
Datum
@ -427,9 +592,16 @@ ts_test_compression(PG_FUNCTION_ARGS)
test_string_dictionary();
test_gorilla_int();
test_gorilla_float();
test_gorilla_double();
test_gorilla_double(/* have_nulls = */ false, /* have_random = */ false);
test_gorilla_double(/* have_nulls = */ false, /* have_random = */ true);
test_gorilla_double(/* have_nulls = */ true, /* have_random = */ false);
test_gorilla_double(/* have_nulls = */ true, /* have_random = */ true);
test_delta();
test_delta2();
test_delta3(/* have_nulls = */ false, /* have_random = */ false);
test_delta3(/* have_nulls = */ false, /* have_random = */ true);
test_delta3(/* have_nulls = */ true, /* have_random = */ false);
test_delta3(/* have_nulls = */ true, /* have_random = */ true);
PG_RETURN_VOID();
}