diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/modules/injection_points/injection_points--1.0.sql | 10 | ||||
-rw-r--r-- | src/test/modules/injection_points/injection_stats.c | 12 | ||||
-rw-r--r-- | src/test/modules/injection_points/injection_stats_fixed.c | 4 | ||||
-rw-r--r-- | src/test/modules/injection_points/t/001_stats.pl | 12 | ||||
-rw-r--r-- | src/test/modules/test_bitmapset/expected/test_bitmapset.out | 826 | ||||
-rw-r--r-- | src/test/modules/test_bitmapset/sql/test_bitmapset.sql | 189 | ||||
-rw-r--r-- | src/test/modules/test_bitmapset/test_bitmapset--1.0.sql | 4 | ||||
-rw-r--r-- | src/test/modules/test_bitmapset/test_bitmapset.c | 55 | ||||
-rw-r--r-- | src/test/regress/expected/aggregates.out | 123 | ||||
-rw-r--r-- | src/test/regress/expected/stats_ext.out | 14 | ||||
-rw-r--r-- | src/test/regress/sql/aggregates.sql | 54 | ||||
-rw-r--r-- | src/test/regress/sql/stats_ext.sql | 8 |
12 files changed, 1271 insertions, 40 deletions
diff --git a/src/test/modules/injection_points/injection_points--1.0.sql b/src/test/modules/injection_points/injection_points--1.0.sql index 5f5657b2043..a7b61fbdfe6 100644 --- a/src/test/modules/injection_points/injection_points--1.0.sql +++ b/src/test/modules/injection_points/injection_points--1.0.sql @@ -100,6 +100,16 @@ AS 'MODULE_PATHNAME', 'injection_points_stats_numcalls' LANGUAGE C STRICT; -- +-- injection_points_stats_count() +-- +-- Return the number of entries stored in the pgstats hash table. +-- +CREATE FUNCTION injection_points_stats_count() +RETURNS bigint +AS 'MODULE_PATHNAME', 'injection_points_stats_count' +LANGUAGE C STRICT; + +-- -- injection_points_stats_drop() -- -- Drop all statistics of injection points. diff --git a/src/test/modules/injection_points/injection_stats.c b/src/test/modules/injection_points/injection_stats.c index ca8df4ad217..158e1631af9 100644 --- a/src/test/modules/injection_points/injection_stats.c +++ b/src/test/modules/injection_points/injection_stats.c @@ -40,6 +40,7 @@ static const PgStat_KindInfo injection_stats = { .name = "injection_points", .fixed_amount = false, /* Bounded by the number of points */ .write_to_file = true, + .track_entry_count = true, /* Injection points are system-wide */ .accessed_across_databases = true, @@ -196,6 +197,17 @@ injection_points_stats_numcalls(PG_FUNCTION_ARGS) PG_RETURN_INT64(entry->numcalls); } +/* + * SQL function returning the number of entries allocated for injection + * points in the shared hashtable of pgstats. + */ +PG_FUNCTION_INFO_V1(injection_points_stats_count); +Datum +injection_points_stats_count(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_get_entry_count(PGSTAT_KIND_INJECTION)); +} + /* Only used by injection_points_stats_drop() */ static bool match_inj_entries(PgStatShared_HashEntry *entry, Datum match_data) diff --git a/src/test/modules/injection_points/injection_stats_fixed.c b/src/test/modules/injection_points/injection_stats_fixed.c index bc54c79d190..74c35fcbfa7 100644 --- a/src/test/modules/injection_points/injection_stats_fixed.c +++ b/src/test/modules/injection_points/injection_stats_fixed.c @@ -152,6 +152,8 @@ pgstat_report_inj_fixed(uint32 numattach, stats_shmem = pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); + LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE); + pgstat_begin_changecount_write(&stats_shmem->changecount); stats_shmem->stats.numattach += numattach; stats_shmem->stats.numdetach += numdetach; @@ -159,6 +161,8 @@ pgstat_report_inj_fixed(uint32 numattach, stats_shmem->stats.numcached += numcached; stats_shmem->stats.numloaded += numloaded; pgstat_end_changecount_write(&stats_shmem->changecount); + + LWLockRelease(&stats_shmem->lock); } /* diff --git a/src/test/modules/injection_points/t/001_stats.pl b/src/test/modules/injection_points/t/001_stats.pl index 25de5fc46fe..47ab58d0e9b 100644 --- a/src/test/modules/injection_points/t/001_stats.pl +++ b/src/test/modules/injection_points/t/001_stats.pl @@ -36,6 +36,9 @@ $node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');"); my $numcalls = $node->safe_psql('postgres', "SELECT injection_points_stats_numcalls('stats-notice');"); is($numcalls, '2', 'number of stats calls'); +my $entrycount = + $node->safe_psql('postgres', "SELECT injection_points_stats_count();"); +is($entrycount, '1', 'number of entries'); my $fixedstats = $node->safe_psql('postgres', "SELECT * FROM injection_points_stats_fixed();"); is($fixedstats, '1|0|2|0|0', 'fixed stats after some calls'); @@ -55,6 +58,9 @@ $node->restart; $numcalls = $node->safe_psql('postgres', "SELECT injection_points_stats_numcalls('stats-notice');"); is($numcalls, '3', 'number of stats after clean restart'); +$entrycount = + $node->safe_psql('postgres', "SELECT injection_points_stats_count();"); +is($entrycount, '1', 'number of entries after clean restart'); $fixedstats = $node->safe_psql('postgres', "SELECT * FROM injection_points_stats_fixed();"); is($fixedstats, '1|0|2|1|1', 'fixed stats after clean restart'); @@ -65,6 +71,9 @@ $node->start; $numcalls = $node->safe_psql('postgres', "SELECT injection_points_stats_numcalls('stats-notice');"); is($numcalls, '', 'number of stats after crash'); +$entrycount = + $node->safe_psql('postgres', "SELECT injection_points_stats_count();"); +is($entrycount, '0', 'number of entries after crash'); $fixedstats = $node->safe_psql('postgres', "SELECT * FROM injection_points_stats_fixed();"); is($fixedstats, '0|0|0|0|0', 'fixed stats after crash'); @@ -81,6 +90,9 @@ $node->safe_psql('postgres', "SELECT injection_points_stats_drop();"); $numcalls = $node->safe_psql('postgres', "SELECT injection_points_stats_numcalls('stats-notice');"); is($numcalls, '', 'no stats after drop via SQL function'); +$entrycount = + $node->safe_psql('postgres', "SELECT injection_points_stats_count();"); +is($entrycount, '0', 'number of entries after drop via SQL function'); # Stop the server, disable the module, then restart. The server # should be able to come up. diff --git a/src/test/modules/test_bitmapset/expected/test_bitmapset.out b/src/test/modules/test_bitmapset/expected/test_bitmapset.out index abbfef1f7a6..be7b6399c82 100644 --- a/src/test/modules/test_bitmapset/expected/test_bitmapset.out +++ b/src/test/modules/test_bitmapset/expected/test_bitmapset.out @@ -21,6 +21,13 @@ SELECT test_bms_make_singleton(1000) AS result; (b 1000) (1 row) +-- Test module check +SELECT test_bms_make_singleton(NULL) AS result; + result +-------- + +(1 row) + -- bms_add_member() SELECT test_bms_add_member('(b 1)', -1); -- error ERROR: negative bitmapset member not allowed @@ -52,6 +59,13 @@ SELECT test_bms_add_member('(b 10)', 10) AS result; (b 10) (1 row) +-- Test module check +SELECT test_bms_add_member('(b)', NULL) AS result; + result +-------- + +(1 row) + -- bms_replace_members() SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result; result @@ -83,6 +97,38 @@ SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result; (b 3 5 7) (1 row) +-- Force repalloc() with larger set +SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; + result +------------- + (b 500 600) +(1 row) + +-- Test module checks +SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_replace_members('(b 5)', NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_replace_members(NULL, '(b 5)') AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_replace_members(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_del_member() SELECT test_bms_del_member('(b)', -20); -- error ERROR: negative bitmapset member not allowed @@ -124,6 +170,101 @@ SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result; (b 30 31 33 34) (1 row) +-- Force word count changes +SELECT test_bms_del_member('(b 1 200)', 200) AS result; + result +-------- + (b 1) +(1 row) + +SELECT test_bms_del_member('(b 1 50 100 200)', 200) AS result; + result +-------------- + (b 1 50 100) +(1 row) + +SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result; + result +-------------- + (b 1 50 200) +(1 row) + +-- Test module checks +SELECT test_bms_del_member('(b 42)', 42) AS result; + result +-------- + +(1 row) + +SELECT test_bms_del_member('(b 5)', NULL) AS result; + result +-------- + +(1 row) + +-- bms_del_members() +SELECT test_bms_del_members('(b)', '(b 10)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_del_members('(b 10)', '(b 10)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_del_members('(b 10)', '(b 5)') AS result; + result +-------- + (b 10) +(1 row) + +SELECT test_bms_del_members('(b 1 2 3)', '(b 2)') AS result; + result +--------- + (b 1 3) +(1 row) + +SELECT test_bms_del_members('(b 5 100)', '(b 100)') AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_del_members('(b 5 100 200)', '(b 200)') AS result; + result +----------- + (b 5 100) +(1 row) + +-- Force word count changes +SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 1 2)') AS result; + result +----------------- + (b 100 200 300) +(1 row) + +SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 200 300)') AS result; + result +------------- + (b 1 2 100) +(1 row) + +-- Test module checks +SELECT test_bms_del_members('(b 5)', NULL) AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_del_members(NULL, '(b 5)') AS result; + result +-------- + +(1 row) + -- bms_join() SELECT test_bms_join('(b 1 3 5)', NULL) AS result; result @@ -149,8 +290,40 @@ SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result; (b 1 3 4 5) (1 row) +-- Force word count changes +SELECT test_bms_join('(b 5)', '(b 100)') AS result; + result +----------- + (b 5 100) +(1 row) + +SELECT test_bms_join('(b 1 2)', '(b 100 200 300)') AS result; + result +--------------------- + (b 1 2 100 200 300) +(1 row) + +-- Test module checks +SELECT test_bms_join('(b 5)', NULL) AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_join(NULL, '(b 5)') AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_join(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_union() --- Overlapping sets. +-- Overlapping sets SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result; result ------------- @@ -181,6 +354,38 @@ SELECT test_bms_union( (b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) (1 row) +-- Union with varrying word counts +SELECT test_bms_union('(b 1 2)', '(b 100 300)') AS result; + result +----------------- + (b 1 2 100 300) +(1 row) + +SELECT test_bms_union('(b 100 300)', '(b 1 2)') AS result; + result +----------------- + (b 1 2 100 300) +(1 row) + +-- Test module checks +SELECT test_bms_union('(b 5)', NULL) AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_union(NULL, '(b 5)') AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_union(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_intersect() -- Overlapping sets SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result; @@ -196,13 +401,51 @@ SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result; (1 row) --- Intersect with empty. +-- Intersect with empty SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result; result -------- (1 row) +-- Intersect with varrying word counts +SELECT test_bms_intersect('(b 1 300)', '(b 1 2 3 4 5)') AS result; + result +-------- + (b 1) +(1 row) + +SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result; + result +-------- + (b 1) +(1 row) + +-- Test module checks +SELECT test_bms_intersect('(b 1)', '(b 2)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_intersect('(b 5)', NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_intersect(NULL, '(b 5)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_intersect(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_int_members() -- Overlapping sets SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result; @@ -218,7 +461,7 @@ SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result; (1 row) --- Intersect with empty. +-- Intersect with empty SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result; result -------- @@ -232,6 +475,31 @@ SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result; (b 31 32 64) (1 row) +-- Test module checks +SELECT test_bms_int_members('(b 1)', '(b 2)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_int_members('(b 5)', NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_int_members(NULL, '(b 5)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_int_members(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_difference() -- Overlapping sets SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result; @@ -271,6 +539,44 @@ SELECT test_bms_difference( (b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49) (1 row) +-- Difference with different word counts +SELECT test_bms_difference('(b 5 100)', '(b 5)') AS result; + result +--------- + (b 100) +(1 row) + +SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result; + result +------------- + (b 100 200) +(1 row) + +-- Test module checks +SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_difference('(b 5)', NULL) AS result; + result +-------- + (b 5) +(1 row) + +SELECT test_bms_difference(NULL, '(b 5)') AS result; + result +-------- + +(1 row) + +SELECT test_bms_difference(NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_is_member() SELECT test_bms_is_member('(b)', -5); -- error ERROR: negative bitmapset member not allowed @@ -298,6 +604,13 @@ SELECT test_bms_is_member('(b)', 1) AS result; f (1 row) +-- Test module check +SELECT test_bms_is_member('(b 5)', NULL) AS result; + result +-------- + f +(1 row) + -- bms_member_index() SELECT test_bms_member_index(NULL, 1) AS result; result @@ -323,6 +636,38 @@ SELECT test_bms_member_index('(b 1 3 5)', 3) AS result; 1 (1 row) +-- Member index with various word positions +SELECT test_bms_member_index('(b 100 200)', 100) AS result; + result +-------- + 0 +(1 row) + +SELECT test_bms_member_index('(b 100 200)', 200) AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_member_index('(b 1 50 100 200)', 200) AS result; + result +-------- + 3 +(1 row) + +-- Test module checks +SELECT test_bms_member_index('', 5) AS result; + result +-------- + -1 +(1 row) + +SELECT test_bms_member_index(NULL, 5) AS result; + result +-------- + -1 +(1 row) + -- bms_num_members() SELECT test_bms_num_members('(b)') AS result; result @@ -373,6 +718,38 @@ SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; f (1 row) +-- Equal with different word counts +SELECT test_bms_equal('(b 5)', '(b 100)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result; + result +-------- + f +(1 row) + +-- Test module checks +SELECT test_bms_equal('(b 5)', NULL) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal(NULL, '(b 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal(NULL, NULL) AS result; + result +-------- + t +(1 row) + -- bms_compare() SELECT test_bms_compare('(b)', '(b)') AS result; result @@ -419,6 +796,25 @@ SELECT test_bms_compare( -1 (1 row) +-- Test module checks +SELECT test_bms_compare('(b 5)', NULL) AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_compare(NULL, '(b 5)') AS result; + result +-------- + -1 +(1 row) + +SELECT test_bms_compare(NULL, NULL) AS result; + result +-------- + 0 +(1 row) + -- bms_add_range() SELECT test_bms_add_range('(b)', -5, 10); -- error ERROR: negative bitmapset member not allowed @@ -474,6 +870,56 @@ SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result; 508 (1 row) +-- Force word count expansion +SELECT test_bms_add_range('(b 5)', 100, 105) AS result; + result +------------------------------- + (b 5 100 101 102 103 104 105) +(1 row) + +SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result; + result +-------- + 211 +(1 row) + +-- Test module checks +SELECT test_bms_add_range('(b 5)', 5, NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_add_range('(b 5)', NULL, 10) AS result; + result +-------- + +(1 row) + +SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result; + result +-------- + +(1 row) + +SELECT test_bms_add_range(NULL, 5, 10) AS result; + result +------------------ + (b 5 6 7 8 9 10) +(1 row) + +SELECT test_bms_add_range(NULL, 10, 5) AS result; + result +-------- + +(1 row) + +SELECT test_bms_add_range(NULL, NULL, NULL) AS result; + result +-------- + +(1 row) + -- bms_membership() SELECT test_bms_membership('(b)') AS result; result @@ -493,6 +939,13 @@ SELECT test_bms_membership('(b 1 2)') AS result; 2 (1 row) +-- Test module check +SELECT test_bms_membership(NULL) AS result; + result +-------- + 0 +(1 row) + -- bms_is_empty() SELECT test_bms_is_empty(NULL) AS result; result @@ -512,7 +965,16 @@ SELECT test_bms_is_empty('(b 1)') AS result; f (1 row) +-- Test module check +SELECT test_bms_is_empty(NULL) AS result; + result +-------- + t +(1 row) + -- bms_singleton_member() +SELECT test_bms_singleton_member('(b)'); -- error +ERROR: bitmapset is empty SELECT test_bms_singleton_member('(b 1 2)'); -- error ERROR: bitmapset has multiple members SELECT test_bms_singleton_member('(b 42)') AS result; @@ -521,7 +983,20 @@ SELECT test_bms_singleton_member('(b 42)') AS result; 42 (1 row) +-- Test module check +SELECT test_bms_singleton_member(NULL) AS result; + result +-------- + +(1 row) + -- bms_get_singleton_member() +SELECT test_bms_get_singleton_member('(b)', 1000); + test_bms_get_singleton_member +------------------------------- + 1000 +(1 row) + -- Not a singleton, returns input default SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result; result @@ -536,6 +1011,19 @@ SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result; 400 (1 row) +-- Test module checks +SELECT test_bms_get_singleton_member('', 1000) AS result; + result +-------- + 1000 +(1 row) + +SELECT test_bms_get_singleton_member(NULL, -1) AS result; + result +-------- + -1 +(1 row) + -- bms_next_member() and bms_prev_member() -- First member SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result; @@ -593,6 +1081,56 @@ SELECT test_bms_prev_member('(b)', 100) AS result; -2 (1 row) +-- Negative prevbit should result in highest possible bit in set +SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result; + result +-------- + 127 +(1 row) + +-- Test module checks +SELECT test_bms_next_member('', 5) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_next_member('(b 5)', NULL) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_next_member(NULL, 5) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_next_member(NULL, NULL) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_prev_member('', 5) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_prev_member('(b 5)', NULL) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_prev_member(NULL, 5) AS result; + result +-------- + -2 +(1 row) + -- bms_hash_value() SELECT test_bms_hash_value('(b)') = 0 AS result; result @@ -612,6 +1150,13 @@ SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS r t (1 row) +-- Test module check +SELECT test_bms_hash_value(NULL) AS result; + result +-------- + 0 +(1 row) + -- bms_overlap() SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result; result @@ -631,6 +1176,25 @@ SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result; f (1 row) +-- Test module checks +SELECT test_bms_overlap('(b 5)', NULL) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap(NULL, '(b 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap(NULL, NULL) AS result; + result +-------- + f +(1 row) + -- bms_is_subset() SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result; result @@ -663,6 +1227,38 @@ SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31), t (1 row) +-- Is subset with shorter word counts? +SELECT test_bms_is_subset('(b 5 100)', '(b 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_subset('(b 1 2 50 100)', '(b 1 2)') AS result; + result +-------- + f +(1 row) + +-- Test module checks +SELECT test_bms_is_subset('(b 5)', NULL) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_subset(NULL, '(b 5)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_subset(NULL, NULL) AS result; + result +-------- + t +(1 row) + -- bms_subset_compare() SELECT test_bms_subset_compare(NULL, NULL) AS result; result @@ -670,13 +1266,43 @@ SELECT test_bms_subset_compare(NULL, NULL) AS result; 0 (1 row) +SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_subset_compare('(b)', '(b)') AS result; + result +-------- + 0 +(1 row) + +SELECT test_bms_subset_compare('(b)', '(b 1)') AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_subset_compare('(b 1)', '(b)') AS result; + result +-------- + 2 +(1 row) + SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result; result -------- 2 (1 row) -SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result; +SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result; + result +-------- + 0 +(1 row) + +SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result; result -------- 1 @@ -688,24 +1314,109 @@ SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result; 2 (1 row) -SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result; +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 3)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 4)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 64)') AS result; result -------- 1 (1 row) -SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result; +SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3)') AS result; result -------- - 0 + 2 +(1 row) + +SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3 65)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1 3)', '(b 2 4)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1)', '(b 64)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 0)', '(b 32)') AS result; + result +-------- + 3 (1 row) -SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result; +SELECT test_bms_subset_compare('(b 0)', '(b 64)') AS result; result -------- 3 (1 row) +SELECT test_bms_subset_compare('(b 64)', '(b 1)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 2 64)') AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_subset_compare('(b 64 200)', '(b 1 201)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 1 64 65)', '(b 1 2 64)') AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result; + result +-------- + 3 +(1 row) + +-- Test module checks +SELECT test_bms_subset_compare('(b 5)', NULL) AS result; + result +-------- + 2 +(1 row) + +SELECT test_bms_subset_compare(NULL, '(b 5)') AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_subset_compare(NULL, NULL) AS result; + result +-------- + 0 +(1 row) + -- bms_copy() SELECT test_bms_copy(NULL) AS result; result @@ -719,13 +1430,14 @@ SELECT test_bms_copy('(b 1 3 5 7)') AS result; (b 1 3 5 7) (1 row) --- bms_add_members() -SELECT test_bms_add_member('(b)', 1000); -- error - test_bms_add_member ---------------------- - (b 1000) +-- Test module check +SELECT test_bms_copy(NULL) AS result; + result +-------- + (1 row) +-- bms_add_members() SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; result ------------- @@ -769,6 +1481,13 @@ SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result; t (1 row) +-- Test module check +SELECT test_bitmap_hash(NULL) AS result; + result +-------- + 0 +(1 row) + -- bitmap_match() SELECT test_bitmap_match('(b)', '(b)') AS result; result @@ -828,6 +1547,25 @@ SELECT (test_bitmap_match('(b)', '(b)') = 0) = t (1 row) +-- Test module checks +SELECT test_bitmap_match('(b 5)', NULL) AS result; + result +-------- + 1 +(1 row) + +SELECT test_bitmap_match(NULL, '(b 5)') AS result; + result +-------- + 1 +(1 row) + +SELECT test_bitmap_match(NULL, NULL) AS result; + result +-------- + 0 +(1 row) + -- bms_overlap_list() SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result; result @@ -866,6 +1604,30 @@ SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result; f (1 row) +-- Overlap list with negative numbers +SELECT test_bms_overlap_list('(b 5 10)', ARRAY[-1,5]) AS result; -- error +ERROR: negative bitmapset member not allowed +SELECT test_bms_overlap_list('(b 1 2 3)', ARRAY[-5,-1,0]) AS result; -- error +ERROR: negative bitmapset member not allowed +-- Test module checks +SELECT test_bms_overlap_list('(b 5)', NULL) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap_list(NULL, ARRAY[1,2,3]) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap_list(NULL, NULL) AS result; + result +-------- + f +(1 row) + -- bms_nonempty_difference() SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result; result @@ -897,6 +1659,44 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result; f (1 row) +-- Difference with different word counts +SELECT test_bms_nonempty_difference('(b 5)', '(b 100)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_nonempty_difference('(b 100)', '(b 5)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result; + result +-------- + t +(1 row) + +-- Test module checks +SELECT test_bms_nonempty_difference('(b 5)', NULL) AS result; + result +-------- + t +(1 row) + +SELECT test_bms_nonempty_difference(NULL, '(b 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_nonempty_difference(NULL, NULL) AS result; + result +-------- + f +(1 row) + -- random operations SELECT test_random_operations(-1, 10000, 81920, 0) > 0 AS result; result diff --git a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql index 2b2c72c876b..c6e6bce60a3 100644 --- a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql +++ b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql @@ -6,6 +6,8 @@ SELECT test_bms_make_singleton(-1); SELECT test_bms_make_singleton(42) AS result; SELECT test_bms_make_singleton(0) AS result; SELECT test_bms_make_singleton(1000) AS result; +-- Test module check +SELECT test_bms_make_singleton(NULL) AS result; -- bms_add_member() SELECT test_bms_add_member('(b 1)', -1); -- error @@ -16,6 +18,8 @@ SELECT test_bms_add_member('(b 5)', 10) AS result; SELECT test_bms_add_member('(b 10)', 5) AS result; -- idempotent change SELECT test_bms_add_member('(b 10)', 10) AS result; +-- Test module check +SELECT test_bms_add_member('(b)', NULL) AS result; -- bms_replace_members() SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result; @@ -23,6 +27,13 @@ SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result; SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5)') AS result; SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result; +-- Force repalloc() with larger set +SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; +-- Test module checks +SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; +SELECT test_bms_replace_members('(b 5)', NULL) AS result; +SELECT test_bms_replace_members(NULL, '(b 5)') AS result; +SELECT test_bms_replace_members(NULL, NULL) AS result; -- bms_del_member() SELECT test_bms_del_member('(b)', -20); -- error @@ -34,15 +45,43 @@ SELECT test_bms_del_member('(b 1 2 3)', 2) AS result; SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result; -- Word boundary SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result; +-- Force word count changes +SELECT test_bms_del_member('(b 1 200)', 200) AS result; +SELECT test_bms_del_member('(b 1 50 100 200)', 200) AS result; +SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result; +-- Test module checks +SELECT test_bms_del_member('(b 42)', 42) AS result; +SELECT test_bms_del_member('(b 5)', NULL) AS result; + +-- bms_del_members() +SELECT test_bms_del_members('(b)', '(b 10)') AS result; +SELECT test_bms_del_members('(b 10)', '(b 10)') AS result; +SELECT test_bms_del_members('(b 10)', '(b 5)') AS result; +SELECT test_bms_del_members('(b 1 2 3)', '(b 2)') AS result; +SELECT test_bms_del_members('(b 5 100)', '(b 100)') AS result; +SELECT test_bms_del_members('(b 5 100 200)', '(b 200)') AS result; +-- Force word count changes +SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 1 2)') AS result; +SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 200 300)') AS result; +-- Test module checks +SELECT test_bms_del_members('(b 5)', NULL) AS result; +SELECT test_bms_del_members(NULL, '(b 5)') AS result; -- bms_join() SELECT test_bms_join('(b 1 3 5)', NULL) AS result; SELECT test_bms_join(NULL, '(b 2 4 6)') AS result; SELECT test_bms_join('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result; +-- Force word count changes +SELECT test_bms_join('(b 5)', '(b 100)') AS result; +SELECT test_bms_join('(b 1 2)', '(b 100 200 300)') AS result; +-- Test module checks +SELECT test_bms_join('(b 5)', NULL) AS result; +SELECT test_bms_join(NULL, '(b 5)') AS result; +SELECT test_bms_join(NULL, NULL) AS result; -- bms_union() --- Overlapping sets. +-- Overlapping sets SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result; -- Union with NULL SELECT test_bms_union('(b 1 3 5)', '(b)') AS result; @@ -53,24 +92,44 @@ SELECT test_bms_union( test_bms_add_range('(b)', 0, 15), test_bms_add_range('(b)', 10, 20) ) AS result; +-- Union with varrying word counts +SELECT test_bms_union('(b 1 2)', '(b 100 300)') AS result; +SELECT test_bms_union('(b 100 300)', '(b 1 2)') AS result; +-- Test module checks +SELECT test_bms_union('(b 5)', NULL) AS result; +SELECT test_bms_union(NULL, '(b 5)') AS result; +SELECT test_bms_union(NULL, NULL) AS result; -- bms_intersect() -- Overlapping sets SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result; -- Disjoint sets SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result; --- Intersect with empty. +-- Intersect with empty SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result; +-- Intersect with varrying word counts +SELECT test_bms_intersect('(b 1 300)', '(b 1 2 3 4 5)') AS result; +SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result; +-- Test module checks +SELECT test_bms_intersect('(b 1)', '(b 2)') AS result; +SELECT test_bms_intersect('(b 5)', NULL) AS result; +SELECT test_bms_intersect(NULL, '(b 5)') AS result; +SELECT test_bms_intersect(NULL, NULL) AS result; -- bms_int_members() -- Overlapping sets SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result; -- Disjoint sets SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result; --- Intersect with empty. +-- Intersect with empty SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result; -- Multiple members SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result; +-- Test module checks +SELECT test_bms_int_members('(b 1)', '(b 2)') AS result; +SELECT test_bms_int_members('(b 5)', NULL) AS result; +SELECT test_bms_int_members(NULL, '(b 5)') AS result; +SELECT test_bms_int_members(NULL, NULL) AS result; -- bms_difference() -- Overlapping sets @@ -86,6 +145,14 @@ SELECT test_bms_difference( test_bms_add_range('(b)', 0, 100), test_bms_add_range('(b)', 50, 150) ) AS result; +-- Difference with different word counts +SELECT test_bms_difference('(b 5 100)', '(b 5)') AS result; +SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result; +-- Test module checks +SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result; +SELECT test_bms_difference('(b 5)', NULL) AS result; +SELECT test_bms_difference(NULL, '(b 5)') AS result; +SELECT test_bms_difference(NULL, NULL) AS result; -- bms_is_member() SELECT test_bms_is_member('(b)', -5); -- error @@ -93,12 +160,21 @@ SELECT test_bms_is_member('(b 1 3 5)', 1) AS result; SELECT test_bms_is_member('(b 1 3 5)', 2) AS result; SELECT test_bms_is_member('(b 1 3 5)', 3) AS result; SELECT test_bms_is_member('(b)', 1) AS result; +-- Test module check +SELECT test_bms_is_member('(b 5)', NULL) AS result; -- bms_member_index() SELECT test_bms_member_index(NULL, 1) AS result; SELECT test_bms_member_index('(b 1 3 5)', 2) AS result; SELECT test_bms_member_index('(b 1 3 5)', 1) AS result; SELECT test_bms_member_index('(b 1 3 5)', 3) AS result; +-- Member index with various word positions +SELECT test_bms_member_index('(b 100 200)', 100) AS result; +SELECT test_bms_member_index('(b 100 200)', 200) AS result; +SELECT test_bms_member_index('(b 1 50 100 200)', 200) AS result; +-- Test module checks +SELECT test_bms_member_index('', 5) AS result; +SELECT test_bms_member_index(NULL, 5) AS result; -- bms_num_members() SELECT test_bms_num_members('(b)') AS result; @@ -111,6 +187,13 @@ SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result; SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result; SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result; SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; +-- Equal with different word counts +SELECT test_bms_equal('(b 5)', '(b 100)') AS result; +SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result; +-- Test module checks +SELECT test_bms_equal('(b 5)', NULL) AS result; +SELECT test_bms_equal(NULL, '(b 5)') AS result; +SELECT test_bms_equal(NULL, NULL) AS result; -- bms_compare() SELECT test_bms_compare('(b)', '(b)') AS result; @@ -123,6 +206,10 @@ SELECT test_bms_compare( test_bms_add_range('(b)', 0, 63), test_bms_add_range('(b)', 0, 64) ) AS result; +-- Test module checks +SELECT test_bms_compare('(b 5)', NULL) AS result; +SELECT test_bms_compare(NULL, '(b 5)') AS result; +SELECT test_bms_compare(NULL, NULL) AS result; -- bms_add_range() SELECT test_bms_add_range('(b)', -5, 10); -- error @@ -138,26 +225,47 @@ SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result; -- Force reallocations SELECT length(test_bms_add_range('(b)', 0, 200)) AS result; SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result; +-- Force word count expansion +SELECT test_bms_add_range('(b 5)', 100, 105) AS result; +SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result; +-- Test module checks +SELECT test_bms_add_range('(b 5)', 5, NULL) AS result; +SELECT test_bms_add_range('(b 5)', NULL, 10) AS result; +SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result; +SELECT test_bms_add_range(NULL, 5, 10) AS result; +SELECT test_bms_add_range(NULL, 10, 5) AS result; +SELECT test_bms_add_range(NULL, NULL, NULL) AS result; -- bms_membership() SELECT test_bms_membership('(b)') AS result; SELECT test_bms_membership('(b 42)') AS result; SELECT test_bms_membership('(b 1 2)') AS result; +-- Test module check +SELECT test_bms_membership(NULL) AS result; -- bms_is_empty() SELECT test_bms_is_empty(NULL) AS result; SELECT test_bms_is_empty('(b)') AS result; SELECT test_bms_is_empty('(b 1)') AS result; +-- Test module check +SELECT test_bms_is_empty(NULL) AS result; -- bms_singleton_member() +SELECT test_bms_singleton_member('(b)'); -- error SELECT test_bms_singleton_member('(b 1 2)'); -- error SELECT test_bms_singleton_member('(b 42)') AS result; +-- Test module check +SELECT test_bms_singleton_member(NULL) AS result; -- bms_get_singleton_member() +SELECT test_bms_get_singleton_member('(b)', 1000); -- Not a singleton, returns input default SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result; -- Singletone, returns sole member SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result; +-- Test module checks +SELECT test_bms_get_singleton_member('', 1000) AS result; +SELECT test_bms_get_singleton_member(NULL, -1) AS result; -- bms_next_member() and bms_prev_member() -- First member @@ -176,16 +284,32 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result; SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result; -- Empty set SELECT test_bms_prev_member('(b)', 100) AS result; +-- Negative prevbit should result in highest possible bit in set +SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result; +-- Test module checks +SELECT test_bms_next_member('', 5) AS result; +SELECT test_bms_next_member('(b 5)', NULL) AS result; +SELECT test_bms_next_member(NULL, 5) AS result; +SELECT test_bms_next_member(NULL, NULL) AS result; +SELECT test_bms_prev_member('', 5) AS result; +SELECT test_bms_prev_member('(b 5)', NULL) AS result; +SELECT test_bms_prev_member(NULL, 5) AS result; -- bms_hash_value() SELECT test_bms_hash_value('(b)') = 0 AS result; SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result; SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result; +-- Test module check +SELECT test_bms_hash_value(NULL) AS result; -- bms_overlap() SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result; SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result; +-- Test module checks +SELECT test_bms_overlap('(b 5)', NULL) AS result; +SELECT test_bms_overlap(NULL, '(b 5)') AS result; +SELECT test_bms_overlap(NULL, NULL) AS result; -- bms_is_subset() SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result; @@ -194,22 +318,50 @@ SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result; SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result; SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31), test_bms_add_range(NULL, 0, 63)) AS result; +-- Is subset with shorter word counts? +SELECT test_bms_is_subset('(b 5 100)', '(b 5)') AS result; +SELECT test_bms_is_subset('(b 1 2 50 100)', '(b 1 2)') AS result; +-- Test module checks +SELECT test_bms_is_subset('(b 5)', NULL) AS result; +SELECT test_bms_is_subset(NULL, '(b 5)') AS result; +SELECT test_bms_is_subset(NULL, NULL) AS result; -- bms_subset_compare() SELECT test_bms_subset_compare(NULL, NULL) AS result; -SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result; SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result; -SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result; -SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result; +SELECT test_bms_subset_compare('(b)', '(b)') AS result; +SELECT test_bms_subset_compare('(b)', '(b 1)') AS result; +SELECT test_bms_subset_compare('(b 1)', '(b)') AS result; +SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result; SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result; -SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result; +SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result; +SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result; +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 3)') AS result; +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 4)') AS result; +SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 64)') AS result; +SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3)') AS result; +SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3 65)') AS result; +SELECT test_bms_subset_compare('(b 1 3)', '(b 2 4)') AS result; +SELECT test_bms_subset_compare('(b 1)', '(b 64)') AS result; +SELECT test_bms_subset_compare('(b 0)', '(b 32)') AS result; +SELECT test_bms_subset_compare('(b 0)', '(b 64)') AS result; +SELECT test_bms_subset_compare('(b 64)', '(b 1)') AS result; +SELECT test_bms_subset_compare('(b 1 2)', '(b 1 2 64)') AS result; +SELECT test_bms_subset_compare('(b 64 200)', '(b 1 201)') AS result; +SELECT test_bms_subset_compare('(b 1 64 65)', '(b 1 2 64)') AS result; +SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result; +-- Test module checks +SELECT test_bms_subset_compare('(b 5)', NULL) AS result; +SELECT test_bms_subset_compare(NULL, '(b 5)') AS result; +SELECT test_bms_subset_compare(NULL, NULL) AS result; -- bms_copy() SELECT test_bms_copy(NULL) AS result; SELECT test_bms_copy('(b 1 3 5 7)') AS result; +-- Test module check +SELECT test_bms_copy(NULL) AS result; -- bms_add_members() -SELECT test_bms_add_member('(b)', 1000); -- error SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 7)') AS result; SELECT test_bms_add_members('(b 1 3 5)', '(b 100 200 300)') AS result; @@ -219,6 +371,8 @@ SELECT test_bitmap_hash('(b)') = 0 AS result; SELECT test_bitmap_hash('(b 1 3 5)') = test_bitmap_hash('(b 1 3 5)') AS result; SELECT test_bitmap_hash('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result; SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result; +-- Test module check +SELECT test_bitmap_hash(NULL) AS result; -- bitmap_match() SELECT test_bitmap_match('(b)', '(b)') AS result; @@ -234,6 +388,10 @@ SELECT (test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') = 0) = test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT (test_bitmap_match('(b)', '(b)') = 0) = test_bms_equal('(b)', '(b)') AS result; +-- Test module checks +SELECT test_bitmap_match('(b 5)', NULL) AS result; +SELECT test_bitmap_match(NULL, '(b 5)') AS result; +SELECT test_bitmap_match(NULL, NULL) AS result; -- bms_overlap_list() SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result; @@ -243,6 +401,13 @@ SELECT test_bms_overlap_list('(b 7 10)', ARRAY[6,7,8,9]) AS result; SELECT test_bms_overlap_list('(b 1 5)', ARRAY[6,7,8,9]) AS result; -- Empty list SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result; +-- Overlap list with negative numbers +SELECT test_bms_overlap_list('(b 5 10)', ARRAY[-1,5]) AS result; -- error +SELECT test_bms_overlap_list('(b 1 2 3)', ARRAY[-5,-1,0]) AS result; -- error +-- Test module checks +SELECT test_bms_overlap_list('(b 5)', NULL) AS result; +SELECT test_bms_overlap_list(NULL, ARRAY[1,2,3]) AS result; +SELECT test_bms_overlap_list(NULL, NULL) AS result; -- bms_nonempty_difference() SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result; @@ -250,6 +415,14 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', NULL) AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 5)') AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result; +-- Difference with different word counts +SELECT test_bms_nonempty_difference('(b 5)', '(b 100)') AS result; +SELECT test_bms_nonempty_difference('(b 100)', '(b 5)') AS result; +SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result; +-- Test module checks +SELECT test_bms_nonempty_difference('(b 5)', NULL) AS result; +SELECT test_bms_nonempty_difference(NULL, '(b 5)') AS result; +SELECT test_bms_nonempty_difference(NULL, NULL) AS result; -- random operations SELECT test_random_operations(-1, 10000, 81920, 0) > 0 AS result; diff --git a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql index 95f5ee02e3f..b95c4d0dda5 100644 --- a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql +++ b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql @@ -112,6 +112,10 @@ CREATE FUNCTION test_bms_int_members(text, text) RETURNS text AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION test_bms_del_members(text, text) +RETURNS text +AS 'MODULE_PATHNAME' LANGUAGE C; + CREATE FUNCTION test_bms_replace_members(text, text) RETURNS text AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c index 5bc4daa23f1..2e821320836 100644 --- a/src/test/modules/test_bitmapset/test_bitmapset.c +++ b/src/test/modules/test_bitmapset/test_bitmapset.c @@ -58,6 +58,7 @@ PG_FUNCTION_INFO_V1(test_bms_member_index); PG_FUNCTION_INFO_V1(test_bms_add_range); PG_FUNCTION_INFO_V1(test_bms_add_members); PG_FUNCTION_INFO_V1(test_bms_int_members); +PG_FUNCTION_INFO_V1(test_bms_del_members); PG_FUNCTION_INFO_V1(test_bms_replace_members); PG_FUNCTION_INFO_V1(test_bms_join); PG_FUNCTION_INFO_V1(test_bitmap_hash); @@ -111,9 +112,6 @@ test_bms_add_member(PG_FUNCTION_ARGS) if (bms) bms_free(bms); - if (result == NULL) - PG_RETURN_NULL(); - PG_RETURN_TEXT_P(result); } @@ -136,9 +134,6 @@ test_bms_add_members(PG_FUNCTION_ARGS) if (bms2) bms_free(bms2); - if (bms1 == NULL) - PG_RETURN_NULL(); - result = BITMAPSET_TO_TEXT(bms1); bms_free(bms1); @@ -161,12 +156,8 @@ test_bms_del_member(PG_FUNCTION_ARGS) member = PG_GETARG_INT32(1); bms = bms_del_member(bms, member); - if (bms == NULL || bms_is_empty(bms)) - { - if (bms) - bms_free(bms); + if (bms_is_empty(bms)) PG_RETURN_NULL(); - } result = BITMAPSET_TO_TEXT(bms); bms_free(bms); @@ -515,8 +506,8 @@ test_bms_get_singleton_member(PG_FUNCTION_ARGS) { Bitmapset *bms = NULL; int32 default_member = PG_GETARG_INT32(1); - int member; bool success; + int member = -1; if (PG_ARGISNULL(0)) PG_RETURN_INT32(default_member); @@ -532,8 +523,8 @@ test_bms_get_singleton_member(PG_FUNCTION_ARGS) if (success) PG_RETURN_INT32(member); - else - PG_RETURN_INT32(default_member); + + PG_RETURN_INT32(default_member); } Datum @@ -609,11 +600,6 @@ test_bms_overlap_list(PG_FUNCTION_ARGS) array = PG_GETARG_ARRAYTYPE_P(1); - if (ARR_ELEMTYPE(array) != INT4OID) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("integer array expected"))); - deconstruct_array(array, INT4OID, sizeof(int32), true, 'i', &elem_datums, &elem_nulls, &elem_count); @@ -753,6 +739,37 @@ test_bms_int_members(PG_FUNCTION_ARGS) } Datum +test_bms_del_members(PG_FUNCTION_ARGS) +{ + Bitmapset *bms1 = NULL, + *bms2 = NULL; + Bitmapset *result_bms; + text *result; + + if (!PG_ARGISNULL(0)) + bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + + if (!PG_ARGISNULL(1)) + bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); + + /* IMPORTANT: bms_del_members modifies/frees the first argument */ + result_bms = bms_del_members(bms1, bms2); + + /* bms1 is now invalid, do not free it */ + + if (bms2) + bms_free(bms2); + + if (result_bms == NULL) + PG_RETURN_NULL(); + + result = BITMAPSET_TO_TEXT(result_bms); + bms_free(result_bms); + + PG_RETURN_TEXT_P(result); +} + +Datum test_bms_replace_members(PG_FUNCTION_ARGS) { Bitmapset *bms1 = NULL, diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 1f24f6ffd1f..035f9a78206 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1557,6 +1557,129 @@ drop table t2; drop table t3; drop table p_t1; -- +-- Test GROUP BY ALL +-- +-- We don't care about the data here, just the proper transformation of the +-- GROUP BY clause, so test some queries and verify the EXPLAIN plans. +-- +CREATE TEMP TABLE t1 ( + a int, + b int, + c int +); +-- basic example +EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: b + -> Seq Scan on t1 +(3 rows) + +-- multiple columns, non-consecutive order +EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: a, b + -> Seq Scan on t1 +(3 rows) + +-- multi columns, no aggregate +EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: (a + b) + -> Seq Scan on t1 +(3 rows) + +-- check we detect a non-top-level aggregate +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: a + -> Seq Scan on t1 +(3 rows) + +-- including grouped column is okay +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: a + -> Seq Scan on t1 +(3 rows) + +-- including non-grouped column, not so much +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL; +ERROR: column "t1.c" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY AL... + ^ +-- all aggregates, should reduce to GROUP BY () +EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + Aggregate + Group Key: () + -> Seq Scan on t1 +(3 rows) + +-- likewise with empty target list +EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL; + QUERY PLAN +----------------------- + Result + Replaces: Aggregate +(2 rows) + +-- window functions are not to be included in GROUP BY, either +EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------------------- + WindowAgg + Window: w1 AS (PARTITION BY a) + -> Sort + Sort Key: a + -> HashAggregate + Group Key: a + -> Seq Scan on t1 +(7 rows) + +-- all cols +EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL; + QUERY PLAN +---------------------- + HashAggregate + Group Key: a, b, c + -> Seq Scan on t1 +(3 rows) + +-- group by all with grouping element(s) (equivalent to GROUP BY's +-- default behavior, explicit antithesis to GROUP BY DISTINCT) +EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a; + QUERY PLAN +---------------------- + HashAggregate + Group Key: a + -> Seq Scan on t1 +(3 rows) + +-- verify deparsing of GROUP BY ALL +CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL; +SELECT pg_get_viewdef('v1'::regclass); + pg_get_viewdef +----------------------- + SELECT b, + + count(*) AS count+ + FROM t1 + + GROUP BY ALL; +(1 row) + +DROP VIEW v1; +DROP TABLE t1; +-- -- Test GROUP BY matching of join columns that are type-coerced due to USING -- create temp table t1(f1 int, f2 int); diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 9f378a6abdf..73a7ef97355 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -122,6 +122,20 @@ ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new; ERROR: must be owner of statistics object ab1_a_b_stats RESET SESSION AUTHORIZATION; DROP ROLE regress_stats_ext; +CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1; +SELECT regexp_replace(pg_describe_object(tableoid, oid, 0), + 'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr, + pg_statistics_obj_is_visible(oid) AS visible + FROM pg_statistic_ext + WHERE stxname = 'stats_ext_temp'; + descr | visible +---------------------------------------------------+--------- + statistics object pg_temp_REDACTED.stats_ext_temp | f +(1 row) + +DROP STATISTICS stats_ext_temp; -- shall fail +ERROR: statistics object "stats_ext_temp" does not exist +DROP STATISTICS pg_temp.stats_ext_temp; CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1; NOTICE: statistics object "ab1_a_b_stats" already exists, skipping DROP STATISTICS ab1_a_b_stats; diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 62540b1ffa4..908af50def3 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -550,6 +550,60 @@ drop table t3; drop table p_t1; -- +-- Test GROUP BY ALL +-- +-- We don't care about the data here, just the proper transformation of the +-- GROUP BY clause, so test some queries and verify the EXPLAIN plans. +-- + +CREATE TEMP TABLE t1 ( + a int, + b int, + c int +); + +-- basic example +EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL; + +-- multiple columns, non-consecutive order +EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL; + +-- multi columns, no aggregate +EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL; + +-- check we detect a non-top-level aggregate +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL; + +-- including grouped column is okay +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL; + +-- including non-grouped column, not so much +EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL; + +-- all aggregates, should reduce to GROUP BY () +EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL; + +-- likewise with empty target list +EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL; + +-- window functions are not to be included in GROUP BY, either +EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL; + +-- all cols +EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL; + +-- group by all with grouping element(s) (equivalent to GROUP BY's +-- default behavior, explicit antithesis to GROUP BY DISTINCT) +EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a; + +-- verify deparsing of GROUP BY ALL +CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL; +SELECT pg_get_viewdef('v1'::regclass); + +DROP VIEW v1; +DROP TABLE t1; + +-- -- Test GROUP BY matching of join columns that are type-coerced due to USING -- diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index d7e5c0c893a..96771600d57 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -83,6 +83,14 @@ DROP STATISTICS ab1_a_b_stats; ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new; RESET SESSION AUTHORIZATION; DROP ROLE regress_stats_ext; +CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1; +SELECT regexp_replace(pg_describe_object(tableoid, oid, 0), + 'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr, + pg_statistics_obj_is_visible(oid) AS visible + FROM pg_statistic_ext + WHERE stxname = 'stats_ext_temp'; +DROP STATISTICS stats_ext_temp; -- shall fail +DROP STATISTICS pg_temp.stats_ext_temp; CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1; DROP STATISTICS ab1_a_b_stats; |