您好,登錄后才能下訂單哦!
這篇文章主要介紹了PostgreSQL如何實現輸出,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
參照current_date函數,首先通過日志跟蹤其parse tree,重點關注targetList
2019-04-19 17:06:15.591 CST,"xdb","testdb",1693,"[local]",5cb98b16.69d,3,"SELECT",2019-04-19 16:47:18 CST,3/4,0,LOG,00000,"parse tree:"," {QUERY :commandType 1 ... :targetList ( {TARGETENTRY :expr {SQLVALUEFUNCTION :op 0 :type 1082 :typmod -1 :location 7 } :resno 1 :resname current_date :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false } ) ... :stmt_len 27 }
分析源代碼,找到與輸出相關的文件是src/backend/parser/parse_target.c,相關的函數為transformTargetEntry,跟蹤此函數,打印調用棧:
(gdb) bt #0 transformTargetEntry (pstate=0x16afae8, node=0x16af770, expr=0x0, exprKind=EXPR_KIND_SELECT_TARGET, colname=0x0, resjunk=false) at parse_target.c:93 #1 0x000000000060b1f9 in transformTargetList (pstate=0x16afae8, targetlist=0x16af828, exprKind=EXPR_KIND_SELECT_TARGET) at parse_target.c:191 #2 0x00000000005b1e3a in transformSelectStmt (pstate=0x16afae8, stmt=0x16af938) at analyze.c:1243 #3 0x00000000005b03db in transformStmt (pstate=0x16afae8, parseTree=0x16af938) at analyze.c:301 #4 0x00000000005b02b6 in transformOptionalSelectInto (pstate=0x16afae8, parseTree=0x16af938) at analyze.c:246 #5 0x00000000005b0174 in transformTopLevelStmt (pstate=0x16afae8, parseTree=0x16afa50) at analyze.c:196 #6 0x00000000005affcc in parse_analyze (parseTree=0x16afa50, sourceText=0x16aed78 "select current_date from t1;", paramTypes=0x0, numParams=0, queryEnv=0x0) at analyze.c:116 #7 0x00000000008bb78c in pg_analyze_and_rewrite (parsetree=0x16afa50, query_string=0x16aed78 "select current_date from t1;", paramTypes=0x0, numParams=0, queryEnv=0x0) at postgres.c:689 #8 0x00000000008bbddd in exec_simple_query (query_string=0x16aed78 "select current_date from t1;") at postgres.c:1070 #9 0x00000000008c01f3 in PostgresMain (argc=1, argv=0x16dcd28, dbname=0x16dcb90 "testdb", username=0x16aba98 "xdb") at postgres.c:4182 #10 0x000000000081e0ce in BackendRun (port=0x16d0b50) at postmaster.c:4361 #11 0x000000000081d841 in BackendStartup (port=0x16d0b50) at postmaster.c:4033 #12 0x0000000000819c3b in ServerLoop () at postmaster.c:1706 #13 0x00000000008194f1 in PostmasterMain (argc=1, argv=0x16a9a50) at postmaster.c:1379 #14 0x0000000000742993 in main (argc=1, argv=0x16a9a50) at main.c:228
其中FigureColnameInternal函數為current_date設置輸出列名,添加以下代碼,則實現輸出sysdate:
//Hacker : 添加系統列 case SVFOP_ZZ_SYSDATE: *name = "sysdate";//zz_sysdate -> sysdate return 2;
相關源碼解讀
/* * transformTargetEntry() * Transform any ordinary "expression-type" node into a targetlist entry. * This is exported so that parse_clause.c can generate targetlist entries * for ORDER/GROUP BY items that are not already in the targetlist. * 轉換所有普通的"表達式類型expression-type"節點為tagetlist條目. * TargetEntry作為輸出參數以便parse_clause.c * 可以為ORDER/GROUP BY等未在targetlist中的items生成targetlist條目 * * node the (untransformed) parse tree for the value expression. * node 未經變換的值表達式 * * expr the transformed expression, or NULL if caller didn't do it yet. * expr 已轉換的表達式,如調用者未轉換則為NULL * * exprKind expression kind (EXPR_KIND_SELECT_TARGET, etc) * exprKind 表達式類型(如EXPR_KIND_SELECT_TARGET等) * * colname the column name to be assigned, or NULL if none yet set. * colname 分配的列名或者為NULL * * resjunk true if the target should be marked resjunk, ie, it is not * wanted in the final projected tuple. * resjunk 如目標應標記為resjunk,則為T,比如該列不希望投影為最終的元組 */ TargetEntry * transformTargetEntry(ParseState *pstate, Node *node, Node *expr, ParseExprKind exprKind, char *colname, bool resjunk) { /* Transform the node if caller didn't do it already */ //expr為NULL,則轉換之 if (expr == NULL) { /* * If it's a SetToDefault node and we should allow that, pass it * through unmodified. (transformExpr will throw the appropriate * error if we're disallowing it.) */ if (exprKind == EXPR_KIND_UPDATE_SOURCE && IsA(node, SetToDefault)) expr = node; else expr = transformExpr(pstate, node, exprKind); } if (colname == NULL && !resjunk) { /* * Generate a suitable column name for a column without any explicit * 'AS ColumnName' clause. * 如非顯式指定列名(AS ColumnName),產生一個合適的列名 */ colname = FigureColname(node); } //返回TargetEntry return makeTargetEntry((Expr *) expr, (AttrNumber) pstate->p_next_resno++, colname, resjunk); } /* * FigureColname - * if the name of the resulting column is not specified in the target * list, we have to guess a suitable name. The SQL spec provides some * guidance, but not much... * * Note that the argument is the *untransformed* parse tree for the target * item. This is a shade easier to work with than the transformed tree. */ char * FigureColname(Node *node) { char *name = NULL; (void) FigureColnameInternal(node, &name); if (name != NULL) return name; /* default result if we can't guess anything */ return "?column?"; } /* * FigureColnameInternal - * internal workhorse for FigureColname * * Return value indicates strength of confidence in result: * 0 - no information * 1 - second-best name choice * 2 - good name choice * The return value is actually only used internally. * If the result isn't zero, *name is set to the chosen name. */ static int FigureColnameInternal(Node *node, char **name) { int strength = 0; if (node == NULL) return strength; switch (nodeTag(node)) { ... case T_SQLValueFunction: /* make these act like a function or variable */ switch (((SQLValueFunction *) node)->op) { case SVFOP_CURRENT_DATE: *name = "current_date"; return 2; ... //Hacker : 添加系統列 case SVFOP_ZZ_SYSDATE: *name = "sysdate";//zz_sysdate -> sysdate return 2; } break; ... } }
感謝你能夠認真閱讀完這篇文章,希望小編分享的“PostgreSQL如何實現輸出”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。