PostgreSQL如何解析表达式.
本篇内容介绍了“PostgreSQL如何解析表达式.”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
SQL样例脚本.
testdb=#select1+id,c2fromt_exprwhereid<3;一、数据结构
FmgrInfo
在函数通过fmgr调用前,该结构体持有系统目录(字典)信息,用于检索相关信息.
如果相同的函数将被调用多次,检索只需要完成一次即可,该结构体会缓存多次使用.
/**Thisstructholdsthesystem-cataloginformationthatmustbelookedup*beforeafunctioncanbecalledthroughfmgr.Ifthesamefunctionis*tobecalledmultipletimes,thelookupneedbedoneonlyonceandthe*infostructsavedforre-use.*在函数通过fmgr调用前,该结构体持有系统目录(字典)信息,用于检索相关信息.*如果相同的函数将被调用多次,检索只需要完成一次即可,该结构体会缓存多次使用.**Notethatfn_exprreallyisparse-time-determinedinformationaboutthe*arguments,ratherthanaboutthefunctionitself.Butit'sconvenient*tostoreithereratherthaninFunctionCallInfoData,whereitmightmore*logicallybelong.*注意,fn_expr实际上是关于参数的解析时确定的信息,而不是函数自身.*但fn_expr在这里存储而不是FunctionCallInfoData中存储,因为从逻辑上来说,它就应该属于那.**fn_extraisavailableforusebythecalledfunction;allotherfields*shouldbetreatedasread-onlyafterthestructiscreated.*fn_extra可用于被调用函数的使用;所有其他字段应该在结构体创建后被处理为只读.*/typedefstructFmgrInfo{//指向函数或者将被调用的处理器PGFunctionfn_addr;/*pointertofunctionorhandlertobecalled*///函数的oidOidfn_oid;/*OIDoffunction(NOTofhandler,ifany)*///输入参数的个数,0..FUNC_MAX_ARGSshortfn_nargs;/*numberofinputargs(0..FUNC_MAX_ARGS)*///函数是否严格(strict),输入NULL,输出NULLboolfn_strict;/*functionis"strict"(NULLin=>NULLout)*///函数是否返回集合boolfn_retset;/*functionreturnsaset*///如track_functions>this,则收集统计信息unsignedcharfn_stats;/*collectstatsiftrack_functions>this*///handler使用的额外空间void*fn_extra;/*extraspaceforusebyhandler*///存储fn_extra的内存上下文MemoryContextfn_mcxt;/*memorycontexttostorefn_extrain*///表达式解析树,或者为NULLfmNodePtrfn_expr;/*expressionparsetreeforcall,orNULL*/}FmgrInfo;typedefstructNode*fmNodePtr;
FunctionCallInfoData
该结构体存储了实际传递给fmgr-called函数的参数
/**Thisstructisthedataactuallypassedtoanfmgr-calledfunction.*该结构体存储了实际传递给fmgr-called函数的参数**Thecalledfunctionisexpectedtosetisnull,andpossiblyresultinfoor*fieldsinwhateverresultinfopointsto.Itshouldnotchangeanyother*fields.(Inparticular,scribblingontheargumentarraysisabadidea,*sincesomecallersassumetheycanre-callwiththesamearguments.)*被调用的函数期望设置isnull以及可能的resultinfo或者resultinfo指向的域字段.*不应该改变其他字段.*(特别的,在参数数组上乱写是个坏主意,因为某些调用者假定它们可以使用相同的参数重复调用)*/typedefstructFunctionCallInfoData{//指向该调用的检索信息FmgrInfo*flinfo;/*ptrtolookupinfousedforthiscall*///调用上下文fmNodePtrcontext;/*passinfoaboutcontextofcall*///传递或返回关于结果的特别信息fmNodePtrresultinfo;/*passorreturnextrainfoaboutresult*///函数的collationOidfncollation;/*collationforfunctiontouse*/#defineFIELDNO_FUNCTIONCALLINFODATA_ISNULL4//如结果为NULL,则必须设置为Tboolisnull;/*functionmustsettrueifresultisNULL*///实际传递的参数个数shortnargs;/*#argumentsactuallypassed*/#defineFIELDNO_FUNCTIONCALLINFODATA_ARG6//传递给函数的参数Datumarg[FUNC_MAX_ARGS];/*Argumentspassedtofunction*/#defineFIELDNO_FUNCTIONCALLINFODATA_ARGNULL7//如arg[i]为NULL,则对应的值为Tboolargnull[FUNC_MAX_ARGS];/*Tifarg[i]isactuallyNULL*/}FunctionCallInfoData;/**Allfunctionsthatcanbecalleddirectlybyfmgrmusthavethissignature.*(Otherfunctionscanbecalledbyusingahandlerthatdoeshavethis*signature.)*所有函数可以通过fmgr直接调用,但必须持有签名.*(其他函数可通过使用handler的方式调用,也有此签名)*/typedefstructFunctionCallInfoData*FunctionCallInfo;二、源码解读
ExecInterpExpr
ExecInterpExpr中与表达式求值相关的代码片段如下:
EEO_CASE(EEOP_FUNCEXPR){FunctionCallInfofcinfo=op->d.func.fcinfo_data;Datumd;fcinfo->isnull=false;d=op->d.func.fn_addr(fcinfo);*op->resvalue=d;*op->resnull=fcinfo->isnull;EEO_NEXT();}
如为函数表达式,则从ExecInitFunc初始化的步骤信息中获取统一的调用参数fcinfo,然后通过函数指针(用于封装)调用实际的函数进行表达式求值.通过统一的参数,统一的返回值,做到了实现的统一,体现了面向对象OO中多态的思想,这再次说明了OO是思想,用过程性语言一样可以实现.
int4pl
SQL样例脚本相应的实现函数是int4pl,其实现代码如下:
Datumint4pl(PG_FUNCTION_ARGS){int32arg1=PG_GETARG_INT32(0);int32arg2=PG_GETARG_INT32(1);int32result;if(unlikely(pg_add_s32_overflow(arg1,arg2,&result)))ereport(ERROR,(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),errmsg("integeroutofrange")));PG_RETURN_INT32(result);}/**Ifa+boverflows,returntrue,otherwisestoretheresultofa+binto**result.Thecontentof*resultisimplementationdefinedincaseof*overflow.*/staticinlineboolpg_add_s32_overflow(int32a,int32b,int32*result){#ifdefined(HAVE__BUILTIN_OP_OVERFLOW)return__builtin_add_overflow(a,b,result);#elseint64res=(int64)a+(int64)b;if(res>PG_INT32_MAX||res<PG_INT32_MIN){*result=0x5EED;/*toavoidspuriouswarnings*/returntrue;}*result=(int32)res;returnfalse;#endif}
函数实现相对比较简单,两个数简单相加,如溢出则返回T,否则返回F.
“PostgreSQL如何解析表达式.”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。