PostgreSQL 的 target_list分析(一)

首先看 lappend

00128 lappend(List *list, void *datum)
00129 {
00130     Assert(IsPointerList(list));
00131 
00132     if (list == NIL)
00133         list = new_list(T_List);
00134     else
00135         new_tail_cell(list);
00136 
00137     lfirst(list->tail) = datum;
00138     check_list_invariants(list);
00139     return list;
00140 }

再看 list 的定义:

typedef struct List
{
   NodeTag type;
   int length;
   ListCell  *head;
   ListCell  *tail;
} List;

和 ListCell 的定义

struct ListCell
{
    union
    {
         void  *ptr_value;
         int     int_value;
         Oid    oid_value;
    }data;

    ListCell  *next;
}

再看 gram.y 中的 target_list 的定义:

target_list:                                    
            target_el                { $$ = list_make1($1); }        
            | target_list ',' target_el                { $$ = lappend($1, $3); }        
        ;                            

也就是说:target_lsit 中的 lappend 相当于:

$1->tail->data.ptr_value  =  $3

换句话说,$1 是一个 List, $2 是一个 ListCell。 

从最开始 的 target_el 的 listmake1($1) ,可以知道,

刚开始的时候,是List 的 head 指向 ListCell,而ListCell的 ptr_value指针,指向第一个ResTarget。

此ResTarget对应的就是 select id1, id2 中,id1 或 id2 。

然后,如果select 的字段不止一个,就会走到  

target_list  ','   target_el  {$$ = lappend($1, $3); }

也就是说:$1->tail->data.ptr_value  =  $3, 即 第一个ResTarget 已经关联到第二个 ResTarget。

这种情况具体说来:

00108 new_tail_cell(List *list)
00109 {
00110     ListCell   *new_tail;
00111 
00112     new_tail = (ListCell *) palloc(sizeof(*new_tail));
00113     new_tail->next = NULL;
00114 
00115     list->tail->next = new_tail;
00116     list->tail = new_tail;
00117     list->length++;
00118 }

如图:

posted @ 2012-09-10 08:41  健哥的数据花园  阅读(785)  评论(0编辑  收藏  举报