日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

PostgreSQL 的 target_list分析(四)

發布時間:2024/1/17 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PostgreSQL 的 target_list分析(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

根據 <PostgreSQL 數據庫內核分析>200和201頁的說法,

ResTarget 應該指向 ColumnRef 。這是如何實現的呢?

target_list: target_el { $$ = list_make1($1); } | target_list ',' target_el { $$ = lappend($1, $3); } ; target_el: a_expr AS ColLabel { $$ = makeNode(ResTarget); $$->name = $3; $$->indirection = NIL; $$->val = (Node *)$1; $$->location = @1; } /* * We support omitting AS only for column labels that aren't * any known keyword. There is an ambiguity against postfix* operators: is "a ! b" an infix expression, or a postfix * expression and a column label? We prefer to resolve this * as an infix expression, which we accomplish by assigning * IDENT a precedence higher than POSTFIXOP. */ | a_expr IDENT { $$ = makeNode(ResTarget); $$->name = $2; $$->indirection = NIL; $$->val = (Node *)$1; $$->location = @1; } | a_expr { $$ = makeNode(ResTarget); $$->name = NULL; $$->indirection = NIL; $$->val = (Node *)$1; $$->location = @1; } | '*' { ColumnRef *n = makeNode(ColumnRef); n->fields = list_make1(makeNode(A_Star)); n->location = @1; $$ = makeNode(ResTarget); $$->name = NULL; $$->indirection = NIL; $$->val = (Node *)n; $$->location = @1; } ;

?和

a_expr: c_expr
{ $$ = $1; } | a_expr TYPECAST Typename { $$ = makeTypeCast($1, $3, @2); } | a_expr COLLATE any_name { CollateClause *n = makeNode(CollateClause); n->arg = $1; n->collname = $3; n->location = @2; $$ = (Node *) n; }
...

c_expr: columnref { $$ = $1; }| AexprConst { $$ = $1; }| PARAM opt_indirection { ParamRef *p = makeNode(ParamRef); p->number = $1; p->location = @1; if ($2) { A_Indirection *n = makeNode(A_Indirection); n->arg = (Node *) p; n->indirection = check_indirection($2, yyscanner); $$ = (Node *) n; } else $$ = (Node *) p; } | '(' a_expr ')' opt_indirection { if ($4) { A_Indirection *n = makeNode(A_Indirection); n->arg = $2; n->indirection = check_indirection($4, yyscanner); $$ = (Node *)n; } else $$ = $2; } | case_expr { $$ = $1; } | func_expr { $$ = $1; } | select_with_parens %prec UMINUS { SubLink *n = makeNode(SubLink); n->subLinkType = EXPR_SUBLINK; n->testexpr = NULL; n->operName = NIL; n->subselect = $1; n->location = @1; $$ = (Node *)n; } | EXISTS select_with_parens { SubLink *n = makeNode(SubLink); n->subLinkType = EXISTS_SUBLINK; n->testexpr = NULL; n->operName = NIL; n->subselect = $2; n->location = @1; $$ = (Node *)n; } | ARRAY select_with_parens { SubLink *n = makeNode(SubLink); n->subLinkType = ARRAY_SUBLINK; n->testexpr = NULL; n->operName = NIL; n->subselect = $2; n->location = @1; $$ = (Node *)n; } | ARRAY array_expr { A_ArrayExpr *n = (A_ArrayExpr *) $2; Assert(IsA(n, A_ArrayExpr)); /* point outermost A_ArrayExpr to the ARRAY keyword */ n->location = @1; $$ = (Node *)n; } | row { RowExpr *r = makeNode(RowExpr); r->args = $1; r->row_typeid = InvalidOid; /* not analyzed yet */ r->location = @1; $$ = (Node *)r; } ;

這個時候,距離ColumnRef 就已經不遠了。

然后挑選最簡單的情況:

columnref: ColId { $$ = makeColumnRef($1, NIL, @1, yyscanner); } | ColId indirection { $$ = makeColumnRef($1, $2, @1, yyscanner); } ;

查了一下, 原來 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。

可以看出,語法分析是一層套著一層。而整個語法分析的目的,就是逐層地構建一個語法分析樹形結構。

總結

以上是生活随笔為你收集整理的PostgreSQL 的 target_list分析(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。