On Wed, 14 Jan 2026 at 15:26, Roman Khapov <[email protected]> wrote:
>> Hi! Thank you 🙏 for your effort. 0003 looks good to me
>> 
>> -- 
>> Best regards,
>> Kirill Reshke
>
> Hi! Thanks for the patch! 
>
> I'v been reviewing your patch, and noticed there are some code logic
> that handles NULL values, but tests doesn't cover this scenarios.
>
> So, I added simple line at contrib/pageinspect/sql/gin.sql:
>
>  INSERT INTO test1 VALUES (1, ARRAY[11, 111], ARRAY['a', 'b', 'c']);
> +INSERT INTO test1 VALUES (1, ARRAY[NULL, 222], ARRAY['d', NULL]);
>  CREATE INDEX test1_y_idx ON test1 USING gin (y) WITH (fastupdate = off); 
>
> And got unexpected result...
> As far as I understand, we shouldn't get error for the whole
> gin_entrypage_items executions when there are NULL-values columns at index 
> key, but the
> output contains only the next error:
>
>  SELECT * FROM gin_entrypage_items(get_raw_page('test1_y_idx', 1), 
> 'test1_y_idx'::regclass);
> --[ RECORD 1 ]--------------
> -itemoffset | 1
> -downlink   | (2147483664,1)
> -tids       | {"(0,1)"}
> -keys       | y=11
> --[ RECORD 2 ]--------------
> -itemoffset | 2
> -downlink   | (2147483664,1)
> -tids       | {"(0,1)"}
> -keys       | y=111
> -
> +ERROR:  invalid gin entry page tuple at offset 4
>
> Is the NULL values handle correct? 
>

Nice catch!

I agree — the NULL handling seems wrong.
Here's a quick patch to fix it. What do you think?

-- 
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.

diff --git a/contrib/pageinspect/expected/gin.out b/contrib/pageinspect/expected/gin.out
index 5018ef76aa7..b27cc582273 100644
--- a/contrib/pageinspect/expected/gin.out
+++ b/contrib/pageinspect/expected/gin.out
@@ -1,5 +1,6 @@
 CREATE TABLE test1 (x int, y int[], z text[]);
 INSERT INTO test1 VALUES (1, ARRAY[11, 111], ARRAY['a', 'b', 'c']);
+INSERT INTO test1 VALUES (2, NULL, ARRAY['d']);
 CREATE INDEX test1_y_idx ON test1 USING gin (y) WITH (fastupdate = off);
 CREATE INDEX test2_y_z_idx ON test1 USING gin (y, z) WITH (fastupdate = off);
 CREATE INDEX test3_y_z_idx ON test1 USING gin (y, z) WITH (fastupdate = on);
@@ -14,7 +15,7 @@ n_pending_tuples | 0
 n_total_pages    | 2
 n_entry_pages    | 1
 n_data_pages     | 0
-n_entries        | 2
+n_entries        | 3
 version          | 2
 
 SELECT * FROM gin_metapage_info(get_raw_page('test1_y_idx', 1));
@@ -40,6 +41,11 @@ itemoffset | 2
 downlink   | (2147483664,1)
 tids       | {"(0,1)"}
 keys       | y=111
+-[ RECORD 3 ]--------------
+itemoffset | 3
+downlink   | (2147483666,1)
+tids       | {"(0,2)"}
+keys       | y=NULL
 
 SELECT * FROM gin_entrypage_items(get_raw_page('test2_y_z_idx', 1), 'test2_y_z_idx'::regclass);
 -[ RECORD 1 ]--------------
@@ -54,19 +60,29 @@ tids       | {"(0,1)"}
 keys       | y=111
 -[ RECORD 3 ]--------------
 itemoffset | 3
-downlink   | (2147483664,1)
-tids       | {"(0,1)"}
-keys       | z=a
+downlink   | (2147483672,1)
+tids       | {"(0,2)"}
+keys       | y=NULL
 -[ RECORD 4 ]--------------
 itemoffset | 4
 downlink   | (2147483664,1)
 tids       | {"(0,1)"}
-keys       | z=b
+keys       | z=a
 -[ RECORD 5 ]--------------
 itemoffset | 5
 downlink   | (2147483664,1)
 tids       | {"(0,1)"}
+keys       | z=b
+-[ RECORD 6 ]--------------
+itemoffset | 6
+downlink   | (2147483664,1)
+tids       | {"(0,1)"}
 keys       | z=c
+-[ RECORD 7 ]--------------
+itemoffset | 7
+downlink   | (2147483664,1)
+tids       | {"(0,2)"}
+keys       | z=d
 
 INSERT INTO test1 SELECT x, ARRAY[1,10] FROM generate_series(2,10000) x;
 SELECT COUNT(*) > 0
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index 4c0bac683ea..8a51e7b5d9a 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -284,10 +284,6 @@ gin_entrypage_items(PG_FUNCTION_ARGS)
 
 			/* Here we can safely reuse any tuple descriptor. */
 			attrVal = index_getattr(idxtuple, FirstOffsetNumber, tupdesc, &isnull);
-			if (isnull)
-				ereport(ERROR,
-						errcode(ERRCODE_INDEX_CORRUPTED),
-						errmsg("invalid gin entry page tuple at offset %u", offset));
 		}
 		else
 		{
diff --git a/contrib/pageinspect/sql/gin.sql b/contrib/pageinspect/sql/gin.sql
index 1a9eaebeebc..65e791f829c 100644
--- a/contrib/pageinspect/sql/gin.sql
+++ b/contrib/pageinspect/sql/gin.sql
@@ -1,5 +1,6 @@
 CREATE TABLE test1 (x int, y int[], z text[]);
 INSERT INTO test1 VALUES (1, ARRAY[11, 111], ARRAY['a', 'b', 'c']);
+INSERT INTO test1 VALUES (2, NULL, ARRAY['d']);
 CREATE INDEX test1_y_idx ON test1 USING gin (y) WITH (fastupdate = off);
 CREATE INDEX test2_y_z_idx ON test1 USING gin (y, z) WITH (fastupdate = off);
 CREATE INDEX test3_y_z_idx ON test1 USING gin (y, z) WITH (fastupdate = on);

Reply via email to