skip to Main Content

Im using the debugger on apacheAGE to understand better the source code. Ive come across multiple times the List struct and the ListeCell struct, since they are very common in holding and fetching information.

Im having trouble what the ListCell struct holds as information. Everytime I access the values of a ListCell struct through gdb, I get some random values/numbers as a result.
I understand that since ListCell is a union, it may be possible that some of the fields dont make any sense since the memory is overwritten by another field, but still none of the 3 fields make any sense.

What is a way to decode those numbers to understand what information is being used each time?

2

Answers


  1. It appears that you are already familiar with the List struct and ListCell union of postgreSQL.

    While you can view the ListCell content using GDB, please note that for Apache AGE, some of it may not appear meaningful as it is transformed and decoded.

    I am sharing my GDB session below, which I hope could be of use to you.

    Query:

    SELECT * FROM cypher('test', $$
      WITH [1, 2, 3] AS c
      RETURN length(c)
    $$) AS (res agtype);
    

    GDB:

    Breakpoint 1, list_length (l=0x5650776cecc0)
            at ../../../src/include/nodes/pg_list.h:91
        91      return l ? l->length : 0;
        
    

    List:

    (gdb) p l
    $1 = (const List *) 0x5650776cecc0
    
    (gdb) p *l
    $2 = {type = T_List, length = 2, head = 0x5650776cecf8, tail = 0x5650776cec98}
    
    // head: A pointer to an array of ListCell that store the actual data of elements of the list.
    
    (gdb) p l->length
    $3 = 2
    
    // Because our list has 3 elements [1, 2, 3].
    

    ListCell:

    (gdb) p l->head
    $4 = (ListCell *) 0x5650776cecf8
    
    (gdb) p *l->head
    $5 = {data = {ptr_value = 0x5650776cec08, int_value = 2003627016, oid_value = 2003627016}, next = 0x5650776cec98}
    
    (gdb) p l->head->data->ptr_value
    $6 = (void *) 0x5650776cec08
    
    // ptr_value: A void pointer which holds our agtype data. So, we need to typecaste ptr_value to agtype pointer to see its content.
    
    (gdb) p *(agtype*)l->head->data->ptr_value
    $7 = {vl_len_ = 344, root = {header = 0, children = 0x5650776cec10}}
    
    (gdb) p (*(agtype*)l->head->data->ptr_value)->vl_len_
    $8 = 344
    
    // _vl_len is varlena header (int32)
    
    (gdb) p (*(agtype*)l->head->data->ptr_value)->root
    $9 = {header = 0, children = 0x5650776cec10}
    
    // root is agtype_container
    
    (gdb) p *((agtype*)l->head->data->ptr_value)->root->children
    $10 = 2003626560
    
    // children is 28-bit agtentry
            
            
    
    Login or Signup to reply.
  2. The List struct can hold three types of data: pointers, integers or Oid’s.

    In the context of Apache AGE, I’ve seen that the ListCell is used to loop through a List. For example:

    #include "nodes/pg_list.h"
    
    typedef struct ListContentExample {
        int x;
    } ListContentExample;
    
    void loop_through_list(List* list)
    {
        ListContentExample* pointer_to_content;
        ListCell* list_cell;
        
        foreach(list_cell, list)
        {
            pointer_to_content = lfirst(list_cell);
            // do something 
            // ...
        }
    }
    

    As you can see from the example, there are pointers of ListContentExample inside the List, and the ListCell will iterate through the List, receiving the value of each item from the List in each loop iteration.

    You can find more of it here:
    https://doxygen.postgresql.org/unionListCell.html

    and in this file from the source code.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search