温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PostgreSQL如何实现输出

发布时间:2021-11-09 09:22:18 来源:亿速云 阅读:494 作者:小新 栏目:关系型数据库

这篇文章主要介绍了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如何实现输出”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI