本篇内容主要讲解“分析PostgreSQL的CreateFunction函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析PostgreSQL的CreateFunction函数”吧!

一、数据结构

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;二、源码解读

/**CreateFunction*ExecuteaCREATEFUNCTION(orCREATEPROCEDURE)utilitystatement.*执行CREATEFUNCTION(orCREATEPROCEDURE)语句*/ObjectAddressCreateFunction(ParseState*pstate,CreateFunctionStmt*stmt){char*probin_str;char*prosrc_str;Oidprorettype;boolreturnsSet;char*language;OidlanguageOid;OidlanguageValidator;Node*transformDefElem=NULL;char*funcname;OidnamespaceId;//命名空间ID(schemaID)AclResultaclresult;//权限检查oidvector*parameterTypes;ArrayType*allParameterTypes;ArrayType*parameterModes;ArrayType*parameterNames;List*parameterDefaults;OidvariadicArgType;List*trftypes_list=NIL;ArrayType*trftypes;OidrequiredResultType;boolisWindowFunc,isStrict,security,isLeakProof;charvolatility;ArrayType*proconfig;float4procost;float4prorows;Oidprosupport;HeapTuplelanguageTuple;Form_pg_languagelanguageStruct;List*as_clause;charparallel;/*Convertlistofnamestoanameandnamespace*///转换名称列表为函数名称和命名空间namespaceId=QualifiedNameGetCreationNamespace(stmt->funcname,&funcname);/*Checkwehavecreationrightsintargetnamespace*///检查权限是否足够(是否可以在目标命名空间中创建对象)aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(),ACL_CREATE);if(aclresult!=ACLCHECK_OK)aclcheck_error(aclresult,OBJECT_SCHEMA,get_namespace_name(namespaceId));/*Setdefaultattributes*///设置默认的属性isWindowFunc=false;//是否窗口函数isStrict=false;//是否严格的函数security=false;//安全性isLeakProof=false;//volatility=PROVOLATILE_VOLATILE;proconfig=NULL;procost=-1;/*indicatesnotset*/prorows=-1;/*indicatesnotset*/prosupport=InvalidOid;parallel=PROPARALLEL_UNSAFE;//非并行安全/*Extractnon-defaultattributesfromstmt->optionslist*///从stmt->options链表中抽取非默认属性compute_function_attributes(pstate,stmt->is_procedure,//是否过程?stmt->options,//选项&as_clause,&language,&transformDefElem,&isWindowFunc,&volatility,&isStrict,&security,&isLeakProof,&proconfig,&procost,&prorows,&prosupport,&parallel);/*Lookupthelanguageandvalidatepermissions*///检索语言并验证授权(比如pl/python这类语言,不一定会支持)languageTuple=SearchSysCache1(LANGNAME,PointerGetDatum(language));if(!HeapTupleIsValid(languageTuple))ereport(ERROR,(errcode(ERRCODE_UNDEFINED_OBJECT),errmsg("language\"%s\"doesnotexist",language),(PLTemplateExists(language)?errhint("UseCREATEEXTENSIONtoloadthelanguageintothedatabase."):0)));//语言结构体和OIDlanguageStruct=(Form_pg_language)GETSTRUCT(languageTuple);languageOid=languageStruct->oid;if(languageStruct->lanpltrusted){/*iftrustedlanguage,needUSAGEprivilege*///可信语言,需要USAGE权限AclResultaclresult;aclresult=pg_language_aclcheck(languageOid,GetUserId(),ACL_USAGE);if(aclresult!=ACLCHECK_OK)aclcheck_error(aclresult,OBJECT_LANGUAGE,NameStr(languageStruct->lanname));}else{/*ifuntrustedlanguage,mustbesuperuser*///非可信语言,必须是超级用户才能创建if(!superuser())aclcheck_error(ACLCHECK_NO_PRIV,OBJECT_LANGUAGE,NameStr(languageStruct->lanname));}languageValidator=languageStruct->lanvalidator;ReleaseSysCache(languageTuple);/**Onlysuperuserisallowedtocreateleakprooffunctionsbecause*leakprooffunctionscanseetupleswhichhavenotyetbeenfilteredout*bysecuritybarrierviewsorrowlevelsecuritypolicies.*只有超级用户才允许创建leakproof函数*/if(isLeakProof&&!superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("onlysuperusercandefinealeakprooffunction")));if(transformDefElem){ListCell*lc;foreach(lc,castNode(List,transformDefElem)){//获取类型IDOidtypeid=typenameTypeId(NULL,lfirst_node(TypeName,lc));//基础类型Oidelt=get_base_element_type(typeid);//如有基础类型则用基础类型,否则用类型IDtypeid=elt?elt:typeid;//get_transform_oid(typeid,languageOid,false);//写入到trftypes_list中trftypes_list=lappend_oid(trftypes_list,typeid);}}/**ConvertremainingparametersofCREATEtoformwantedby*ProcedureCreate.*转换CREATE中剩下的参数,用于ProcedureCreate调用*/interpret_function_parameter_list(pstate,stmt->parameters,languageOid,stmt->is_procedure?OBJECT_PROCEDURE:OBJECT_FUNCTION,&parameterTypes,&allParameterTypes,&parameterModes,&parameterNames,&parameterDefaults,&variadicArgType,&requiredResultType);if(stmt->is_procedure){//过程Assert(!stmt->returnType);prorettype=requiredResultType?requiredResultType:VOIDOID;returnsSet=false;}elseif(stmt->returnType){//存在返回类型:显式的RETURNS语句/*explicitRETURNSclause*///获取返回类型compute_return_type(stmt->returnType,languageOid,&prorettype,&returnsSet);if(OidIsValid(requiredResultType)&&prorettype!=requiredResultType)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("functionresulttypemustbe%sbecauseofOUTparameters",format_type_be(requiredResultType))));}elseif(OidIsValid(requiredResultType)){/*defaultRETURNSclausefromOUTparameters*///通过OUT参数作为返回参数prorettype=requiredResultType;returnsSet=false;}else{//没有指定结果类型ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("functionresulttypemustbespecified")));/*Alternativepossibility:defaulttoRETURNSVOID*/prorettype=VOIDOID;returnsSet=false;}if(list_length(trftypes_list)>0){//处理类型链表ListCell*lc;Datum*arr;inti;arr=palloc(list_length(trftypes_list)*sizeof(Datum));i=0;foreach(lc,trftypes_list)arr[i++]=ObjectIdGetDatum(lfirst_oid(lc));trftypes=construct_array(arr,list_length(trftypes_list),OIDOID,sizeof(Oid),true,'i');}else{/*storeSQLNULLinsteadofemptyarray*/trftypes=NULL;}//解析AS语句interpret_AS_clause(languageOid,language,funcname,as_clause,&prosrc_str,&probin_str);/**SetdefaultvaluesforCOSTandROWSdependingonotherparameters;*rejectROWSifit'snotreturnsSet.NB:pg_dumpknowsthesedefault*values,keepitinsyncifyouchangethem.*基于其他参数设置COST和ROWS的默认值*/if(procost<0){/*SQLandPL-languagefunctionsareassumedmoreexpensive*///SQL和PL-XXX函数假定成本更高if(languageOid==INTERNALlanguageId||languageOid==ClanguageId)procost=1;elseprocost=100;}if(prorows<0){if(returnsSet)prorows=1000;elseprorows=0;/*dummyvalueifnotreturnsSet*/}elseif(!returnsSet)ereport(ERROR,(errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg("ROWSisnotapplicablewhenfunctiondoesnotreturnaset")));/**Andnowthatwehavealltheparameters,andknowwe'repermittedtodo*so,goaheadandcreatethefunction.*这时候已准备好所有的参数,并且已验证具备相应的权限,创建函数*/returnProcedureCreate(funcname,namespaceId,stmt->replace,returnsSet,prorettype,GetUserId(),languageOid,languageValidator,prosrc_str,/*convertedtotextlater*/probin_str,/*convertedtotextlater*/stmt->is_procedure?PROKIND_PROCEDURE:(isWindowFunc?PROKIND_WINDOW:PROKIND_FUNCTION),security,isLeakProof,isStrict,volatility,parallel,parameterTypes,PointerGetDatum(allParameterTypes),PointerGetDatum(parameterModes),PointerGetDatum(parameterNames),parameterDefaults,PointerGetDatum(trftypes),PointerGetDatum(proconfig),prosupport,procost,prorows);}三、跟踪分析

测试脚本

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)bCreateFunctionBreakpoint1at0x670b94:filefunctioncmds.c,line929.(gdb)cContinuing.Breakpoint1,CreateFunction(pstate=0x2b02cb8,stmt=0x2add8f8)atfunctioncmds.c:929929Node*transformDefElem=NULL;(gdb)bt#0CreateFunction(pstate=0x2b02cb8,stmt=0x2add8f8)atfunctioncmds.c:929#10x00000000008f61a6inProcessUtilitySlow(pstate=0x2b02cb8,pstmt=0x2addc78,queryString=0x2adbf08"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...,context=PROCESS_UTILITY_TOPLEVEL,params=0x0,queryEnv=0x0,dest=0x2addd70,completionTag=0x7fffef099ca0"")atutility.c:1478#20x00000000008f5069instandard_ProcessUtility(pstmt=0x2addc78,queryString=0x2adbf08"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...,context=PROCESS_UTILITY_TOPLEVEL,params=0x0,queryEnv=0x0,dest=0x2addd70,completionTag=0x7fffef099ca0"")atutility.c:927#30x00000000008f418finProcessUtility(pstmt=0x2addc78,queryString=0x2adbf08"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...,context=PROCESS_UTILITY_TOPLEVEL,params=0x0,queryEnv=0x0,dest=0x2addd70,completionTag=0x7fffef099ca0"")atutility.c:360#40x00000000008f3188inPortalRunUtility(portal=0x2b43278,pstmt=0x2addc78,---Type<return>tocontinue,orq<return>toquit---isTopLevel=true,setHoldSnapshot=false,dest=0x2addd70,completionTag=0x7fffef099ca0"")atpquery.c:1175#50x00000000008f339einPortalRunMulti(portal=0x2b43278,isTopLevel=true,setHoldSnapshot=false,dest=0x2addd70,altdest=0x2addd70,completionTag=0x7fffef099ca0"")atpquery.c:1321#60x00000000008f28d3inPortalRun(portal=0x2b43278,count=9223372036854775807,isTopLevel=true,run_once=true,dest=0x2addd70,altdest=0x2addd70,completionTag=0x7fffef099ca0"")atpquery.c:796#70x00000000008ec882inexec_simple_query(query_string=0x2adbf08"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...)atpostgres.c:1215#80x00000000008f0b04inPostgresMain(argc=1,argv=0x2b09318,dbname=0x2b09160"testdb",username=0x2ad8b28"pg12")atpostgres.c:4247#90x0000000000846fa8inBackendRun(port=0x2afdb10)atpostmaster.c:4437#100x0000000000846786inBackendStartup(port=0x2afdb10)atpostmaster.c:4128#110x00000000008429b4inServerLoop()atpostmaster.c:1704#120x000000000084226ainPostmasterMain(argc=1,argv=0x2ad6ae0)atpostmaster.c:1377#130x0000000000762364inmain(argc=1,argv=0x2ad6ae0)atmain.c:228(gdb)(gdb)

输入参数,pstate是ParseState结构体,stmt类型是CreateFunctionStmt结构体

(gdb)p*pstate$1={parentParseState=0x0,p_sourcetext=0x2adbf08"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)p*stmt$2={type=T_CreateFunctionStmt,is_procedure=false,replace=true,funcname=0x2adcb58,parameters=0x2adcd60,returnType=0x2add580,options=0x2add818}

获取namespace

(gdb)n939List*trftypes_list=NIL;(gdb)957namespaceId=QualifiedNameGetCreationNamespace(stmt->funcname,(gdb)961aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(),ACL_CREATE);(gdb)pnamespaceId$3=2200(gdb)

namespace是public

[local:/data/run/pg12]:5120pg12@testdb=#select*frompg_namespace;oid|nspname|nspowner|nspacl-------+--------------------+----------+-------------------------99|pg_toast|10|12314|pg_temp_1|10|12315|pg_toast_temp_1|10|11|pg_catalog|10|{pg12=UC/pg12,=U/pg12}2200|public|10|{pg12=UC/pg12,=UC/pg12}13291|information_schema|10|{pg12=UC/pg12,=U/pg12}(6rows)

执行权限检查,初始化属性默认值

(gdb)n962if(aclresult!=ACLCHECK_OK)(gdb)paclresult$4=ACLCHECK_OK(gdb)n967isWindowFunc=false;(gdb)968isStrict=false;(gdb)969security=false;(gdb)970isLeakProof=false;(gdb)971volatility=PROVOLATILE_VOLATILE;(gdb)972proconfig=NULL;(gdb)973procost=-1;/*indicatesnotset*/(gdb)974prorows=-1;/*indicatesnotset*/(gdb)975prosupport=InvalidOid;(gdb)976parallel=PROPARALLEL_UNSAFE;(gdb)979compute_function_attributes(pstate,

调用compute_function_attributes从stmt->options链表中抽取非默认属性

(gdb)989languageTuple=SearchSysCache1(LANGNAME,PointerGetDatum(language));(gdb)p*language$33=112'p'(gdb)p*transformDefElemCannotaccessmemoryataddress0x0(gdb)pisWindowFunc$34=false(gdb)pvolatility$35=118'v'(gdb)pisStrict$36=false(gdb)psecurity$37=false(gdb)pisLeakProof$38=false(gdb)pproconfig$39=(ArrayType*)0x0(gdb)pprocost$40=-1(gdb)pprorows$41=-1(gdb)pprosupport$42=0(gdb)pparallel$43=117'u'(gdb)pstmt->options$44=(List*)0x2add818(gdb)p*stmt->options$45={type=T_List,length=2,head=0x2add7f0,tail=0x2add8d0}(gdb)p*(Node*)stmt->options->head->data.ptr_value$46={type=T_DefElem}(gdb)p*(DefElem*)stmt->options->head->data.ptr_value$47={type=T_DefElem,defnamespace=0x0,defname=0xbbf727"as",arg=0x2add760,defaction=DEFELEM_UNSPEC,location=134}(gdb)p*((DefElem*)stmt->options->head->data.ptr_value)->arg$48={type=T_List}

(gdb)p*pstate$5={parentParseState=0x0,p_sourcetext=0x2adbf08"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)x/1024cpstate->p_sourcetext0x2adbf08:99'c'114'r'101'e'97'a'116't'101'e'32''111'o'0x2adbf10:114'r'32''114'r'101'e'112'p'108'l'97'a'99'c'0x2adbf18:101'e'32''102'f'117'u'110'n'99'c'116't'105'i'0x2adbf20:111'o'110'n'32''102'f'117'u'110'n'99'c'95'_'0x2adbf28:116't'101'e'115's'116't'40'('112'p'105'i'95'_'0x2adbf30:118'v'49'1'32''105'i'110'n'32''105'i'110'n'0x2adbf38:116't'44','112'p'105'i'95'_'118'v'50'2'32''0x2adbf40:118'v'97'a'114'r'99'c'104'h'97'a'114'r'44','0x2adbf48:112'p'105'i'111'o'95'_'118'v'51'3'32''105'i'0x2adbf50:110'n'111'o'117'u'116't'32''118'v'97'a'114'r'0x2adbf58:99'c'104'h'97'a'114'r'44','112'p'111'o'95'_'0x2adbf60:118'v'52'4'32''111'o'117'u'116't'32''105'i'0x2adbf68:110'n'116't'44','112'p'111'o'95'_'118'v'53'5'0x2adbf70:32''111'o'117'u'116't'32''118'v'97'a'114'r'0x2adbf78:99'c'104'h'97'a'114'r'41')'10'\n'114'r'101'e'0x2adbf80:116't'117'u'114'r'110'n'115's'32''114'r'101'e'0x2adbf88:99'c'111'o'114'r'100'd'32''10'\n'97'a'115's'0x2adbf90:10'\n'36'$'36'$'10'\n'100'd'101'e'99'c'108'l'0x2adbf98:97'a'114'r'101'e'10'\n'98'b'101'e'103'g'105'i'0x2adbfa0:110'n'10'\n'32''32''114'r'97'a'105'i'115's'---Type<return>tocontinue,orq<return>toquit---0x2adbfa8:101'e'32''110'n'111'o'116't'105'i'99'c'101'e'0x2adbfb0:32''39'\''112'p'105'i'95'_'118'v'49'1'32''0x2adbfb8:58':'61'='32''37'%'44','112'p'105'i'95'_'0x2adbfc0:118'v'50'2'32''58':'61'='32''37'%'44','0x2adbfc8:112'p'105'i'95'_'118'v'51'3'32''58':'61'='0x2adbfd0:32''37'%'39'\''44','112'p'105'i'95'_'118'v'0x2adbfd8:49'1'44','112'p'105'i'95'_'118'v'50'2'44','0x2adbfe0:112'p'105'i'111'o'95'_'118'v'51'3'59';'10'\n'0x2adbfe8:32''32''112'p'105'i'111'o'95'_'118'v'51'3'0x2adbff0:32''58':'61'='32''39'\''112'p'105'i'111'o'0x2adbff8:95'_'118'v'51'3'32''105'i'47'/'111'o'39'\''0x2adc000:59';'10'\n'32''32''112'p'111'o'95'_'118'v'0x2adc008:52'4'32''58':'61'='32''49'1'48'0'48'0'0x2adc010:59';'10'\n'32''32''112'p'111'o'95'_'118'v'0x2adc018:53'5'32''58':'61'='32''39'\''112'p'111'o'0x2adc020:95'_'118'v'53'5'32''111'o'117'u'116't'39'\''0x2adc028:59';'10'\n'101'e'110'n'100'd'59';'10'\n'36'$'0x2adc030:36'$'32''76'L'65'A'78'N'71'G'85'U'65'A'0x2adc038:71'G'69'E'32''112'p'108'l'112'p'103'g'115's'0x2adc040:113'q'108'l'59';'0'\000'0'\000'127'\177'127'\1---Type<return>tocontinue,orq<return>toquit---^CQuit(gdb)(gdb)n

获取language

990if(!HeapTupleIsValid(languageTuple))(gdb)planguageTuple$7=(HeapTuple)0x7fcc407e0bf8(gdb)p*languageTuple$8={t_len=120,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=4},t_tableOid=2612,t_data=0x7fcc407e0c20}(gdb)n997languageStruct=(Form_pg_language)GETSTRUCT(languageTuple);(gdb)998languageOid=languageStruct->oid;(gdb)p*languageStruct$9={oid=13581,lanname={data="plpgsql",'\000'<repeats56times>},lanowner=10,lanispl=true,lanpltrusted=true,lanplcallfoid=13578,laninline=13579,lanvalidator=13580}(gdb)n1000if(languageStruct->lanpltrusted)(gdb)1005aclresult=pg_language_aclcheck(languageOid,GetUserId(),ACL_USAGE);(gdb)1006if(aclresult!=ACLCHECK_OK)(gdb)1018languageValidator=languageStruct->lanvalidator;(gdb)1020ReleaseSysCache(languageTuple);(gdb)1027if(isLeakProof&&!superuser())(gdb)1032if(transformDefElem)(gdb)1056stmt->is_procedure?OBJECT_PROCEDURE:OBJECT_FUNCTION,(gdb)

转换CREATE中剩下的参数,用于ProcedureCreate调用

1053interpret_function_parameter_list(pstate,(gdb)1065if(stmt->is_procedure)(gdb)p*pstate$10={parentParseState=0x0,p_sourcetext=0x2adbf08"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)p*stmt$11={type=T_CreateFunctionStmt,is_procedure=false,replace=true,funcname=0x2adcb58,parameters=0x2adcd60,returnType=0x2add580,options=0x2add818}(gdb)p*stmt->parameters$12={type=T_List,length=5,head=0x2adcd38,tail=0x2add4b0}(gdb)pparameterTypes$13=(oidvector*)0x2bed1a8(gdb)p*parameterTypes$14={vl_len_=144,ndim=1,dataoffset=0,elemtype=26,dim1=3,lbound1=0,values=0x2bed1c0}(gdb)x/144h0x2bed1c00x2bed1c0:23'\027'0'\000'19'\023'0'\000'19'\023'0'\000'126'~'127'\177'0x2bed1d0:127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'0x2bed1e0:127'\177'127'\177'127'\177'127'\177'64'@'0'\000'0'\000'0'\000'0x2bed1f0:44','0'\000'0'\000'0'\000'-96'\240'-80'\260'0'\000'0'\000'0x2bed200:-80'\260'0'\000'1'\001'0'\000'0'\000'0'\000'26'\032'0'\000'0x2bed210:5'\005'0'\000'1'\001'0'\000'23'\027'0'\000'19'\023'0'\000'0x2bed220:19'\023'0'\000'23'\027'0'\000'19'\023'0'\000'126'~'127'\177'0x2bed230:127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'127'\177'0x2bed240:32''0'\000'0'\000'0'\000'29'\035'0'\000'0'\000'0'\000'0x2bed250:-96'\240'-80'\260'0'\000'0'\000'116't'0'\000'1'\001'0'\000'---Type<return>tocontinue,orq<return>toquit---^CQuit(gdb)n1071elseif(stmt->returnType)(gdb)p*stmt->returnType$15={type=T_TypeName,names=0x2add548,typeOid=0,setof=false,pct_type=false,typmods=0x0,typemod=-1,arrayBounds=0x0,location=126}(gdb)p*stmt->returnType->names$16={type=T_List,length=1,head=0x2add520,tail=0x2add520}(gdb)n1074compute_return_type(stmt->returnType,languageOid,(gdb)1076if(OidIsValid(requiredResultType)&&prorettype!=requiredResultType)(gdb)p*prorettypeCannotaccessmemoryataddress0x8c9(gdb)pprorettype$17=2249(gdb)preturnsSet$18=false(gdb)p$19=false(gdb)p*allParameterTypes$20={vl_len_=176,ndim=1,dataoffset=0,elemtype=26}(gdb)pparameterModes$21=(ArrayType*)0x2bed258(gdb)p*parameterModes$22={vl_len_=116,ndim=1,dataoffset=0,elemtype=18}(gdb)p*parameterNames$23={vl_len_=336,ndim=1,dataoffset=0,elemtype=25}(gdb)p*parameterDefaultsCannotaccessmemoryataddress0x0(gdb)p*variadicArgTypeCannotaccessmemoryataddress0x0(gdb)p*requiredResultTypeCannotaccessmemoryataddress0x8c9(gdb)prequiredResultType$24=2249(gdb)n1098if(list_length(trftypes_list)>0)(gdb)ptrftypes_list$25=(List*)0x0(gdb)n1114trftypes=NULL;(gdb)1117interpret_AS_clause(languageOid,language,funcname,as_clause,(gdb)1125if(procost<0)(gdb)p*prosrc_str$26=10'\n'(gdb)p*probin_strCannotaccessmemoryataddress0x0(gdb)pas_clause$27=(List*)0x2add760(gdb)p*as_clause$28={type=T_List,length=1,head=0x2add738,tail=0x2add738}(gdb)p*as_clause->head$29={data={ptr_value=0x2add710,int_value=44947216,oid_value=44947216},next=0x0}(gdb)p(Node*)as_clause->head->data.ptr_value$30=(Node*)0x2add710(gdb)p(Node**)as_clause->head->data.ptr_value$31=(Node**)0x2add710(gdb)p*as_clause->head->data.ptr_valueAttempttodereferenceagenericpointer.(gdb)p(Node*)as_clause->head->data.ptr_value$32=(Node*)0x2add710(gdb)n1128if(languageOid==INTERNALlanguageId||(gdb)1132procost=100;(gdb)1134if(prorows<0)(gdb)1136if(returnsSet)(gdb)1139prorows=0;/*dummyvalueifnotreturnsSet*/(gdb)1150returnProcedureCreate(funcname,(gdb)1160stmt->is_procedure?PROKIND_PROCEDURE:(isWindowFunc?PROKIND_WINDOW:PROKIND_FUNCTION),(gdb)1150returnProcedureCreate(funcname,(gdb)1152stmt->replace,(gdb)1150returnProcedureCreate(funcname,(gdb)1176}(gdb)ProcessUtilitySlow(pstate=0x2b02cb8,pstmt=0x2addc78,queryString=0x2adbf08"createorreplacefunctionfunc_test(pi_v1inint,pi_v2varchar,pio_v3inoutvarchar,po_v4outint,po_v5outvarchar)\nreturnsrecord\nas\n$$\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:="...,context=PROCESS_UTILITY_TOPLEVEL,params=0x0,queryEnv=0x0,dest=0x2addd70,completionTag=0x7fffef099ca0"")atutility.c:14791479break;(gdb)

到此,相信大家对“分析PostgreSQL的CreateFunction函数”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!