博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL 源码解读(174)- 内核研发#2(如何添加系统字段)#2
阅读量:2496 次
发布时间:2019-05-11

本文共 6483 字,大约阅读时间需要 21 分钟。

本节继续处理上一节给出的任务,重点介绍第二部分:输出,实现结果投影列名称命名为sysdate

一、输出

参照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 intFigureColnameInternal(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;        ...    }}

二、参考资料

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/6906/viewspace-2641981/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/6906/viewspace-2641981/

你可能感兴趣的文章
5.学习资源
查看>>
IOS错误总结
查看>>
通过Referer设置来防盗链
查看>>
团队冲刺2.2
查看>>
6.生成器模式-builder
查看>>
ZeroMQ接口函数之 :zmq_socket – 创建ZMQ套接字
查看>>
Win10系列:C#应用控件进阶4
查看>>
std::remove_if
查看>>
前端学HTTP之报文首部
查看>>
设置IIS 兼容32位DLL
查看>>
Python输出格式全总结
查看>>
Python数据结构 将列表作为栈和队列使用
查看>>
树的点分治讲解
查看>>
Leetcode Search a 2D Matrix
查看>>
UVA 10815 Andy's First Dictionary【set】
查看>>
【CUDA 基础】3.2 理解线程束执行的本质(Part I)
查看>>
xshell配色
查看>>
重载、覆盖、隐藏
查看>>
Excel实用知识3
查看>>
Tomcat - 设置 HTTP 基本认证
查看>>