PostgreSQL 的 target_list分析(六)
进一步分析 ColumnRef:
查了一下, 原来 makeColumnRef 就在 gram.y 里面:
static Node * makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner) { /* * Generate a ColumnRef node, with an A_Indirection node added if there * is any subscripting in the specified indirection list. However, * any field selection at the start of the indirection list must be * transposed into the "fields" part of the ColumnRef node. */ ColumnRef *c = makeNode(ColumnRef); int nfields = 0; ListCell *l; c->location = location; foreach(l, indirection) { if (IsA(lfirst(l), A_Indices)) { A_Indirection *i = makeNode(A_Indirection); if (nfields == 0) { /* easy case - all indirection goes to A_Indirection */ c->fields = list_make1(makeString(colname)); i->indirection = check_indirection(indirection, yyscanner); } else { /* got to split the list in two */ i->indirection = check_indirection(
list_copy_tail(indirection, nfields),yyscanner); indirection = list_truncate(indirection, nfields); c->fields = lcons(makeString(colname), indirection); } i->arg = (Node *) c; return (Node *) i; } else if (IsA(lfirst(l), A_Star)) { /* We only allow '*' at the end of a ColumnRef */ if (lnext(l) != NULL) parser_yyerror("improper use of \"*\""); } nfields++; } /* No subscripting, so all indirection gets added to field list */ c->fields = lcons(makeString(colname), indirection); return (Node *) c; }
这个
ColumnRef *c = makeNode(ColumnRef);
和
c->fields = list_make1(makeString(colname)); 将 字段 赋予了 ColumnRef。
makeString 来自于 value.c:
00047 /* 00048 * makeString 00049 * 00050 * Caller is responsible for passing a palloc'd string. 00051 */ 00052 Value * 00053 makeString(char *str) 00054 { 00055 Value *v = makeNode(Value); 00056 00057 v->type = T_String; 00058 v->val.str = str; 00059 return v; 00060 }
Value 的定义来自于 value.h:
00042 typedef struct Value 00043 { 00044 NodeTag type; /* tag appropriately (eg. T_String) */ 00045 union ValUnion 00046 { 00047 long ival; /* machine integer */ 00048 char *str; /* string */ 00049 } val; 00050 } Value;
再看 pg_list.h 中的 list_make1:
00142 #define list_make1(x1) lcons(x1, NIL)
再看 list.c中的 lcons:
00259 lcons(void *datum, List *list) 00260 { 00261 Assert(IsPointerList(list)); 00262 00263 if (list == NIL) 00264 list = new_list(T_List); 00265 else 00266 new_head_cell(list); 00267 00268 lfirst(list->head) = datum; 00269 check_list_invariants(list); 00270 return list; 00271 } 00272
再看 list==NIL 时的 new_list(T_List):
00063 new_list(NodeTag type) 00064 { 00065 List *new_list; 00066 ListCell *new_head; 00067 00068 new_head = (ListCell *) palloc(sizeof(*new_head)); 00069 new_head->next = NULL; 00070 /* new_head->data is left undefined! */ 00071 00072 new_list = (List *) palloc(sizeof(*new_list)); 00073 new_list->type = type; 00074 new_list->length = 1; 00075 new_list->head = new_head; 00076 new_list->tail = new_head; 00077 00078 return new_list; 00079 }
如下图: