From e8c1f8d2a4b8e7c5d6e3f4a5b6c7d8e9f0a1b2c3 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Wed, 27 May 2026 07:11:27 -0500 Subject: [PATCH] Add regression tests for btree skip scan support functions Several btree skip scan support functions in nbtcompare.c have zero test coverage as shown by coverage.postgresql.org: oid8: btoid8skipsupport, oid8_decrement, oid8_increment int8: btint8skipsupport, int8_decrement, int8_increment bool: btboolskipsupport, bool_decrement, bool_increment char: btcharskipsupport, char_decrement, char_increment oid: oid_decrement int2: int2_decrement Add tests that exercise skip scans (both forward and backward) on multi-column indexes with these types as the leading column. This triggers the per-type skip-support function and the increment/ decrement helpers via the Index Only Scan path. Author: Baji Shaik Reviewed-by: Discussion: --- diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index 21dc9b5783a..111f5d4b682 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -736,3 +736,235 @@ ALTER INDEX btree_part_idx ALTER COLUMN id SET (n_distinct=100); ERROR: ALTER action ALTER COLUMN ... SET cannot be performed on relation "btree_part_idx" DETAIL: This operation is not supported for partitioned indexes. DROP TABLE btree_part; +-- +-- Test btree skip scan support for types that currently lack test coverage +-- (exercises btXXXskipsupport, XXX_decrement, XXX_increment functions) +-- +SET enable_seqscan = off; +SET enable_bitmapscan = off; +-- int8: btint8skipsupport, int8_decrement, int8_increment +CREATE TABLE skip_int8 (a int8, b int4); +INSERT INTO skip_int8 SELECT i / 10, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_int8 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a; + QUERY PLAN +------------------------------------------------------ + Index Only Scan using skip_int8_a_b_idx on skip_int8 + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a; + a | b +---+--- + 0 | 5 + 1 | 5 + 2 | 5 + 3 | 5 + 4 | 5 + 5 | 5 + 6 | 5 + 7 | 5 + 8 | 5 + 9 | 5 +(10 rows) + +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a DESC; + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan Backward using skip_int8_a_b_idx on skip_int8 + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a DESC; + a | b +---+--- + 9 | 5 + 8 | 5 + 7 | 5 + 6 | 5 + 5 | 5 + 4 | 5 + 3 | 5 + 2 | 5 + 1 | 5 + 0 | 5 +(10 rows) + +DROP TABLE skip_int8; +-- oid8: btoid8skipsupport, oid8_decrement, oid8_increment +CREATE TABLE skip_oid8 (a oid8, b int4); +INSERT INTO skip_oid8 SELECT (i / 10)::int8::oid8, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_oid8 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a; + QUERY PLAN +------------------------------------------------------ + Index Only Scan using skip_oid8_a_b_idx on skip_oid8 + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a; + a | b +---+--- + 0 | 5 + 1 | 5 + 2 | 5 + 3 | 5 + 4 | 5 + 5 | 5 + 6 | 5 + 7 | 5 + 8 | 5 + 9 | 5 +(10 rows) + +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a DESC; + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan Backward using skip_oid8_a_b_idx on skip_oid8 + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a DESC; + a | b +---+--- + 9 | 5 + 8 | 5 + 7 | 5 + 6 | 5 + 5 | 5 + 4 | 5 + 3 | 5 + 2 | 5 + 1 | 5 + 0 | 5 +(10 rows) + +DROP TABLE skip_oid8; +-- bool: btboolskipsupport, bool_decrement, bool_increment +CREATE TABLE skip_bool (a bool, b int4); +INSERT INTO skip_bool SELECT (i % 2 = 0), i FROM generate_series(1, 100) i; +CREATE INDEX ON skip_bool (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a; + QUERY PLAN +------------------------------------------------------ + Index Only Scan using skip_bool_a_b_idx on skip_bool + Index Cond: (b = 50) +(2 rows) + +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a; + a | b +---+---- + t | 50 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a DESC; + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan Backward using skip_bool_a_b_idx on skip_bool + Index Cond: (b = 50) +(2 rows) + +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a DESC; + a | b +---+---- + t | 50 +(1 row) + +DROP TABLE skip_bool; +-- "char": btcharskipsupport, char_decrement, char_increment +CREATE TABLE skip_char (a "char", b int4); +INSERT INTO skip_char SELECT chr(ascii('a') + (i % 26))::"char", i FROM generate_series(1, 100) i; +CREATE INDEX ON skip_char (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a; + QUERY PLAN +------------------------------------------------------ + Index Only Scan using skip_char_a_b_idx on skip_char + Index Cond: (b = 50) +(2 rows) + +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a; + a | b +---+---- + y | 50 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a DESC; + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan Backward using skip_char_a_b_idx on skip_char + Index Cond: (b = 50) +(2 rows) + +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a DESC; + a | b +---+---- + y | 50 +(1 row) + +DROP TABLE skip_char; +-- oid: oid_decrement (btoidskipsupport and oid_increment already covered) +CREATE TABLE skip_oid (a oid, b int4); +INSERT INTO skip_oid SELECT (i / 10)::oid, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_oid (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid WHERE b = 5 ORDER BY a DESC; + QUERY PLAN +------------------------------------------------------------- + Index Only Scan Backward using skip_oid_a_b_idx on skip_oid + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_oid WHERE b = 5 ORDER BY a DESC; + a | b +---+--- + 9 | 5 + 8 | 5 + 7 | 5 + 6 | 5 + 5 | 5 + 4 | 5 + 3 | 5 + 2 | 5 + 1 | 5 + 0 | 5 +(10 rows) + +DROP TABLE skip_oid; +-- int2: int2_decrement (btint2skipsupport and int2_increment already covered) +CREATE TABLE skip_int2 (a int2, b int4); +INSERT INTO skip_int2 SELECT (i / 10)::int2, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_int2 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int2 WHERE b = 5 ORDER BY a DESC; + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan Backward using skip_int2_a_b_idx on skip_int2 + Index Cond: (b = 5) +(2 rows) + +SELECT a, b FROM skip_int2 WHERE b = 5 ORDER BY a DESC; + a | b +---+--- + 9 | 5 + 8 | 5 + 7 | 5 + 6 | 5 + 5 | 5 + 4 | 5 + 3 | 5 + 2 | 5 + 1 | 5 + 0 | 5 +(10 rows) + +DROP TABLE skip_int2; +RESET enable_seqscan; +RESET enable_bitmapscan; diff --git a/src/test/regress/sql/btree_index.sql b/src/test/regress/sql/btree_index.sql index 6aaaa386abc..1109f1e0506 100644 --- a/src/test/regress/sql/btree_index.sql +++ b/src/test/regress/sql/btree_index.sql @@ -438,3 +438,79 @@ CREATE TABLE btree_part (id int4) PARTITION BY RANGE (id); CREATE INDEX btree_part_idx ON btree_part(id); ALTER INDEX btree_part_idx ALTER COLUMN id SET (n_distinct=100); DROP TABLE btree_part; + +-- +-- Test btree skip scan support for types that currently lack test coverage +-- (exercises btXXXskipsupport, XXX_decrement, XXX_increment functions) +-- +SET enable_seqscan = off; +SET enable_bitmapscan = off; + +-- int8: btint8skipsupport, int8_decrement, int8_increment +CREATE TABLE skip_int8 (a int8, b int4); +INSERT INTO skip_int8 SELECT i / 10, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_int8 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a; +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a; +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a DESC; +SELECT a, b FROM skip_int8 WHERE b = 5 ORDER BY a DESC; +DROP TABLE skip_int8; + +-- oid8: btoid8skipsupport, oid8_decrement, oid8_increment +CREATE TABLE skip_oid8 (a oid8, b int4); +INSERT INTO skip_oid8 SELECT (i / 10)::int8::oid8, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_oid8 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a; +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a; +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a DESC; +SELECT a, b FROM skip_oid8 WHERE b = 5 ORDER BY a DESC; +DROP TABLE skip_oid8; + +-- bool: btboolskipsupport, bool_decrement, bool_increment +CREATE TABLE skip_bool (a bool, b int4); +INSERT INTO skip_bool SELECT (i % 2 = 0), i FROM generate_series(1, 100) i; +CREATE INDEX ON skip_bool (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a; +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a; +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a DESC; +SELECT a, b FROM skip_bool WHERE b = 50 ORDER BY a DESC; +DROP TABLE skip_bool; + +-- "char": btcharskipsupport, char_decrement, char_increment +CREATE TABLE skip_char (a "char", b int4); +INSERT INTO skip_char SELECT chr(ascii('a') + (i % 26))::"char", i FROM generate_series(1, 100) i; +CREATE INDEX ON skip_char (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a; +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a; +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a DESC; +SELECT a, b FROM skip_char WHERE b = 50 ORDER BY a DESC; +DROP TABLE skip_char; + +-- oid: oid_decrement (btoidskipsupport and oid_increment already covered) +CREATE TABLE skip_oid (a oid, b int4); +INSERT INTO skip_oid SELECT (i / 10)::oid, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_oid (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_oid WHERE b = 5 ORDER BY a DESC; +SELECT a, b FROM skip_oid WHERE b = 5 ORDER BY a DESC; +DROP TABLE skip_oid; + +-- int2: int2_decrement (btint2skipsupport and int2_increment already covered) +CREATE TABLE skip_int2 (a int2, b int4); +INSERT INTO skip_int2 SELECT (i / 10)::int2, i % 10 FROM generate_series(1, 100) i; +CREATE INDEX ON skip_int2 (a, b); +EXPLAIN (COSTS OFF) +SELECT a, b FROM skip_int2 WHERE b = 5 ORDER BY a DESC; +SELECT a, b FROM skip_int2 WHERE b = 5 ORDER BY a DESC; +DROP TABLE skip_int2; + +RESET enable_seqscan; +RESET enable_bitmapscan; -- 2.50.1 (Apple Git-155)