From ee5da25dbba924c1c9a399568c27db8ac603e2d8 Mon Sep 17 00:00:00 2001 From: ChangAo Chen Date: Sun, 14 Dec 2025 18:13:31 +0800 Subject: [PATCH v1 1/3] Add pg_lfind8_nonzero(). --- src/include/port/pg_lfind.h | 40 +++++++++++++++++++ .../test_lfind/expected/test_lfind.out | 6 +++ .../modules/test_lfind/sql/test_lfind.sql | 1 + .../modules/test_lfind/test_lfind--1.0.sql | 4 ++ src/test/modules/test_lfind/test_lfind.c | 17 ++++++++ 5 files changed, 68 insertions(+) diff --git a/src/include/port/pg_lfind.h b/src/include/port/pg_lfind.h index 20f7497dcb7..8dd7b81ebba 100644 --- a/src/include/port/pg_lfind.h +++ b/src/include/port/pg_lfind.h @@ -80,6 +80,46 @@ pg_lfind8_le(uint8 key, uint8 *base, uint32 nelem) return false; } +/* + * pg_lfind8_nonzero + * + * Return true if there is an element in 'base' that is not equal to + * zero, otherwise return false. + */ +static inline bool +pg_lfind8_nonzero(uint8 *base, uint32 nelem) +{ + uint32 i; + uint32 tail_idx; + uint64 chunk; + + /* Search the array one-by-one if there aren't enough elements. */ + if (nelem < sizeof(chunk)) + { + for (i = 0; i < nelem; i++) + { + if (base[i] != 0) + return true; + } + return false; + } + + /* Round down to multiple of chunk length. */ + tail_idx = nelem & ~(sizeof(chunk) - 1); + + for (i = 0; i < tail_idx; i += sizeof(chunk)) + { + /* memcpy() to avoid unaligned access. */ + memcpy(&chunk, &base[i], sizeof(chunk)); + if (chunk != 0) + return true; + } + + /* Process the last chunk in the array. */ + memcpy(&chunk, &base[nelem - sizeof(chunk)], sizeof(chunk)); + return chunk != 0; +} + /* * pg_lfind32_one_by_one_helper * diff --git a/src/test/modules/test_lfind/expected/test_lfind.out b/src/test/modules/test_lfind/expected/test_lfind.out index 1d4b14e7032..4f43a729b51 100644 --- a/src/test/modules/test_lfind/expected/test_lfind.out +++ b/src/test/modules/test_lfind/expected/test_lfind.out @@ -16,6 +16,12 @@ SELECT test_lfind8_le(); (1 row) +SELECT test_lfind8_nonzero(); + test_lfind8_nonzero +--------------------- + +(1 row) + SELECT test_lfind32(); test_lfind32 -------------- diff --git a/src/test/modules/test_lfind/sql/test_lfind.sql b/src/test/modules/test_lfind/sql/test_lfind.sql index 766c640831f..7894fa61e78 100644 --- a/src/test/modules/test_lfind/sql/test_lfind.sql +++ b/src/test/modules/test_lfind/sql/test_lfind.sql @@ -7,4 +7,5 @@ CREATE EXTENSION test_lfind; -- SELECT test_lfind8(); SELECT test_lfind8_le(); +SELECT test_lfind8_nonzero(); SELECT test_lfind32(); diff --git a/src/test/modules/test_lfind/test_lfind--1.0.sql b/src/test/modules/test_lfind/test_lfind--1.0.sql index 81801926ae8..bb72cc6e56a 100644 --- a/src/test/modules/test_lfind/test_lfind--1.0.sql +++ b/src/test/modules/test_lfind/test_lfind--1.0.sql @@ -14,3 +14,7 @@ CREATE FUNCTION test_lfind8() CREATE FUNCTION test_lfind8_le() RETURNS pg_catalog.void AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION test_lfind8_nonzero() + RETURNS pg_catalog.void + AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_lfind/test_lfind.c b/src/test/modules/test_lfind/test_lfind.c index 8dcaa8f9fda..52ae6783ec9 100644 --- a/src/test/modules/test_lfind/test_lfind.c +++ b/src/test/modules/test_lfind/test_lfind.c @@ -115,6 +115,23 @@ test_lfind8_le(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +PG_FUNCTION_INFO_V1(test_lfind8_nonzero); +Datum +test_lfind8_nonzero(PG_FUNCTION_ARGS) +{ + uint8 charbuf[64] = {0}; + + charbuf[32] = 1; + + if (pg_lfind8_nonzero(charbuf, 32)) + elog(ERROR, "pg_lfind8_nonzero() found nonexistent nonzero"); + + if (!pg_lfind8_nonzero(charbuf, 64)) + elog(ERROR, "pg_lfind8_nonzero() did not find existing nonzero"); + + PG_RETURN_VOID(); +} + PG_FUNCTION_INFO_V1(test_lfind32); Datum test_lfind32(PG_FUNCTION_ARGS) -- 2.52.0