这篇文章主要介绍了PostgreSQL如何实现输出,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

一、输出

参照current_date函数,首先通过日志跟踪其parse tree,重点关注targetList

2019-04-1917:06:15.591CST,"xdb","testdb",1693,"[local]",5cb98b16.69d,3,"SELECT",2019-04-1916:47:18CST,3/4,0,LOG,00000,"parsetree:","{QUERY:commandType1...:targetList({TARGETENTRY:expr{SQLVALUEFUNCTION:op0:type1082:typmod-1:location7}:resno1:resnamecurrent_date:ressortgroupref0:resorigtbl0:resorigcol0:resjunkfalse})...:stmt_len27}

分析源代码,找到与输出相关的文件是src/backend/parser/parse_target.c,相关的函数为transformTargetEntry,跟踪此函数,打印调用栈:

(gdb)bt#0transformTargetEntry(pstate=0x16afae8,node=0x16af770,expr=0x0,exprKind=EXPR_KIND_SELECT_TARGET,colname=0x0,resjunk=false)atparse_target.c:93#10x000000000060b1f9intransformTargetList(pstate=0x16afae8,targetlist=0x16af828,exprKind=EXPR_KIND_SELECT_TARGET)atparse_target.c:191#20x00000000005b1e3aintransformSelectStmt(pstate=0x16afae8,stmt=0x16af938)atanalyze.c:1243#30x00000000005b03dbintransformStmt(pstate=0x16afae8,parseTree=0x16af938)atanalyze.c:301#40x00000000005b02b6intransformOptionalSelectInto(pstate=0x16afae8,parseTree=0x16af938)atanalyze.c:246#50x00000000005b0174intransformTopLevelStmt(pstate=0x16afae8,parseTree=0x16afa50)atanalyze.c:196#60x00000000005affccinparse_analyze(parseTree=0x16afa50,sourceText=0x16aed78"selectcurrent_datefromt1;",paramTypes=0x0,numParams=0,queryEnv=0x0)atanalyze.c:116#70x00000000008bb78cinpg_analyze_and_rewrite(parsetree=0x16afa50,query_string=0x16aed78"selectcurrent_datefromt1;",paramTypes=0x0,numParams=0,queryEnv=0x0)atpostgres.c:689#80x00000000008bbdddinexec_simple_query(query_string=0x16aed78"selectcurrent_datefromt1;")atpostgres.c:1070#90x00000000008c01f3inPostgresMain(argc=1,argv=0x16dcd28,dbname=0x16dcb90"testdb",username=0x16aba98"xdb")atpostgres.c:4182#100x000000000081e0ceinBackendRun(port=0x16d0b50)atpostmaster.c:4361#110x000000000081d841inBackendStartup(port=0x16d0b50)atpostmaster.c:4033#120x0000000000819c3binServerLoop()atpostmaster.c:1706#130x00000000008194f1inPostmasterMain(argc=1,argv=0x16a9a50)atpostmaster.c:1379#140x0000000000742993inmain(argc=1,argv=0x16a9a50)atmain.c:228

其中FigureColnameInternal函数为current_date设置输出列名,添加以下代码,则实现输出sysdate:

//Hacker:添加系统列caseSVFOP_ZZ_SYSDATE:*name="sysdate";//zz_sysdate->sysdatereturn2;

相关源码解读

/**transformTargetEntry()*Transformanyordinary"expression-type"nodeintoatargetlistentry.*Thisisexportedsothatparse_clause.ccangeneratetargetlistentries*forORDER/GROUPBYitemsthatarenotalreadyinthetargetlist.*转换所有普通的"表达式类型expression-type"节点为tagetlist条目.*TargetEntry作为输出参数以便parse_clause.c*可以为ORDER/GROUPBY等未在targetlist中的items生成targetlist条目**nodethe(untransformed)parsetreeforthevalueexpression.*node未经变换的值表达式**exprthetransformedexpression,orNULLifcallerdidn'tdoityet.*expr已转换的表达式,如调用者未转换则为NULL**exprKindexpressionkind(EXPR_KIND_SELECT_TARGET,etc)*exprKind表达式类型(如EXPR_KIND_SELECT_TARGET等)**colnamethecolumnnametobeassigned,orNULLifnoneyetset.*colname分配的列名或者为NULL**resjunktrueifthetargetshouldbemarkedresjunk,ie,itisnot*wantedinthefinalprojectedtuple.*resjunk如目标应标记为resjunk,则为T,比如该列不希望投影为最终的元组*/TargetEntry*transformTargetEntry(ParseState*pstate,Node*node,Node*expr,ParseExprKindexprKind,char*colname,boolresjunk){/*Transformthenodeifcallerdidn'tdoitalready*///expr为NULL,则转换之if(expr==NULL){/**Ifit'saSetToDefaultnodeandweshouldallowthat,passit*throughunmodified.(transformExprwillthrowtheappropriate*errorifwe'redisallowingit.)*/if(exprKind==EXPR_KIND_UPDATE_SOURCE&&IsA(node,SetToDefault))expr=node;elseexpr=transformExpr(pstate,node,exprKind);}if(colname==NULL&&!resjunk){/**Generateasuitablecolumnnameforacolumnwithoutanyexplicit*'ASColumnName'clause.*如非显式指定列名(ASColumnName),产生一个合适的列名*/colname=FigureColname(node);}//返回TargetEntryreturnmakeTargetEntry((Expr*)expr,(AttrNumber)pstate->p_next_resno++,colname,resjunk);}/**FigureColname-*ifthenameoftheresultingcolumnisnotspecifiedinthetarget*list,wehavetoguessasuitablename.TheSQLspecprovidessome*guidance,butnotmuch...**Notethattheargumentisthe*untransformed*parsetreeforthetarget*item.Thisisashadeeasiertoworkwiththanthetransformedtree.*/char*FigureColname(Node*node){char*name=NULL;(void)FigureColnameInternal(node,&name);if(name!=NULL)returnname;/*defaultresultifwecan'tguessanything*/return"?column?";}/**FigureColnameInternal-*internalworkhorseforFigureColname**Returnvalueindicatesstrengthofconfidenceinresult:*0-noinformation*1-second-bestnamechoice*2-goodnamechoice*Thereturnvalueisactuallyonlyusedinternally.*Iftheresultisn'tzero,*nameissettothechosenname.*/staticintFigureColnameInternal(Node*node,char**name){intstrength=0;if(node==NULL)returnstrength;switch(nodeTag(node)){...caseT_SQLValueFunction:/*maketheseactlikeafunctionorvariable*/switch(((SQLValueFunction*)node)->op){caseSVFOP_CURRENT_DATE:*name="current_date";return2;...//Hacker:添加系统列caseSVFOP_ZZ_SYSDATE:*name="sysdate";//zz_sysdate->sysdatereturn2;}break;...}}

感谢你能够认真阅读完这篇文章,希望小编分享的“PostgreSQL如何实现输出”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!