On Fri, 09 Jan 2026 at 21:39, Kirill Reshke <[email protected]> wrote:
> On Fri, 9 Jan 2026 at 14:43, Chao Li <[email protected]> wrote:
>>
>> Hi Kirill,
>>
>> Thanks for the patch. I have some small comments:
>>
>> 1 - 0001
>> ```
>> Subject: [PATCH v11 1/2] Preliminary cleanup
>> ```
>>
>> 0001 does some cleanup work, the commit subject "Preliminary cleanup” is a 
>> bit vague. Maybe: pageinspect: clean up ginfuncs.c formatting and 
>> allocations, or pageinspect: cleanup in ginfuncs.c
>>
>
> Yes, the commit message is indeed vague. PFA v12 with reworked commit message.
>
>> 2 - 0001
>> ```
>> Per Peter Eisentraut's patch in thread.
>> ```
>>
>> From what I have seen so far, instead of mention a name, it’s more common to 
>> mention a commit id.
>
> In this case, I am referring to this patch, which is never committed
> anywhere [0]
>
>> 3 - 0001
>> ```
>> Reviewed-by: Andrey Borodin [email protected]
>> ```
>>
>> I think the correct form is: Reviewed-by: Andrey Borodin 
>> <[email protected] <mailto:[email protected]>>
>>
>> I believe the committer will fix that before pushing. But to make 
>> committer’s life easier, you’d better fix that rather than leaving to the 
>> committer.
>>
>> Otherwise, code changes of 0001 is straightforward and LGTM.
>
> Yes, fixed.
>
>> 4 - 0002
>> ```
>> Reviewed-by: Andrey Borodin [email protected]
>> Reviewed-by: Roman Khapov [email protected] 
>> <mailto:[email protected]>
>> ```
>>
>> Add <> to email addresses.
>
> Thanks, fixed.
>
>> 5 - 0002
>> ```
>> +       if (!IS_INDEX(indexRel) || !IS_GIN(indexRel))
>> +               ereport(ERROR,
>> +                               errcode(ERRCODE_WRONG_OBJECT_TYPE),
>> +                               errmsg("\"%s\" is not a %s index",
>> +                                          
>> RelationGetRelationName(indexRel), "GIN"));
>> ```
>>
>> I don’t see a test covering this error case.
>
> Hmm. I dont see any tests for this in nearby pageinspect modules (for
> btree, hash, etc), so I leave it as-is for now. I am not sure the
> value of testing this is worth testing cycles.
>
>> 6 - 0002
>> ```
>> +       /* we only support entry tree in this function, check that */
>> +       if (opaq->flags & GIN_META)
>> +               ereport(ERROR,
>> +                               errcode(ERRCODE_INVALID_PARAMETER_VALUE),
>> +                               errmsg("gin_entrypage_items is unsupported 
>> for metapage"));
>> +
>> +
>> +       if (opaq->flags & (GIN_LIST | GIN_LIST_FULLROW))
>> +               ereport(ERROR,
>> +                               errcode(ERRCODE_INVALID_PARAMETER_VALUE),
>> +                               errmsg("gin_entrypage_items is unsupported 
>> for fast list pages"));
>> +
>> +
>> +       if (opaq->flags & GIN_DATA)
>> +               ereport(ERROR,
>> +                               errcode(ERRCODE_INVALID_PARAMETER_VALUE),
>> +                               errmsg("input page is not a GIN entry tree 
>> page"),
>> +                               errhint("This appears to be a GIN posting 
>> tree page. Please use gin_datapage_items."));
>> ```
>>
>> I just feel the comment is unclear. It’s easy to read it as only for
>> the immediate “if”, but it’s actually for the following 3
>> “if”. Maybe change to: Reject non-entry-tree GIN pages (meta, fast
>> list, and data pages)
>>
>> And the 3 error messages look in inconsistent forms. I would suggest change 
>> the first 2 error messages to:
>>
>> * gin_entrypage_items does not support metapages
>> * gin_entrypage_items does not support fast list pages
>
> Thank you, I changed all 3 error messages to this form and updated tests.
>
>> 7 - 0002
>> ```
>> +               if (!ItemIdIsValid(iid))
>> +                       elog(ERROR, "invalid ItemId”);
>> ```
>>
>> Why this is elog but ereport?
>
> I copied this from gistfuncs.c. However, this is user-facing change,
> so this is indeed something where ereport should be used.
>
>> Also, the error message is too simple. Maybe change to:
>> ```
>> errmsg("invalid ItemId at offset %u", offset))
>> ```
>>
>> 8 - 0002
>> ```
>> +                       /*
>> +                        * here we can safely reuse pg_class's tuple 
>> descriptor.
>> +                        */
>> +                       attrVal = index_getattr(idxtuple, FirstOffsetNumber, 
>> tupdesc, &isnull);
>> ```
>>
>> I think this comment is wrong. tupdesc is the index relation’s descriptor.
>>
>> Also, this can be a one-line comment.
>
> Thank you, I have updated this comment.
>
>> 9 - 0002
>> ```
>> +                               ereport(ERROR,
>> +                                               
>> errcode(ERRCODE_INDEX_CORRUPTED),
>> +                                               errmsg("invalid gin entry 
>> page tuple at offset %d", offset));
>> ```
>>
>> Offset is unsigned, so %u should be used.
>
> Fixed.
>
>> 10 - 0002
>> ```
>> +                       /* Most of this is copied from record_out(). */
>> +                       typoid = TupleDescAttr(tupdesc, indAtt - 
>> 1)->atttypid;
>> ```
>>
>> This comment is confusing. I understand that you meant to say the following 
>> code piece is copied from record_out(). Maybe change to:
>> ```
>> typoid = TupleDescAttr(tupdesc, indAtt - 1)->atttypid;
>> getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
>> value = OidOutputFunctionCall(foutoid, attrVal);
>>
>> /*
>>  * The following value output and quoting logic is copied
>>  * from record_out().
>>  */
>> ```
>
> Applied.
>
>> 11 - 0002
>> ```
>> +                       /* Get list of item pointers from the tuple. */
>> +                       if (GinItupIsCompressed(idxtuple))
>> ```
>>
>> Nit: Get list -> Get a list
>
> Applied.
>
>> Best regards,
>> --
>> Chao Li (Evan)
>> HighGo Software Co., Ltd.
>> https://www.highgo.com/
>>
>>
>>
>>
>
>
>
> PFA v12.
>
> [0] 
> https://www.postgresql.org/message-id/921aa27c-e983-4577-b1dc-3adda3ce79da%40eisentraut.org
>
> -- 
> Best regards,
> Kirill Reshke
>
> [2. text/x-diff; 
> v12-0001-Modernize-coding-in-GIN-pageinspect-functions.patch]...
>
> [3. text/x-diff; 
> v12-0002-GIN-pageinspect-support-for-entry-tree-and-posti.patch]...

Just a few small nitpicks on v12:

1.
+       /* Open the relation */
+       indexRel = index_open(indexRelid, AccessShareLock);

"relation" is technically correct, but "index" feels more precise here.

2.
+       if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
+               ereport(ERROR,
+                               errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                               errmsg("input page is not a valid GIN entry 
tree page"),
+                               errdetail("Expected special size %d, got %d.",
+                                                 (int) 
MAXALIGN(sizeof(GinPageOpaqueData)),
+                                                 PageGetSpecialSize(page)));

Cast the second PageGetSpecialSize(page) to int as well, for consistency.

3.
+                       /* orig tuple reuse is safe */
+
+                       res = index_getattr(idxtuple, FirstOffsetNumber, 
tupdesc, &isnull);

Does "orig tuple" refer to `idxtuple` here? If so, maybe the comment could be
slightly clearer, e.g.:
   
   /* Safe to reuse the original index tuple */

4.
+
+       return (Datum) 0;

Since this appears to be a void-returning function, consider using_RETURN_VOID()
instead — it's the conventional way and slightly more self-documenting.

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


Reply via email to