这篇文章主要介绍“分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”,在日常操作中,相信很多人在分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、数据结构

Form_pg_language
plpgsql语言定义结构体

/*----------------*pg_languagedefinition.cppturnsthisinto*typedefstructFormData_pg_language*----------------*/CATALOG(pg_language,2612,LanguageRelationId){Oidoid;/*oid*//*Languagename*/NameDatalanname;/*Language'sowner*/OidlanownerBKI_DEFAULT(PGUID);/*Isaprocedurallanguage*/boollanisplBKI_DEFAULT(f);/*PListrusted*/boollanpltrustedBKI_DEFAULT(f);/*Callhandler,ifit'saPL*/OidlanplcallfoidBKI_DEFAULT(0)BKI_LOOKUP(pg_proc);/*Optionalanonymous-blockhandlerfunction*/OidlaninlineBKI_DEFAULT(0)BKI_LOOKUP(pg_proc);/*Optionalvalidationfunction*/OidlanvalidatorBKI_DEFAULT(0)BKI_LOOKUP(pg_proc);#ifdefCATALOG_VARLEN/*variable-lengthfieldsstarthere*//*Accessprivileges*/aclitemlanacl[1]BKI_DEFAULT(_null_);#endif}FormData_pg_language;/*----------------*Form_pg_languagecorrespondstoapointertoatuplewith*theformatofpg_languagerelation.*----------------*/typedefFormData_pg_language*Form_pg_language;

ArrayType

/**Arraysarevarlenaobjects,somustmeetthevarlenaconventionthat*thefirstint32oftheobjectcontainsthetotalobjectsizeinbytes.*BesuretouseVARSIZE()andSET_VARSIZE()toaccessit,though!*Arrays是可变对象集,必须符合varlena约定,即对象的第一个int32包含对象的总大小(以字节为单位)。*但是,一定要确保使用VARSIZE和SET_VARSIZE函数范围该结构体**CAUTION:ifyouchangetheheaderforordinaryarraysyouwillalso*needtochangetheheadersforoidvectorandint2vector!*/typedefstruct{//可变的headerint32vl_len_;/*varlenaheader(donottouchdirectly!)*///维度intndim;/*#ofdimensions*///指向数据的偏移量,如为0则表示没有位图int32dataoffset;/*offsettodata,or0ifnobitmap*///元素类型的OIDOidelemtype;/*elementtypeOID*/}ArrayType;

DefElem

typedefstructDefElem{NodeTagtype;char*defnamespace;/*NULLifunqualifiedname*/char*defname;Node*arg;/*a(Value*)ora(TypeName*)*/DefElemActiondefaction;/*unspecifiedaction,orSET/ADD/DROP*/intlocation;/*tokenlocation,or-1ifunknown*/}DefElem;

FunctionParameter

typedefenumFunctionParameterMode{/*theassignedenumvaluesappearinpg_proc,don'tchange'em!*/FUNC_PARAM_IN='i',/*inputonly*/FUNC_PARAM_OUT='o',/*outputonly*/FUNC_PARAM_INOUT='b',/*both*/FUNC_PARAM_VARIADIC='v',/*variadic(alwaysinput)*/FUNC_PARAM_TABLE='t'/*tablefunctionoutputcolumn*/}FunctionParameterMode;typedefstructFunctionParameter{NodeTagtype;char*name;/*parametername,orNULLifnotgiven*/TypeName*argType;/*TypeNameforparametertype*/FunctionParameterModemode;/*IN/OUT/etc*/Node*defexpr;/*rawdefaultexpr,orNULLifnotgiven*/}FunctionParameter;二、源码解读

/**InterpretthefunctionparameterlistofaCREATEFUNCTIONor*CREATEAGGREGATEstatement.*解析CREATEFUNCTON/CREATEAGGREGATE语句中的参数链表**Inputparameters:*parameters:listofFunctionParameterstructs*languageOid:OIDoffunctionlanguage(InvalidOidifit'sCREATEAGGREGATE)*objtype:neededonlytodetermineerrorhandlingandrequiredresulttype*输入参数:*parameters:FunctionParameter结构体链表*languageOid:语言ID*objtype:确定错误处理时需要,并且需要结果类型**Resultsarestoredintooutputparameters.parameterTypesmustalways*becreated,buttheotherarraysaresettoNULLifnotneeded.*variadicArgTypeissettothevariadicarraytypeifthere'saVARIADIC*parameter(therecanbeonlyone);ortoInvalidOidifnot.*requiredResultTypeissettoInvalidOidiftherearenoOUTparameters,*elseitissettotheOIDoftheimpliedresulttype.*结果存储在输出参数中.必须创建parameterTypes,如不需要其他数组将设置为NULL.*如存在VARIADIC参数(有且仅有一个),variadicArgType将设置为variadic数组类型.*如无OUT参数,则requiredResultType设置为InvalidOid,否则设置为结果类型.*/voidinterpret_function_parameter_list(ParseState*pstate,//解析状态List*parameters,//参数链表OidlanguageOid,//语言OIDObjectTypeobjtype,//对象类型oidvector**parameterTypes,//参数类型oidvectorArrayType**allParameterTypes,//所有的参数类型ArrayType**parameterModes,//参数模式,i/o/b/v/tArrayType**parameterNames,//参数名称List**parameterDefaults,//参数默认值链表Oid*variadicArgType,//variadic参数类型OIDOid*requiredResultType)//结果类型{intparameterCount=list_length(parameters);//参数个数Oid*inTypes;intinCount=0;Datum*allTypes;Datum*paramModes;Datum*paramNames;intoutCount=0;intvarCount=0;boolhave_names=false;boolhave_defaults=false;ListCell*x;inti;*variadicArgType=InvalidOid;/*defaultresult*/*requiredResultType=InvalidOid;/*defaultresult*///输入参数类型inTypes=(Oid*)palloc(parameterCount*sizeof(Oid));//所有参数的类型allTypes=(Datum*)palloc(parameterCount*sizeof(Datum));//paramModes=(Datum*)palloc(parameterCount*sizeof(Datum));//参数名称paramNames=(Datum*)palloc0(parameterCount*sizeof(Datum));*parameterDefaults=NIL;/*Scanthelistandextractdataintoworkarrays*///扫描链表,提前数据到结果数组中i=0;foreach(x,parameters){//函数参数FunctionParameter*fp=(FunctionParameter*)lfirst(x);//类型名称TypeName*t=fp->argType;//是否输入参数boolisinput=false;Oidtoid;//pg_proc元组Typetyptup;//权限检查结果AclResultaclresult;//检索typetupletyptup=LookupTypeName(NULL,t,NULL,false);if(typtup){//if(!((Form_pg_type)GETSTRUCT(typtup))->typisdefined){/*Asabove,harderroriflanguageisSQL*/if(languageOid==SQLlanguageId)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("SQLfunctioncannotacceptshelltype%s",TypeNameToString(t))));/*Wedon'tallowcreatingaggregatesonshelltypeseither*/elseif(objtype==OBJECT_AGGREGATE)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("aggregatecannotacceptshelltype%s",TypeNameToString(t))));elseereport(NOTICE,(errcode(ERRCODE_WRONG_OBJECT_TYPE),errmsg("argumenttype%sisonlyashell",TypeNameToString(t))));}//type的OIDtoid=typeTypeId(typtup);//释放缓存ReleaseSysCache(typtup);}else{//该类型不存在ereport(ERROR,(errcode(ERRCODE_UNDEFINED_OBJECT),errmsg("type%sdoesnotexist",TypeNameToString(t))));toid=InvalidOid;/*keepcompilerquiet*/}//权限检查aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);if(aclresult!=ACLCHECK_OK)aclcheck_error_type(aclresult,toid);if(t->setof){//存在setofif(objtype==OBJECT_AGGREGATE)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("aggregatescannotacceptsetarguments")));elseif(objtype==OBJECT_PROCEDURE)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("procedurescannotacceptsetarguments")));elseereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("functionscannotacceptsetarguments")));}if(objtype==OBJECT_PROCEDURE){//过程对象,不需要OUT参数,只允许inout参数if(fp->mode==FUNC_PARAM_OUT)ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),(errmsg("procedurescannothaveOUTarguments"),errhint("INOUTargumentsarepermitted."))));}/*handleinputparameters*///处理输入参数if(fp->mode!=FUNC_PARAM_OUT&&fp->mode!=FUNC_PARAM_TABLE){//非OUT参数并且不是TABLE参数/*otherinputparameterscan'tfollowaVARIADICparameter*/if(varCount>0)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("VARIADICparametermustbethelastinputparameter")));//写入到输入类型数组中inTypes[inCount++]=toid;isinput=true;}/*handleoutputparameters*///处理输出参数if(fp->mode!=FUNC_PARAM_IN&&fp->mode!=FUNC_PARAM_VARIADIC){if(objtype==OBJECT_PROCEDURE)//存储过程:要求输出结果类型为RECORD*requiredResultType=RECORDOID;elseif(outCount==0)/*savefirstoutputparam'stype*///第一个OID*requiredResultType=toid;outCount++;}if(fp->mode==FUNC_PARAM_VARIADIC){//variadic参数*variadicArgType=toid;varCount++;/*validatevariadicparametertype*///验证variadic参数类型switch(toid){caseANYARRAYOID:caseANYOID:/*okay*/break;default:if(!OidIsValid(get_element_type(toid)))ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("VARIADICparametermustbeanarray")));break;}}//转换为DatumallTypes[i]=ObjectIdGetDatum(toid);//参数类型paramModes[i]=CharGetDatum(fp->mode);if(fp->name&&fp->name[0]){//检查参数名称,参数名称不能重复ListCell*px;/**AsofPostgres9.0wedisallowusingthesamenamefortwo*inputortwooutputfunctionparameters.Dependingonthe*function'slanguage,conflictinginputandoutputnamesmight*bebadtoo,butweleaveittothePLtocomplainifso.*/foreach(px,parameters){//循环判断参数是否重复FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);if(prevfp==fp)break;/*pureindoesn'tconflictwithpureout*///输入和输出不冲突if((fp->mode==FUNC_PARAM_IN||fp->mode==FUNC_PARAM_VARIADIC)&&(prevfp->mode==FUNC_PARAM_OUT||prevfp->mode==FUNC_PARAM_TABLE))continue;if((prevfp->mode==FUNC_PARAM_IN||prevfp->mode==FUNC_PARAM_VARIADIC)&&(fp->mode==FUNC_PARAM_OUT||fp->mode==FUNC_PARAM_TABLE))continue;if(prevfp->name&&prevfp->name[0]&&strcmp(prevfp->name,fp->name)==0)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("parametername\"%s\"usedmorethanonce",fp->name)));}//获取DatumparamNames[i]=CStringGetTextDatum(fp->name);have_names=true;}if(fp->defexpr){Node*def;if(!isinput)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("onlyinputparameterscanhavedefaultvalues")));def=transformExpr(pstate,fp->defexpr,EXPR_KIND_FUNCTION_DEFAULT);def=coerce_to_specific_type(pstate,def,toid,"DEFAULT");assign_expr_collations(pstate,def);/**Makesurenovariablesarereferredto(thisisprobablydead*codenowthatadd_missing_fromishistory).*/if(list_length(pstate->p_rtable)!=0||contain_var_clause(def))ereport(ERROR,(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),errmsg("cannotusetablereferencesinparameterdefaultvalue")));/**transformExpr()shouldhavealreadyrejectedsubqueries,*aggregates,andwindowfunctions,basedontheEXPR_KIND_fora*defaultexpression.**Itcan'treturnaseteither---butcoerce_to_specific_type*alreadycheckedthatforus.**Note:thepointoftheserestrictionsistoensurethatan*expressionthat,onitsface,hasn'tgotsubplans,aggregates,*etccannotsuddenlyhavethemafterfunctiondefaultarguments*areinserted.*/*parameterDefaults=lappend(*parameterDefaults,def);have_defaults=true;}else{if(isinput&&have_defaults)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("inputparametersafteronewithadefaultvaluemustalsohavedefaults")));}i++;}/*Nowconstructtheproperoutputsasneeded*///如需要,构建合适的输出*parameterTypes=buildoidvector(inTypes,inCount);if(outCount>0||varCount>0){//输出参数*allParameterTypes=construct_array(allTypes,parameterCount,OIDOID,sizeof(Oid),true,'i');*parameterModes=construct_array(paramModes,parameterCount,CHAROID,1,true,'c');if(outCount>1)*requiredResultType=RECORDOID;/*otherwisewesetrequiredResultTypecorrectlyabove*/}else{*allParameterTypes=NULL;*parameterModes=NULL;}if(have_names){//指定了参数名称for(i=0;i<parameterCount;i++){if(paramNames[i]==PointerGetDatum(NULL))paramNames[i]=CStringGetTextDatum("");}*parameterNames=construct_array(paramNames,parameterCount,TEXTOID,-1,false,'i');}else*parameterNames=NULL;}三、跟踪分析

测试脚本

createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)returnsrecordas$$declarebeginraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:=%',pi_v1,pi_v2,pio_v3;pio_v3:='pio_v3i/o';po_v4:=100;po_v5:='po_v5out';end;$$LANGUAGEplpgsql;

启动GDB跟踪

(gdb)cContinuing.Breakpoint1,interpret_function_parameter_list(pstate=0x10edc88,parameters=0x10c7d30,languageOid=13581,objtype=OBJECT_FUNCTION,parameterTypes=0x7ffec5c6ea88,allParameterTypes=0x7ffec5c6ea80,parameterModes=0x7ffec5c6ea78,parameterNames=0x7ffec5c6ea70,parameterDefaults=0x7ffec5c6ea68,variadicArgType=0x7ffec5c6ea64,requiredResultType=0x7ffec5c6ea60)atfunctioncmds.c:195195intparameterCount=list_length(parameters);(gdb)

输入参数,语言为pl/pgsql,对象类型是function,存在有5个参数

(gdb)p*pstate$1={parentParseState=0x0,p_sourcetext=0x10c6ed8"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...,p_rtable=0x0,p_joinexprs=0x0,p_joinlist=0x0,p_namespace=0x0,p_lateral_active=false,p_ctenamespace=0x0,p_future_ctes=0x0,p_parent_cte=0x0,p_target_relation=0x0,p_target_rangetblentry=0x0,p_is_insert=false,p_windowdefs=0x0,p_expr_kind=EXPR_KIND_NONE,p_next_resno=1,p_multiassign_exprs=0x0,p_locking_clause=0x0,p_locked_from_parent=false,p_resolve_unknowns=true,p_queryEnv=0x0,p_hasAggs=false,p_hasWindowFuncs=false,p_hasTargetSRFs=false,p_hasSubLinks=false,p_hasModifyingCTE=false,p_last_srf=0x0,p_pre_columnref_hook=0x0,p_post_columnref_hook=0x0,p_paramref_hook=0x0,p_coerce_param_hook=0x0,p_ref_hook_state=0x0}(gdb)(gdb)p*parameters$2={type=T_List,length=5,head=0x10c7d08,tail=0x10c8480}(gdb)

初始化相关变量

(gdb)n197intinCount=0;(gdb)201intoutCount=0;(gdb)202intvarCount=0;(gdb)203boolhave_names=false;(gdb)204boolhave_defaults=false;(gdb)208*variadicArgType=InvalidOid;/*defaultresult*/(gdb)209*requiredResultType=InvalidOid;/*defaultresult*/(gdb)211inTypes=(Oid*)palloc(parameterCount*sizeof(Oid));(gdb)212allTypes=(Datum*)palloc(parameterCount*sizeof(Datum));(gdb)213paramModes=(Datum*)palloc(parameterCount*sizeof(Datum));(gdb)214paramNames=(Datum*)palloc0(parameterCount*sizeof(Datum));(gdb)215*parameterDefaults=NIL;(gdb)218i=0;(gdb)219foreach(x,parameters)(gdb)

开始循环,第一个参数,名称为pi_v1,参数类型为pg_catalog.int4

(gdb)221FunctionParameter*fp=(FunctionParameter*)lfirst(x);(gdb)222TypeName*t=fp->argType;(gdb)223boolisinput=false;(gdb)p*fp$4={type=T_FunctionParameter,name=0x10c7b60"pi_v1",argType=0x10c7c58,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)p*fp->argType$5={type=T_TypeName,names=0x10c7bd0,typeOid=0,setof=false,pct_type=false,typmods=0x0,typemod=-1,arrayBounds=0x0,location=46}(gdb)p*fp->argType->names$6={type=T_List,length=2,head=0x10c7c30,tail=0x10c7ba8}(gdb)p*(Node*)fp->argType->names->head->data.ptr_value$7={type=T_String}(gdb)p*(Value*)fp->argType->names->head->data.ptr_value$8={type=T_String,val={ival=12340746,str=0xbc4e0a"pg_catalog"}}(gdb)p*(Value*)fp->argType->names->head->next->data.ptr_value$9={type=T_String,val={ival=12320664,str=0xbbff98"int4"}}(gdb)p*t$10={type=T_TypeName,names=0x10c7bd0,typeOid=0,setof=false,pct_type=false,typmods=0x0,typemod=-1,arrayBounds=0x0,location=46}(gdb)

获取pg_type中对应type的tuple

(gdb)n228typtup=LookupTypeName(NULL,t,NULL,false);(gdb)229if(typtup)(gdb)p*typtup$11={t_len=176,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=8},t_tableOid=1247,t_data=0x7ff12a2c3c40}(gdb)p*typtup->t_data$12={t_choice={t_heap={t_xmin=1,t_xmax=0,t_field3={t_cid=0,t_xvac=0}},t_datum={datum_len_=1,datum_typmod=0,datum_typeid=0}},t_ctid={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=8},t_infomask2=31,t_infomask=2305,t_hoff=32'',t_bits=0x7ff12a2c3c57"\377\377\377\017"}(gdb)x/16ctyptup->t_data->t_bits0x7ff12a2c3c57:-1'\377'-1'\377'-1'\377'15'\017'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c5f:0'\000'23'\027'0'\000'0'\000'0'\000'105'i'110'n'116't'(gdb)x/64ctyptup->t_data->t_bits0x7ff12a2c3c57:-1'\377'-1'\377'-1'\377'15'\017'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c5f:0'\000'23'\027'0'\000'0'\000'0'\000'105'i'110'n'116't'0x7ff12a2c3c67:52'4'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c6f:0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c77:0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c7f:0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c87:0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0x7ff12a2c3c8f:0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'0'\000'(gdb)(gdb)p*((Form_pg_type)GETSTRUCT(typtup))$14={oid=23,typname={data="int4",'\000'<repeats59times>},typnamespace=11,typowner=10,typlen=4,typbyval=true,typtype=98'b',typcategory=78'N',typispreferred=false,typisdefined=true,typdelim=44',',typrelid=0,typelem=0,typarray=1007,typinput=42,typoutput=43,typreceive=2406,typsend=2407,typmodin=0,typmodout=0,typanalyze=0,typalign=105'i',typstorage=112'p',typnotnull=false,typbasetype=0,typtypmod=-1,typndims=0,typcollation=0}(gdb)

获取type的oid

(gdb)n251toid=typeTypeId(typtup);(gdb)252ReleaseSysCache(typtup);(gdb)263aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);(gdb)ptoid$15=23(gdb)

检查权限

263aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);(gdb)ptoid$15=23(gdb)n264if(aclresult!=ACLCHECK_OK)(gdb)267if(t->setof)(gdb)

处理输入参数

(gdb)pt->setof$16=false(gdb)n283if(objtype==OBJECT_PROCEDURE)(gdb)293if(fp->mode!=FUNC_PARAM_OUT&&fp->mode!=FUNC_PARAM_TABLE)(gdb)296if(varCount>0)(gdb)300inTypes[inCount++]=toid;(gdb)301isinput=true;(gdb)305if(fp->mode!=FUNC_PARAM_IN&&fp->mode!=FUNC_PARAM_VARIADIC)(gdb)314if(fp->mode==FUNC_PARAM_VARIADIC)(gdb)(gdb)n334allTypes[i]=ObjectIdGetDatum(toid);(gdb)336paramModes[i]=CharGetDatum(fp->mode);(gdb)338if(fp->name&&fp->name[0])(gdb)pfp->mode$17=FUNC_PARAM_IN(gdb)n348foreach(px,parameters)(gdb)

判断是否重名

(gdb)n350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)353break;(gdb)

如无重名,设置相关变量,把fp->name的地址写入paramNames指针数组中

373paramNames[i]=CStringGetTextDatum(fp->name);(gdb)374have_names=true;(gdb)377if(fp->defexpr)(gdb)pparamNames[0]$18=17751776

下一个参数

(gdb)n420if(isinput&&have_defaults)(gdb)426i++;(gdb)p*fp->defexprCannotaccessmemoryataddress0x0(gdb)n219foreach(x,parameters)(gdb)221FunctionParameter*fp=(FunctionParameter*)lfirst(x);(gdb)222TypeName*t=fp->argType;(gdb)223boolisinput=false;(gdb)228typtup=LookupTypeName(NULL,t,NULL,false);(gdb)(gdb)n229if(typtup)(gdb)231if(!((Form_pg_type)GETSTRUCT(typtup))->typisdefined)(gdb)251toid=typeTypeId(typtup);(gdb)252ReleaseSysCache(typtup);(gdb)p*((Form_pg_type)GETSTRUCT(typtup))$22={oid=1043,typname={data="varchar",'\000'<repeats56times>},typnamespace=11,typowner=10,typlen=-1,typbyval=false,typtype=98'b',typcategory=83'S',typispreferred=false,typisdefined=true,typdelim=44',',typrelid=0,typelem=0,typarray=1015,typinput=1046,typoutput=1047,typreceive=2432,typsend=2433,typmodin=2915,typmodout=2916,typanalyze=0,typalign=105'i',typstorage=120'x',typnotnull=false,typbasetype=0,typtypmod=-1,typndims=0,typcollation=100}(gdb)n263aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);(gdb)264if(aclresult!=ACLCHECK_OK)(gdb)267if(t->setof)(gdb)283if(objtype==OBJECT_PROCEDURE)(gdb)293if(fp->mode!=FUNC_PARAM_OUT&&fp->mode!=FUNC_PARAM_TABLE)(gdb)296if(varCount>0)(gdb)300inTypes[inCount++]=toid;(gdb)301isinput=true;(gdb)305if(fp->mode!=FUNC_PARAM_IN&&fp->mode!=FUNC_PARAM_VARIADIC)(gdb)314if(fp->mode==FUNC_PARAM_VARIADIC)(gdb)334allTypes[i]=ObjectIdGetDatum(toid);(gdb)336paramModes[i]=CharGetDatum(fp->mode);(gdb)

判断参数是否重复

338if(fp->name&&fp->name[0])(gdb)348foreach(px,parameters)(gdb)pfp->name$23=0x10c7d68"pi_v2"(gdb)pfp->name[0]$24=112'p'(gdb)n350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)p*prevfp$25={type=T_FunctionParameter,name=0x10c7b60"pi_v1",argType=0x10c7c58,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)n355if((fp->mode==FUNC_PARAM_IN||(gdb)357(prevfp->mode==FUNC_PARAM_OUT||(gdb)356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)358prevfp->mode==FUNC_PARAM_TABLE))(gdb)357(prevfp->mode==FUNC_PARAM_OUT||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)363fp->mode==FUNC_PARAM_TABLE))(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)366strcmp(prevfp->name,fp->name)==0)(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)p*prevfp$26={type=T_FunctionParameter,name=0x10c7d68"pi_v2",argType=0x10c7e60,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)p*fp$27={type=T_FunctionParameter,name=0x10c7d68"pi_v2",argType=0x10c7e60,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)n353break;(gdb)373paramNames[i]=CStringGetTextDatum(fp->name);(gdb)374have_names=true;(gdb)377if(fp->defexpr)(gdb)420if(isinput&&have_defaults)(gdb)426i++;(gdb)219foreach(x,parameters)

下一参数,这时候是一个INOUT参数(在IN和OUT数组中均记录)

(gdb)n221FunctionParameter*fp=(FunctionParameter*)lfirst(x);(gdb)222TypeName*t=fp->argType;(gdb)223boolisinput=false;(gdb)228typtup=LookupTypeName(NULL,t,NULL,false);(gdb)229if(typtup)(gdb)231if(!((Form_pg_type)GETSTRUCT(typtup))->typisdefined)(gdb)251toid=typeTypeId(typtup);(gdb)p*((Form_pg_type)GETSTRUCT(typtup))$28={oid=1043,typname={data="varchar",'\000'<repeats56times>},typnamespace=11,typowner=10,typlen=-1,typbyval=false,typtype=98'b',typcategory=83'S',typispreferred=false,typisdefined=true,typdelim=44',',typrelid=0,typelem=0,typarray=1015,typinput=1046,typoutput=1047,typreceive=2432,typsend=2433,typmodin=2915,typmodout=2916,typanalyze=0,typalign=105'i',typstorage=120'x',typnotnull=false,typbasetype=0,typtypmod=-1,typndims=0,typcollation=100}(gdb)n252ReleaseSysCache(typtup);(gdb)263aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);(gdb)264if(aclresult!=ACLCHECK_OK)(gdb)267if(t->setof)(gdb)283if(objtype==OBJECT_PROCEDURE)(gdb)293if(fp->mode!=FUNC_PARAM_OUT&&fp->mode!=FUNC_PARAM_TABLE)(gdb)296if(varCount>0)(gdb)300inTypes[inCount++]=toid;(gdb)301isinput=true;(gdb)305if(fp->mode!=FUNC_PARAM_IN&&fp->mode!=FUNC_PARAM_VARIADIC)(gdb)307if(objtype==OBJECT_PROCEDURE)(gdb)309elseif(outCount==0)/*savefirstoutputparam'stype*/(gdb)310*requiredResultType=toid;(gdb)311outCount++;(gdb)314if(fp->mode==FUNC_PARAM_VARIADIC)(gdb)334allTypes[i]=ObjectIdGetDatum(toid);(gdb)336paramModes[i]=CharGetDatum(fp->mode);(gdb)338if(fp->name&&fp->name[0])(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)p*prevfp$29={type=T_FunctionParameter,name=0x10c7b60"pi_v1",argType=0x10c7c58,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)n355if((fp->mode==FUNC_PARAM_IN||(gdb)356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)p*fp$30={type=T_FunctionParameter,name=0x10c7f38"pio_v3",argType=0x10c8030,mode=FUNC_PARAM_INOUT,defexpr=0x0}(gdb)n355if((fp->mode==FUNC_PARAM_IN||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)363fp->mode==FUNC_PARAM_TABLE))(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)366strcmp(prevfp->name,fp->name)==0)(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)363fp->mode==FUNC_PARAM_TABLE))(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)366strcmp(prevfp->name,fp->name)==0)(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)353break;(gdb)373paramNames[i]=CStringGetTextDatum(fp->name);(gdb)374have_names=true;(gdb)377if(fp->defexpr)(gdb)420if(isinput&&have_defaults)(gdb)426i++;(gdb)219foreach(x,parameters)

下一个参数,OUT参数

(gdb)n221FunctionParameter*fp=(FunctionParameter*)lfirst(x);(gdb)n222TypeName*t=fp->argType;(gdb)223boolisinput=false;(gdb)228typtup=LookupTypeName(NULL,t,NULL,false);(gdb)229if(typtup)(gdb)231if(!((Form_pg_type)GETSTRUCT(typtup))->typisdefined)(gdb)251toid=typeTypeId(typtup);(gdb)p*((Form_pg_type)GETSTRUCT(typtup))$31={oid=23,typname={data="int4",'\000'<repeats59times>},typnamespace=11,typowner=10,typlen=4,typbyval=true,typtype=98'b',typcategory=78'N',typispreferred=false,typisdefined=true,typdelim=44',',typrelid=0,typelem=0,typarray=1007,typinput=42,typoutput=43,typreceive=2406,typsend=2407,typmodin=0,typmodout=0,typanalyze=0,typalign=105'i',typstorage=112'p',typnotnull=false,typbasetype=0,typtypmod=-1,typndims=0,typcollation=0}(gdb)n252ReleaseSysCache(typtup);(gdb)263aclresult=pg_type_aclcheck(toid,GetUserId(),ACL_USAGE);(gdb)264if(aclresult!=ACLCHECK_OK)(gdb)267if(t->setof)(gdb)283if(objtype==OBJECT_PROCEDURE)(gdb)293if(fp->mode!=FUNC_PARAM_OUT&&fp->mode!=FUNC_PARAM_TABLE)(gdb)305if(fp->mode!=FUNC_PARAM_IN&&fp->mode!=FUNC_PARAM_VARIADIC)(gdb)307if(objtype==OBJECT_PROCEDURE)(gdb)309elseif(outCount==0)/*savefirstoutputparam'stype*/(gdb)311outCount++;(gdb)314if(fp->mode==FUNC_PARAM_VARIADIC)(gdb)334allTypes[i]=ObjectIdGetDatum(toid);(gdb)336paramModes[i]=CharGetDatum(fp->mode);(gdb)338if(fp->name&&fp->name[0])(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)p*prevfp$32={type=T_FunctionParameter,name=0x10c7b60"pi_v1",argType=0x10c7c58,mode=FUNC_PARAM_IN,defexpr=0x0}(gdb)p*fp$33={type=T_FunctionParameter,name=0x10c8108"po_v4",argType=0x10c8200,mode=FUNC_PARAM_OUT,defexpr=0x0}(gdb)n356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)364continue;(gdb)n348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)362(fp->mode==FUNC_PARAM_OUT||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)364continue;(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)356fp->mode==FUNC_PARAM_VARIADIC)&&(gdb)355if((fp->mode==FUNC_PARAM_IN||(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)361prevfp->mode==FUNC_PARAM_VARIADIC)&&(gdb)360if((prevfp->mode==FUNC_PARAM_IN||(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)366strcmp(prevfp->name,fp->name)==0)(gdb)365if(prevfp->name&&prevfp->name[0]&&(gdb)348foreach(px,parameters)(gdb)350FunctionParameter*prevfp=(FunctionParameter*)lfirst(px);(gdb)352if(prevfp==fp)(gdb)353break;(gdb)373paramNames[i]=CStringGetTextDatum(fp->name);(gdb)374have_names=true;(gdb)377if(fp->defexpr)(gdb)420if(isinput&&have_defaults)(gdb)426i++;(gdb)219foreach(x,parameters)

下一个参数

......

完成所有参数的解析

219foreach(x,parameters)(gdb)430*parameterTypes=buildoidvector(inTypes,inCount);(gdb)432if(outCount>0||varCount>0)(gdb)434*allParameterTypes=construct_array(allTypes,parameterCount,OIDOID,(gdb)n436*parameterModes=construct_array(paramModes,parameterCount,CHAROID,(gdb)438if(outCount>1)(gdb)439*requiredResultType=RECORDOID;(gdb)p*allTypes$34=23(gdb)pallTypes[4]$35=1043(gdb)n438if(outCount>1)(gdb)448if(have_names)(gdb)450for(i=0;i<parameterCount;i++)(gdb)452if(paramNames[i]==PointerGetDatum(NULL))(gdb)450for(i=0;i<parameterCount;i++)(gdb)452if(paramNames[i]==PointerGetDatum(NULL))(gdb)450for(i=0;i<parameterCount;i++)(gdb)452if(paramNames[i]==PointerGetDatum(NULL))(gdb)450for(i=0;i<parameterCount;i++)(gdb)452if(paramNames[i]==PointerGetDatum(NULL))(gdb)450for(i=0;i<parameterCount;i++)(gdb)452if(paramNames[i]==PointerGetDatum(NULL))(gdb)450for(i=0;i<parameterCount;i++)(gdb)455*parameterNames=construct_array(paramNames,parameterCount,TEXTOID,(gdb)460}(gdb)CreateFunction(pstate=0x10edc88,stmt=0x10c88c8)atfunctioncmds.c:10651065if(stmt->is_procedure)(gdb)

到此,关于“分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!