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;
/*----------------------------------------------------------------*ProcedureCreate**Note:allParameterTypes,parameterModes,parameterNames,trftypes,andproconfig*areeitherarraysofthepropertypesorNULL.WedeclarethemDatum,*not"ArrayType*",toavoidimportingarray.hintopg_proc.h.*注意:allParameterTypes,parameterModes,parameterNames,trftypes,andproconfig*要么為相應類型的數組,要么為NULL.這些變量的類型為Datum而不是ArrayType*,*目的是為了避免引入array.h到pg_proc.h中*----------------------------------------------------------------*/ObjectAddressProcedureCreate(constchar*procedureName,OidprocNamespace,boolreplace,boolreturnsSet,OidreturnType,Oidproowner,OidlanguageObjectId,OidlanguageValidator,constchar*prosrc,constchar*probin,charprokind,boolsecurity_definer,boolisLeakProof,boolisStrict,charvolatility,charparallel,oidvector*parameterTypes,DatumallParameterTypes,DatumparameterModes,DatumparameterNames,List*parameterDefaults,Datumtrftypes,Datumproconfig,Oidprosupport,float4procost,float4prorows){Oidretval;//返回值類型intparameterCount;//輸入參數intallParamCount;//所有參數,如無輸出參數,則為0Oid*allParams;//所有參數類型,如無輸出參數,則為NULLchar*paramModes=NULL;//參數類型boolgenericInParam=false;boolgenericOutParam=false;boolanyrangeInParam=false;boolanyrangeOutParam=false;boolinternalInParam=false;boolinternalOutParam=false;OidvariadicType=InvalidOid;Acl*proacl=NULL;//ACL結構體Relationrel;//關系HeapTupletup;//tupleHeapTupleoldtup;//原pg_proctupleboolnulls[Natts_pg_proc];//是否為nullDatumvalues[Natts_pg_proc];//值boolreplaces[Natts_pg_proc];//是否替換NameDataprocname;//名稱TupleDesctupDesc;//tuple描述符boolis_update;//是否替換?ObjectAddressmyself,referenced;inti;//臨時變量Oidtrfid;/**sanitychecks*/Assert(PointerIsValid(prosrc));//參數個數parameterCount=parameterTypes->dim1;//#defineFUNC_MAX_ARGS100if(parameterCount<0||parameterCount>FUNC_MAX_ARGS)ereport(ERROR,(errcode(ERRCODE_TOO_MANY_ARGUMENTS),errmsg_plural("functionscannothavemorethan%dargument","functionscannothavemorethan%darguments",FUNC_MAX_ARGS,FUNC_MAX_ARGS)));/*note:theaboveiscorrect,wedoNOTcountoutputarguments(不計算輸出參數)*//*Deconstructarrayinputs*///重構數組輸入:所有參數類型if(allParameterTypes!=PointerGetDatum(NULL)){/**Weexpectthearraytobea1-DOIDarray;verifythat.Wedon't*needtousedeconstruct_array()sincethearraydataisjustgoing*tolooklikeaCarrayofOIDvalues.*我們期望數組是一維OID數組,需要驗證這一點.*因為數組中的數據看起來像是C語言中的OID數組,隱藏不需要使用deconstruct_array()函數*/ArrayType*allParamArray=(ArrayType*)DatumGetPointer(allParameterTypes);//獲取數組的維數//#defineARR_DIMS(a)\((int*)(((char*)(a))+sizeof(ArrayType)))//#defineARR_NDIM(a)((a)->ndim)//#defineARR_HASNULL(a)((a)->dataoffset!=0)allParamCount=ARR_DIMS(allParamArray)[0];if(ARR_NDIM(allParamArray)!=1||allParamCount<=0||ARR_HASNULL(allParamArray)||ARR_ELEMTYPE(allParamArray)!=OIDOID)elog(ERROR,"allParameterTypesisnota1-DOidarray");//所有參數allParams=(Oid*)ARR_DATA_PTR(allParamArray);Assert(allParamCount>=parameterCount);/*weassumecallergotthecontentsright*/}else{//均為輸入參數,無輸出參數allParamCount=parameterCount;allParams=parameterTypes->values;}if(parameterModes!=PointerGetDatum(NULL)){//參數模式(輸入/輸出等)/**Weexpectthearraytobea1-DCHARarray;verifythat.Wedon't*needtousedeconstruct_array()sincethearraydataisjustgoing*tolooklikeaCarrayofcharvalues.*/ArrayType*modesArray=(ArrayType*)DatumGetPointer(parameterModes);if(ARR_NDIM(modesArray)!=1||ARR_DIMS(modesArray)[0]!=allParamCount||ARR_HASNULL(modesArray)||ARR_ELEMTYPE(modesArray)!=CHAROID)elog(ERROR,"parameterModesisnota1-Dchararray");paramModes=(char*)ARR_DATA_PTR(modesArray);}/**DetectwhetherwehavepolymorphicorINTERNALarguments.Thefirst*loopchecksinputarguments,thesecondoutputarguments.*檢查是否存在多態或者INTERNAL參數.*兩趟循環:第一趟檢查輸入參數,第二趟檢查輸出參數*/for(i=0;i<parameterCount;i++){switch(parameterTypes->values[i]){caseANYARRAYOID:caseANYELEMENTOID:caseANYNONARRAYOID:caseANYENUMOID:genericInParam=true;break;caseANYRANGEOID:genericInParam=true;anyrangeInParam=true;break;caseINTERNALOID:internalInParam=true;break;}}if(allParameterTypes!=PointerGetDatum(NULL)){for(i=0;i<allParamCount;i++){if(paramModes==NULL||paramModes[i]==PROARGMODE_IN||paramModes[i]==PROARGMODE_VARIADIC)continue;/*ignoreinput-onlyparams*/switch(allParams[i]){caseANYARRAYOID:caseANYELEMENTOID:caseANYNONARRAYOID:caseANYENUMOID:genericOutParam=true;break;caseANYRANGEOID:genericOutParam=true;anyrangeOutParam=true;break;caseINTERNALOID:internalOutParam=true;break;}}}/**Donotallowpolymorphicreturntypeunlessatleastoneinputargument*ispolymorphic.ANYRANGEreturntypeisevenstricter:musthavean*ANYRANGEinput(sincewecan'tdeducethespecificrangetypefrom*ANYELEMENT).Also,donotallowreturntypeINTERNALunlessatleast*oneinputargumentisINTERNAL.*至少存在一個多態輸入參數的情況下才允許返回多態類型.*ANYRANGE返回類型更為嚴格:必須含有一個ANYRANGE輸入(因為無法從ANYELEMENT中規約特殊的范圍類型.)*同時,除非至少有一個INTERNAL輸入參數類型,否則不允許返回INTERNAL類型.*/if((IsPolymorphicType(returnType)||genericOutParam)&&!genericInParam)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotdetermineresultdatatype"),errdetail("Afunctionreturningapolymorphictypemusthaveatleastonepolymorphicargument.")));if((returnType==ANYRANGEOID||anyrangeOutParam)&&!anyrangeInParam)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotdetermineresultdatatype"),errdetail("Afunctionreturning\"anyrange\"musthaveatleastone\"anyrange\"argument.")));if((returnType==INTERNALOID||internalOutParam)&&!internalInParam)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("unsafeuseofpseudo-type\"internal\""),errdetail("Afunctionreturning\"internal\"musthaveatleastone\"internal\"argument.")));if(paramModes!=NULL){/**Onlythelastinputparametercanbevariadic;ifitis,saveits*elementtype.Errorsherearejustelogsincecallershouldhave*checkedthisalready.*只有最后一個輸入參數可以是variadic.如是,則存儲元素類型.*/for(i=0;i<allParamCount;i++){switch(paramModes[i]){casePROARGMODE_IN:casePROARGMODE_INOUT:if(OidIsValid(variadicType))elog(ERROR,"variadicparametermustbelast");break;casePROARGMODE_OUT:casePROARGMODE_TABLE:/*okay*/break;casePROARGMODE_VARIADIC:if(OidIsValid(variadicType))elog(ERROR,"variadicparametermustbelast");switch(allParams[i]){caseANYOID:variadicType=ANYOID;break;caseANYARRAYOID:variadicType=ANYELEMENTOID;break;default:variadicType=get_element_type(allParams[i]);if(!OidIsValid(variadicType))elog(ERROR,"variadicparameterisnotanarray");break;}break;default:elog(ERROR,"invalidparametermode'%c'",paramModes[i]);break;}}}/**AllseemsOK;preparethedatatobeinsertedintopg_proc.*檢查完畢,寫入到pg_proc中*///#defineNatts_pg_proc29for(i=0;i<Natts_pg_proc;++i){nulls[i]=false;values[i]=(Datum)0;replaces[i]=true;}//#defineAnum_pg_proc_oid1//#defineAnum_pg_proc_proname2//...//#defineAnum_pg_proc_proacl29namestrcpy(&procname,procedureName);values[Anum_pg_proc_proname-1]=NameGetDatum(&procname);values[Anum_pg_proc_pronamespace-1]=ObjectIdGetDatum(procNamespace);values[Anum_pg_proc_proowner-1]=ObjectIdGetDatum(proowner);values[Anum_pg_proc_prolang-1]=ObjectIdGetDatum(languageObjectId);values[Anum_pg_proc_procost-1]=Float4GetDatum(procost);values[Anum_pg_proc_prorows-1]=Float4GetDatum(prorows);values[Anum_pg_proc_provariadic-1]=ObjectIdGetDatum(variadicType);values[Anum_pg_proc_prosupport-1]=ObjectIdGetDatum(prosupport);values[Anum_pg_proc_prokind-1]=CharGetDatum(prokind);values[Anum_pg_proc_prosecdef-1]=BoolGetDatum(security_definer);values[Anum_pg_proc_proleakproof-1]=BoolGetDatum(isLeakProof);values[Anum_pg_proc_proisstrict-1]=BoolGetDatum(isStrict);values[Anum_pg_proc_proretset-1]=BoolGetDatum(returnsSet);values[Anum_pg_proc_provolatile-1]=CharGetDatum(volatility);values[Anum_pg_proc_proparallel-1]=CharGetDatum(parallel);values[Anum_pg_proc_pronargs-1]=UInt16GetDatum(parameterCount);values[Anum_pg_proc_pronargdefaults-1]=UInt16GetDatum(list_length(parameterDefaults));values[Anum_pg_proc_prorettype-1]=ObjectIdGetDatum(returnType);values[Anum_pg_proc_proargtypes-1]=PointerGetDatum(parameterTypes);if(allParameterTypes!=PointerGetDatum(NULL))values[Anum_pg_proc_proallargtypes-1]=allParameterTypes;elsenulls[Anum_pg_proc_proallargtypes-1]=true;if(parameterModes!=PointerGetDatum(NULL))values[Anum_pg_proc_proargmodes-1]=parameterModes;elsenulls[Anum_pg_proc_proargmodes-1]=true;if(parameterNames!=PointerGetDatum(NULL))values[Anum_pg_proc_proargnames-1]=parameterNames;elsenulls[Anum_pg_proc_proargnames-1]=true;if(parameterDefaults!=NIL)values[Anum_pg_proc_proargdefaults-1]=CStringGetTextDatum(nodeToString(parameterDefaults));elsenulls[Anum_pg_proc_proargdefaults-1]=true;if(trftypes!=PointerGetDatum(NULL))values[Anum_pg_proc_protrftypes-1]=trftypes;elsenulls[Anum_pg_proc_protrftypes-1]=true;values[Anum_pg_proc_prosrc-1]=CStringGetTextDatum(prosrc);if(probin)values[Anum_pg_proc_probin-1]=CStringGetTextDatum(probin);elsenulls[Anum_pg_proc_probin-1]=true;if(proconfig!=PointerGetDatum(NULL))values[Anum_pg_proc_proconfig-1]=proconfig;elsenulls[Anum_pg_proc_proconfig-1]=true;/*proaclwillbedeterminedlater*/rel=table_open(ProcedureRelationId,RowExclusiveLock);tupDesc=RelationGetDescr(rel);/*Checkforpre-existingdefinition*///檢查是否已存在oldtup=SearchSysCache3(PROCNAMEARGSNSP,PointerGetDatum(procedureName),PointerGetDatum(parameterTypes),ObjectIdGetDatum(procNamespace));if(HeapTupleIsValid(oldtup)){//--------已存在/*Thereisone;okaytoreplaceit?*///獲取原記錄(pg_proc記錄)Form_pg_procoldproc=(Form_pg_proc)GETSTRUCT(oldtup);Datumproargnames;boolisnull;constchar*dropcmd;if(!replace)ereport(ERROR,(errcode(ERRCODE_DUPLICATE_FUNCTION),errmsg("function\"%s\"alreadyexistswithsameargumenttypes",procedureName)));if(!pg_proc_ownercheck(oldproc->oid,proowner))aclcheck_error(ACLCHECK_NOT_OWNER,OBJECT_FUNCTION,procedureName);/*Notokaytochangeroutinekind*///不能改變類型(如原來是proc,那么創建同名func是不行的)if(oldproc->prokind!=prokind)ereport(ERROR,(errcode(ERRCODE_WRONG_OBJECT_TYPE),errmsg("cannotchangeroutinekind"),(oldproc->prokind==PROKIND_AGGREGATE?errdetail("\"%s\"isanaggregatefunction.",procedureName):oldproc->prokind==PROKIND_FUNCTION?errdetail("\"%s\"isafunction.",procedureName):oldproc->prokind==PROKIND_PROCEDURE?errdetail("\"%s\"isaprocedure.",procedureName):oldproc->prokind==PROKIND_WINDOW?errdetail("\"%s\"isawindowfunction.",procedureName):0)));dropcmd=(prokind==PROKIND_PROCEDURE?"DROPPROCEDURE":prokind==PROKIND_AGGREGATE?"DROPAGGREGATE":"DROPFUNCTION");/**Notokaytochangethereturntypeoftheexistingproc,since*existingrules,views,etcmaydependonthereturntype.*改變返回類型也是不行的,因為現存的規則\視圖等等可能依賴返回類型.**Incaseofaprocedure,achangingreturntypemeansthatwhether*theprocedurehasoutputparameterswaschanged.Sincethereisno*uservisiblereturntype,weproduceamorespecificerrormessage.*如為存儲過程,改變返回類型意味著過程已有的輸出參數已改變.*由于存在非用戶可見返回類型,隱藏產生更為詳盡的錯誤信息.*/if(returnType!=oldproc->prorettype||returnsSet!=oldproc->proretset)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),prokind==PROKIND_PROCEDURE?errmsg("cannotchangewhetheraprocedurehasoutputparameters"):errmsg("cannotchangereturntypeofexistingfunction"),/**translator:first%sisDROPFUNCTION,DROPPROCEDURE,orDROP*AGGREGATE*/errhint("Use%s%sfirst.",dropcmd,format_procedure(oldproc->oid))));/**IfitreturnsRECORD,checkforpossiblechangeofrecordtype*impliedbyOUTparameters*如果返回RECORD類型,檢查使用OUT參數指明的可能的record類型變化.*/if(returnType==RECORDOID){//返回RECORD類型TupleDescolddesc;TupleDescnewdesc;olddesc=build_function_result_tupdesc_t(oldtup);newdesc=build_function_result_tupdesc_d(prokind,allParameterTypes,parameterModes,parameterNames);if(olddesc==NULL&&newdesc==NULL)/*ok,bothareruntime-definedRECORDs*/;elseif(olddesc==NULL||newdesc==NULL||!equalTupleDescs(olddesc,newdesc))ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotchangereturntypeofexistingfunction"),errdetail("RowtypedefinedbyOUTparametersisdifferent."),/*translator:first%sisDROPFUNCTIONorDROPPROCEDURE*/errhint("Use%s%sfirst.",dropcmd,format_procedure(oldproc->oid))));}/**Iftherewereanynamedinputparameters,checktomakesurethe*nameshavenotbeenchanged,asthiscouldbreakexistingcalls.We*allowaddingnamestoformerlyunnamedparameters,though.*如存在已命名的輸入參數,確保名稱沒有變更,否則會破壞現存的調用.*但允許添加名稱到未命名的參數中.*/proargnames=SysCacheGetAttr(PROCNAMEARGSNSP,oldtup,Anum_pg_proc_proargnames,&isnull);if(!isnull){Datumproargmodes;char**old_arg_names;char**new_arg_names;intn_old_arg_names;intn_new_arg_names;intj;proargmodes=SysCacheGetAttr(PROCNAMEARGSNSP,oldtup,Anum_pg_proc_proargmodes,&isnull);if(isnull)proargmodes=PointerGetDatum(NULL);/*justtobesure*/n_old_arg_names=get_func_input_arg_names(proargnames,proargmodes,&old_arg_names);n_new_arg_names=get_func_input_arg_names(parameterNames,parameterModes,&new_arg_names);for(j=0;j<n_old_arg_names;j++){if(old_arg_names[j]==NULL)continue;if(j>=n_new_arg_names||new_arg_names[j]==NULL||strcmp(old_arg_names[j],new_arg_names[j])!=0)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotchangenameofinputparameter\"%s\"",old_arg_names[j]),/*translator:first%sisDROPFUNCTIONorDROPPROCEDURE*/errhint("Use%s%sfirst.",dropcmd,format_procedure(oldproc->oid))));}}/**Ifthereareexistingdefaults,checkcompatibility:redefinition*mustnotremoveanydefaultsnorchangetheirtypes.(Removinga*defaultmightcauseafunctiontofailtosatisfyanexistingcall.*Changingtypewouldonlybepossibleiftheassociatedparameteris*polymorphic,andinsuchcasesachangeofdefaulttypemightalter*theresolvedoutputtypeofexistingcalls.)*存在defaults(默認參數),檢查兼容性:*重新定義不應刪去已有的默認定義或者改變類型,否則會破壞現存的調用.*/if(oldproc->pronargdefaults!=0){//默認值判斷Datumproargdefaults;List*oldDefaults;ListCell*oldlc;ListCell*newlc;if(list_length(parameterDefaults)<oldproc->pronargdefaults)ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotremoveparameterdefaultsfromexistingfunction"),/*translator:first%sisDROPFUNCTIONorDROPPROCEDURE*/errhint("Use%s%sfirst.",dropcmd,format_procedure(oldproc->oid))));proargdefaults=SysCacheGetAttr(PROCNAMEARGSNSP,oldtup,Anum_pg_proc_proargdefaults,&isnull);Assert(!isnull);oldDefaults=castNode(List,stringToNode(TextDatumGetCString(proargdefaults)));Assert(list_length(oldDefaults)==oldproc->pronargdefaults);/*newlistcanhavemoredefaultsthanold,advanceover'em*/newlc=list_head(parameterDefaults);for(i=list_length(parameterDefaults)-oldproc->pronargdefaults;i>0;i--)newlc=lnext(newlc);foreach(oldlc,oldDefaults){Node*oldDef=(Node*)lfirst(oldlc);Node*newDef=(Node*)lfirst(newlc);if(exprType(oldDef)!=exprType(newDef))ereport(ERROR,(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),errmsg("cannotchangedatatypeofexistingparameterdefaultvalue"),/*translator:first%sisDROPFUNCTIONorDROPPROCEDURE*/errhint("Use%s%sfirst.",dropcmd,format_procedure(oldproc->oid))));newlc=lnext(newlc);}}/**Donotchangeexistingoid,ownershiporpermissions,either.Note*dependency-updatecodebelowhastoagreewiththisdecision.*不改變現有的oid,宿主或者權限等.*注意下面的依賴更新代碼必須遵循這一約定.*/replaces[Anum_pg_proc_oid-1]=false;replaces[Anum_pg_proc_proowner-1]=false;replaces[Anum_pg_proc_proacl-1]=false;/*Okay,doit...*/tup=heap_modify_tuple(oldtup,tupDesc,values,nulls,replaces);CatalogTupleUpdate(rel,&tup->t_self,tup);ReleaseSysCache(oldtup);is_update=true;}else{//--------------不存在/*Creatinganewprocedure*///創建新的過程OidnewOid;/*First,getdefaultpermissionsandsetupproacl*///首先:獲取默認的權限并設置proaclproacl=get_user_default_acl(OBJECT_FUNCTION,proowner,procNamespace);if(proacl!=NULL)values[Anum_pg_proc_proacl-1]=PointerGetDatum(proacl);elsenulls[Anum_pg_proc_proacl-1]=true;//獲取新的OIDnewOid=GetNewOidWithIndex(rel,ProcedureOidIndexId,Anum_pg_proc_oid);//設置pg_proc中的OIDvalues[Anum_pg_proc_oid-1]=ObjectIdGetDatum(newOid);//構造tupletup=heap_form_tuple(tupDesc,values,nulls);//執行插入操作CatalogTupleInsert(rel,tup);is_update=false;}//獲取pg_proc結構體retval=((Form_pg_proc)GETSTRUCT(tup))->oid;/**Createdependenciesforthenewfunction.Ifweareupdatingan*existingfunction,firstdeleteanyexistingpg_dependentries.*(However,sincewearenotchangingownershiporpermissions,the*shareddependenciesdo*not*needtochange,andweleavethemalone.)*創建新函數的依賴.*如正在更新現存的函數,首先刪除現存的pg_depend條目.*/if(is_update)//刪除依賴deleteDependencyRecordsFor(ProcedureRelationId,retval,true);myself.classId=ProcedureRelationId;myself.objectId=retval;myself.objectSubId=0;/*dependencyonnamespace*///依賴:namespacereferenced.classId=NamespaceRelationId;referenced.objectId=procNamespace;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);/*dependencyonimplementationlanguage*///依賴:語言referenced.classId=LanguageRelationId;referenced.objectId=languageObjectId;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);/*dependencyonreturntype*///依賴:返回類型referenced.classId=TypeRelationId;referenced.objectId=returnType;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);/*dependencyontransformusedbyreturntype,ifany*///依賴:返回類型的轉換規則if((trfid=get_transform_oid(returnType,languageObjectId,true))){referenced.classId=TransformRelationId;referenced.objectId=trfid;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);}/*dependencyonparametertypes*///依賴:參數類型for(i=0;i<allParamCount;i++){referenced.classId=TypeRelationId;referenced.objectId=allParams[i];referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);/*dependencyontransformusedbyparametertype,ifany*/if((trfid=get_transform_oid(allParams[i],languageObjectId,true))){referenced.classId=TransformRelationId;referenced.objectId=trfid;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);}}/*dependencyonparameterdefaultexpressions*///依賴:默認表達式if(parameterDefaults)recordDependencyOnExpr(&myself,(Node*)parameterDefaults,NIL,DEPENDENCY_NORMAL);/*dependencyonsupportfunction,ifany*///依賴:支持的函數if(OidIsValid(prosupport)){referenced.classId=ProcedureRelationId;referenced.objectId=prosupport;referenced.objectSubId=0;recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);}/*dependencyonowner*///依賴:ownerif(!is_update)recordDependencyOnOwner(ProcedureRelationId,retval,proowner);/*dependencyonanyrolesmentionedinACL*///依賴:ACL中標明的角色if(!is_update)recordDependencyOnNewAcl(ProcedureRelationId,retval,0,proowner,proacl);/*dependencyonextension*///依賴:擴展recordDependencyOnCurrentExtension(&myself,is_update);heap_freetuple(tup);/*Postcreationhookfornewfunction*///調用對象創建后的鉤子函數InvokeObjectPostCreateHook(ProcedureRelationId,retval,0);//關閉pg_proctable_close(rel,RowExclusiveLock);/*Verifyfunctionbody*///驗證函數bodyif(OidIsValid(languageValidator)){ArrayType*set_items=NULL;intsave_nestlevel=0;/*Advancecommandcountersonewtuplecanbeseenbyvalidator*///增加命令計數CommandCounterIncrement();/**Setper-functionconfigurationparameterssothatthevalidationis*donewiththeenvironmentthefunctionexpects.However,if*check_function_bodiesisoff,wedon'tdothis,becausethatwould*createdumporderinghazardsthatpg_dumpdoesn'tknowhowtodeal*with.(Forexample,aSETclausemightrefertoanot-yet-created*textsearchconfiguration.)Thismeansthatthevalidator*shouldn'tcomplainaboutanythingthatmightdependonaGUC*parameterwhencheck_function_bodiesisoff.*/if(check_function_bodies){//檢查函數體//獲取函數設定的參數set_items=(ArrayType*)DatumGetPointer(proconfig);if(set_items)/*NeedanewGUCnestinglevel*/{save_nestlevel=NewGUCNestLevel();ProcessGUCArray(set_items,(superuser()?PGC_SUSET:PGC_USERSET),PGC_S_SESSION,GUC_ACTION_SAVE);}}//調用語言校驗器OidFunctionCall1(languageValidator,ObjectIdGetDatum(retval));if(set_items)AtEOXact_GUC(true,save_nestlevel);}returnmyself;}
測試腳本
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)bProcedureCreateBreakpoint1at0x5bd665:filepg_proc.c,line99.(gdb)cContinuing.Breakpoint1,ProcedureCreate(procedureName=0x1173ab0"func_test",procNamespace=2200,replace=true,returnsSet=false,returnType=2249,proowner=10,languageObjectId=13581,languageValidator=13580,prosrc=0x11745c8"\ndeclare\nbegin\nraisenotice'pi_v1:=%,pi_v2:=%,pi_v3:=%',pi_v1,pi_v2,pio_v3;\npio_v3:='pio_v3i/o';\npo_v4:=100;\npo_v5:='po_v5out';\nend;\n",probin=0x0,prokind=102'f',security_definer=false,isLeakProof=false,isStrict=false,volatility=118'v',parallel=117'u',parameterTypes=0x119a3d0,allParameterTypes=18458616,parameterModes=18457432,parameterNames=18456792,parameterDefaults=0x0,trftypes=0,proconfig=0,prosupport=0,procost=100,prorows=0)atpg_proc.c:9999char*paramModes=NULL;(gdb)
輸入參數
[local:/data/run/pg12]:5120pg12@testdb=#\dpg_typeTable"pg_catalog.pg_type"Column|Type|Collation|Nullable|Default----------------+--------------+-----------+----------+---------oid|oid||notnull|typname|name||notnull|typnamespace|oid||notnull|typowner|oid||notnull|typlen|smallint||notnull|typbyval|boolean||notnull|typtype|"char"||notnull|typcategory|"char"||notnull|typispreferred|boolean||notnull|typisdefined|boolean||notnull|typdelim|"char"||notnull|typrelid|oid||notnull|typelem|oid||notnull|typarray|oid||notnull|typinput|regproc||notnull|typoutput|regproc||notnull|typreceive|regproc||notnull|[local:/data/run/pg12]:5120pg12@testdb=#selectoid,typnamefrompg_typewhereoid=2249;oid|typname------+---------2249|record(1row)[local:/data/run/pg12]:5120pg12@testdb=#\dpg_namespaceTable"pg_catalog.pg_namespace"Column|Type|Collation|Nullable|Default----------+-----------+-----------+----------+---------oid|oid||notnull|nspname|name||notnull|nspowner|oid||notnull|nspacl|aclitem[]|||Indexes:"pg_namespace_nspname_index"UNIQUE,btree(nspname)"pg_namespace_oid_index"UNIQUE,btree(oid)[local:/data/run/pg12]:5120pg12@testdb=#selectoid,nspnamefrompg_namespacewhereoid=2200;oid|nspname------+---------2200|public(1row)[local:/data/run/pg12]:5120pg12@testdb=#\dpg_userView"pg_catalog.pg_user"Column|Type|Collation|Nullable|Default--------------+--------------------------+-----------+----------+---------usename|name|||usesysid|oid|||usecreatedb|boolean|||usesuper|boolean|||userepl|boolean|||usebypassrls|boolean|||passwd|text|||valuntil|timestampwithtimezone|||useconfig|text[]|C||[local:/data/run/pg12]:5120pg12@testdb=#selectusename,usesysidfrompg_userwhereusesysid=10;usename|usesysid---------+----------pg12|10(1row)[local:/data/run/pg12]:5120pg12@testdb=#\dpg_languageTable"pg_catalog.pg_language"Column|Type|Collation|Nullable|Default---------------+-----------+-----------+----------+---------oid|oid||notnull|lanname|name||notnull|lanowner|oid||notnull|lanispl|boolean||notnull|lanpltrusted|boolean||notnull|lanplcallfoid|oid||notnull|laninline|oid||notnull|lanvalidator|oid||notnull|lanacl|aclitem[]|||Indexes:"pg_language_name_index"UNIQUE,btree(lanname)"pg_language_oid_index"UNIQUE,btree(oid)[local:/data/run/pg12]:5120pg12@testdb=#selectoid,lanname,lanownerfrompg_languagewhereoid=13581;oid|lanname|lanowner-------+---------+----------13581|plpgsql|10(1row)
初始化本地臨時變量
99char*paramModes=NULL;(gdb)n100boolgenericInParam=false;(gdb)101boolgenericOutParam=false;(gdb)102boolanyrangeInParam=false;(gdb)103boolanyrangeOutParam=false;(gdb)104boolinternalInParam=false;(gdb)105boolinternalOutParam=false;(gdb)106OidvariadicType=InvalidOid;(gdb)107Acl*proacl=NULL;(gdb)125Assert(PointerIsValid(prosrc));(gdb)127parameterCount=parameterTypes->dim1;(gdb)
獲取參數個數(3個輸入參數,類型為26-oid,數據類型為int4,varchar,varchar)
(gdb)n128if(parameterCount<0||parameterCount>FUNC_MAX_ARGS)(gdb)pparameterCount$1=3(gdb)p*parameterTypes$2={vl_len_=144,ndim=1,dataoffset=0,elemtype=26,dim1=3,lbound1=0,values=0x119a3e8}(gdb)(gdb)p*parameterTypes->values$3=23(gdb)pparameterTypes->values[1]$4=1043(gdb)pparameterTypes->values[2]$5=1043(gdb)###[local:/data/run/pg12]:5120pg12@testdb=#selectoid,typnamefrompg_typewhereoid=26;oid|typname-----+---------26|oid(1row)[local:/data/run/pg12]:5120pg12@testdb=#selectoid,typnamefrompg_typewhereoidin(23,1043);oid|typname------+---------23|int41043|varchar(2rows)
重構數組輸入:所有參數類型
(gdb)n138if(allParameterTypes!=PointerGetDatum(NULL))(gdb)145ArrayType*allParamArray=(ArrayType*)DatumGetPointer(allParameterTypes);(gdb)147allParamCount=ARR_DIMS(allParamArray)[0];(gdb)148if(ARR_NDIM(allParamArray)!=1||(gdb)150ARR_HASNULL(allParamArray)||(gdb)149allParamCount<=0||(gdb)151ARR_ELEMTYPE(allParamArray)!=OIDOID)(gdb)150ARR_HASNULL(allParamArray)||(gdb)153allParams=(Oid*)ARR_DATA_PTR(allParamArray);(gdb)154Assert(allParamCount>=parameterCount);(gdb)p*allParamArray$6={vl_len_=176,ndim=1,dataoffset=0,elemtype=26}(gdb)pallParamArray[1]$7={vl_len_=5,ndim=1,dataoffset=23,elemtype=1043}(gdb)pallParamCount$8=5(gdb)p*ARR_DIMS(allParamArray)$9=5(gdb)pallParamArray[2]$10={vl_len_=1043,ndim=23,dataoffset=1043,elemtype=2139062142}(gdb)pallParamArray[3]$11={vl_len_=2139062143,ndim=2139062143,dataoffset=2139062143,elemtype=2139062143}(gdb)n163if(parameterModes!=PointerGetDatum(NULL))(gdb)
處理參數模式:參數模式(輸入/輸出等),分別是i,i,b,o,o
(gdb)n170ArrayType*modesArray=(ArrayType*)DatumGetPointer(parameterModes);(gdb)172if(ARR_NDIM(modesArray)!=1||(gdb)173ARR_DIMS(modesArray)[0]!=allParamCount||(gdb)172if(ARR_NDIM(modesArray)!=1||(gdb)174ARR_HASNULL(modesArray)||(gdb)173ARR_DIMS(modesArray)[0]!=allParamCount||(gdb)175ARR_ELEMTYPE(modesArray)!=CHAROID)(gdb)174ARR_HASNULL(modesArray)||(gdb)177paramModes=(char*)ARR_DATA_PTR(modesArray);(gdb)184for(i=0;i<parameterCount;i++)(gdb)pparamModes[0]$12=105'i'(gdb)pparamModes[1]$13=105'i'(gdb)pparamModes[2]$14=98'b'(gdb)pparamModes[3]$15=111'o'(gdb)pparamModes[4]$16=111'o'(gdb)
檢查是否存在多態或者INTERNAL參數.
兩趟循環:第一趟檢查輸入參數,第二趟檢查輸出參數
(gdb)n186switch(parameterTypes->values[i])(gdb)184for(i=0;i<parameterCount;i++)(gdb)186switch(parameterTypes->values[i])(gdb)184for(i=0;i<parameterCount;i++)(gdb)186switch(parameterTypes->values[i])(gdb)184for(i=0;i<parameterCount;i++)(gdb)204if(allParameterTypes!=PointerGetDatum(NULL))(gdb)206for(i=0;i<allParamCount;i++)(gdb)208if(paramModes==NULL||(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)208if(paramModes==NULL||(gdb)211continue;/*ignoreinput-onlyparams*/(gdb)206for(i=0;i<allParamCount;i++)(gdb)208if(paramModes==NULL||(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)208if(paramModes==NULL||(gdb)211continue;/*ignoreinput-onlyparams*/(gdb)206for(i=0;i<allParamCount;i++)(gdb)208if(paramModes==NULL||(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)208if(paramModes==NULL||(gdb)210paramModes[i]==PROARGMODE_VARIADIC)(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)213switch(allParams[i])(gdb)206for(i=0;i<allParamCount;i++)(gdb)208if(paramModes==NULL||(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)208if(paramModes==NULL||(gdb)210paramModes[i]==PROARGMODE_VARIADIC)(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)213switch(allParams[i])(gdb)206for(i=0;i<allParamCount;i++)(gdb)208if(paramModes==NULL||(gdb)pallParamCount$17=5(gdb)n209paramModes[i]==PROARGMODE_IN||(gdb)208if(paramModes==NULL||(gdb)210paramModes[i]==PROARGMODE_VARIADIC)(gdb)209paramModes[i]==PROARGMODE_IN||(gdb)213switch(allParams[i])(gdb)206for(i=0;i<allParamCount;i++)(gdb)239if((IsPolymorphicType(returnType)||genericOutParam)(gdb)
至少存在一個多態輸入參數的情況下才允許返回多態類型.
ANYRANGE返回類型更為嚴格:必須含有一個ANYRANGE輸入(因為無法從ANYELEMENT中規約特殊的范圍類型.)
同時,除非至少有一個INTERNAL輸入參數類型,否則不允許返回INTERNAL類型.
(gdb)n246if((returnType==ANYRANGEOID||anyrangeOutParam)&&(gdb)253if((returnType==INTERNALOID||internalOutParam)&&!internalInParam)(gdb)259if(paramModes!=NULL)(gdb)
只有最后一個輸入參數可以是variadic.如是,則存儲元素類型.
266for(i=0;i<allParamCount;i++)(gdb)n268switch(paramModes[i])(gdb)272if(OidIsValid(variadicType))(gdb)274break;(gdb)266for(i=0;i<allParamCount;i++)(gdb)268switch(paramModes[i])(gdb)272if(OidIsValid(variadicType))(gdb)274break;(gdb)266for(i=0;i<allParamCount;i++)(gdb)268switch(paramModes[i])(gdb)272if(OidIsValid(variadicType))(gdb)274break;(gdb)266for(i=0;i<allParamCount;i++)(gdb)268switch(paramModes[i])(gdb)278break;(gdb)266for(i=0;i<allParamCount;i++)(gdb)268switch(paramModes[i])(gdb)278break;(gdb)266for(i=0;i<allParamCount;i++)(gdb)308for(i=0;i<Natts_pg_proc;++i)(gdb)
檢查完畢,寫入到pg_proc中,初始化values
308for(i=0;i<Natts_pg_proc;++i)(gdb)310nulls[i]=false;(gdb)311values[i]=(Datum)0;(gdb)312replaces[i]=true;(gdb)...
賦值
308for(i=0;i<Natts_pg_proc;++i)(gdb)315namestrcpy(&procname,procedureName);(gdb)316values[Anum_pg_proc_proname-1]=NameGetDatum(&procname);(gdb)pprocedureName$20=0x1173ab0"func_test"(gdb)n317values[Anum_pg_proc_pronamespace-1]=ObjectIdGetDatum(procNamespace);(gdb)318values[Anum_pg_proc_proowner-1]=ObjectIdGetDatum(proowner);(gdb)319values[Anum_pg_proc_prolang-1]=ObjectIdGetDatum(languageObjectId);(gdb)320values[Anum_pg_proc_procost-1]=Float4GetDatum(procost);(gdb)321values[Anum_pg_proc_prorows-1]=Float4GetDatum(prorows);(gdb)322values[Anum_pg_proc_provariadic-1]=ObjectIdGetDatum(variadicType);(gdb)323values[Anum_pg_proc_prosupport-1]=ObjectIdGetDatum(prosupport);(gdb)324values[Anum_pg_proc_prokind-1]=CharGetDatum(prokind);(gdb)325values[Anum_pg_proc_prosecdef-1]=BoolGetDatum(security_definer);(gdb)326values[Anum_pg_proc_proleakproof-1]=BoolGetDatum(isLeakProof);(gdb)327values[Anum_pg_proc_proisstrict-1]=BoolGetDatum(isStrict);(gdb)328values[Anum_pg_proc_proretset-1]=BoolGetDatum(returnsSet);(gdb)329values[Anum_pg_proc_provolatile-1]=CharGetDatum(volatility);(gdb)330values[Anum_pg_proc_proparallel-1]=CharGetDatum(parallel);(gdb)331values[Anum_pg_proc_pronargs-1]=UInt16GetDatum(parameterCount);(gdb)332values[Anum_pg_proc_pronargdefaults-1]=UInt16GetDatum(list_length(parameterDefaults));(gdb)333values[Anum_pg_proc_prorettype-1]=ObjectIdGetDatum(returnType);(gdb)334values[Anum_pg_proc_proargtypes-1]=PointerGetDatum(parameterTypes);(gdb)335if(allParameterTypes!=PointerGetDatum(NULL))(gdb)336values[Anum_pg_proc_proallargtypes-1]=allParameterTypes;(gdb)339if(parameterModes!=PointerGetDatum(NULL))(gdb)340values[Anum_pg_proc_proargmodes-1]=parameterModes;(gdb)343if(parameterNames!=PointerGetDatum(NULL))(gdb)344values[Anum_pg_proc_proargnames-1]=parameterNames;(gdb)347if(parameterDefaults!=NIL)(gdb)350nulls[Anum_pg_proc_proargdefaults-1]=true;(gdb)351if(trftypes!=PointerGetDatum(NULL))(gdb)354nulls[Anum_pg_proc_protrftypes-1]=true;(gdb)355values[Anum_pg_proc_prosrc-1]=CStringGetTextDatum(prosrc);(gdb)356if(probin)(gdb)359nulls[Anum_pg_proc_probin-1]=true;(gdb)360if(proconfig!=PointerGetDatum(NULL))(gdb)363nulls[Anum_pg_proc_proconfig-1]=true;(gdb)366rel=table_open(ProcedureRelationId,RowExclusiveLock);(gdb)367tupDesc=RelationGetDescr(rel);(gdb)
判斷是否已存在
(gdb)pvalues[28]$21=0(gdb)pvalues[0]$22=0(gdb)pvalues[2]$23=2200(gdb)n370oldtup=SearchSysCache3(PROCNAMEARGSNSP,(gdb)p*tupDesc$24={natts=29,tdtypeid=81,tdtypmod=-1,tdrefcount=1,constr=0x7fbeb44493b8,attrs=0x7fbeb44483b8}(gdb)n375if(HeapTupleIsValid(oldtup))(gdb)378Form_pg_procoldproc=(Form_pg_proc)GETSTRUCT(oldtup);(gdb)383if(!replace)(gdb)poldproc$25=(Form_pg_proc)0x7fbeb4388bf8(gdb)p*oldproc$26={oid=16387,proname={data="func_test",'\000'<repeats54times>},pronamespace=2200,proowner=10,prolang=13581,procost=100,prorows=0,provariadic=0,prosupport=0,prokind=102'f',prosecdef=false,proleakproof=false,proisstrict=false,proretset=false,provolatile=118'v',proparallel=117'u',pronargs=3,pronargdefaults=0,prorettype=2249,proargtypes={vl_len_=144,ndim=1,dataoffset=0,elemtype=26,dim1=3,lbound1=0,values=0x7fbeb4388c80}}(gdb)
執行相關判斷:如返回類型,參數類型,參數個數等
(gdb)n388if(!pg_proc_ownercheck(oldproc->oid,proowner))(gdb)393if(oldproc->prokind!=prokind)(gdb)407dropcmd=(prokind==PROKIND_PROCEDURE?"DROPPROCEDURE":(gdb)419if(returnType!=oldproc->prorettype||(gdb)420returnsSet!=oldproc->proretset)(gdb)419if(returnType!=oldproc->prorettype||(gdb)439if(returnType==RECORDOID)(gdb)444olddesc=build_function_result_tupdesc_t(oldtup);(gdb)445newdesc=build_function_result_tupdesc_d(prokind,(gdb)449if(olddesc==NULL&&newdesc==NULL)(gdb)451elseif(olddesc==NULL||newdesc==NULL||(gdb)452!equalTupleDescs(olddesc,newdesc))(gdb)451elseif(olddesc==NULL||newdesc==NULL||(gdb)468proargnames=SysCacheGetAttr(PROCNAMEARGSNSP,oldtup,(gdb)471if(!isnull)(gdb)480proargmodes=SysCacheGetAttr(PROCNAMEARGSNSP,oldtup,(gdb)483if(isnull)(gdb)486n_old_arg_names=get_func_input_arg_names(proargnames,(gdb)489n_new_arg_names=get_func_input_arg_names(parameterNames,(gdb)492for(j=0;j<n_old_arg_names;j++)(gdb)494if(old_arg_names[j]==NULL)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)497strcmp(old_arg_names[j],new_arg_names[j])!=0)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)492for(j=0;j<n_old_arg_names;j++)(gdb)494if(old_arg_names[j]==NULL)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)497strcmp(old_arg_names[j],new_arg_names[j])!=0)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)492for(j=0;j<n_old_arg_names;j++)(gdb)494if(old_arg_names[j]==NULL)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)497strcmp(old_arg_names[j],new_arg_names[j])!=0)(gdb)496if(j>=n_new_arg_names||new_arg_names[j]==NULL||(gdb)492for(j=0;j<n_old_arg_names;j++)(gdb)517if(oldproc->pronargdefaults!=0)(gdb)568replaces[Anum_pg_proc_oid-1]=false;(gdb)569replaces[Anum_pg_proc_proowner-1]=false;(gdb)570replaces[Anum_pg_proc_proacl-1]=false;(gdb)573tup=heap_modify_tuple(oldtup,tupDesc,values,nulls,replaces);(gdb)574CatalogTupleUpdate(rel,&tup->t_self,tup);(gdb
更新tuple
(gdb)n576ReleaseSysCache(oldtup);(gdb)577is_update=true;(gdb)601retval=((Form_pg_proc)GETSTRUCT(tup))->oid;(gdb)
處理函數依賴
(gdb)pretval$27=16387(gdb)n610deleteDependencyRecordsFor(ProcedureRelationId,retval,true);(gdb)612myself.classId=ProcedureRelationId;(gdb)613myself.objectId=retval;(gdb)614myself.objectSubId=0;(gdb)617referenced.classId=NamespaceRelationId;(gdb)618referenced.objectId=procNamespace;(gdb)619referenced.objectSubId=0;(gdb)620recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)623referenced.classId=LanguageRelationId;(gdb)624referenced.objectId=languageObjectId;(gdb)625referenced.objectSubId=0;(gdb)626recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)629referenced.classId=TypeRelationId;(gdb)630referenced.objectId=returnType;(gdb)631referenced.objectSubId=0;(gdb)632recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)635if((trfid=get_transform_oid(returnType,languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)646referenced.classId=TypeRelationId;(gdb)647referenced.objectId=allParams[i];(gdb)648referenced.objectSubId=0;(gdb)649recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)652if((trfid=get_transform_oid(allParams[i],languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)646referenced.classId=TypeRelationId;(gdb)647referenced.objectId=allParams[i];(gdb)648referenced.objectSubId=0;(gdb)649recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)652if((trfid=get_transform_oid(allParams[i],languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)646referenced.classId=TypeRelationId;(gdb)647referenced.objectId=allParams[i];(gdb)648referenced.objectSubId=0;(gdb)649recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)652if((trfid=get_transform_oid(allParams[i],languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)646referenced.classId=TypeRelationId;(gdb)647referenced.objectId=allParams[i];(gdb)648referenced.objectSubId=0;(gdb)649recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)652if((trfid=get_transform_oid(allParams[i],languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)646referenced.classId=TypeRelationId;(gdb)647referenced.objectId=allParams[i];(gdb)648referenced.objectSubId=0;(gdb)649recordDependencyOn(&myself,&referenced,DEPENDENCY_NORMAL);(gdb)652if((trfid=get_transform_oid(allParams[i],languageObjectId,true)))(gdb)644for(i=0;i<allParamCount;i++)(gdb)662if(parameterDefaults)(gdb)667if(OidIsValid(prosupport))(gdb)676if(!is_update)(gdb)680if(!is_update)(gdb)685recordDependencyOnCurrentExtension(&myself,is_update);(gdb)687heap_freetuple(tup);(gdb)690InvokeObjectPostCreateHook(ProcedureRelationId,retval,0);(gdb)692table_close(rel,RowExclusiveLock);(gdb)
執行函數body驗證
695if(OidIsValid(languageValidator))(gdb)697ArrayType*set_items=NULL;(gdb)698intsave_nestlevel=0;(gdb)701CommandCounterIncrement();(gdb)713if(check_function_bodies)(gdb)(gdb)n715set_items=(ArrayType*)DatumGetPointer(proconfig);(gdb)716if(set_items)/*NeedanewGUCnestinglevel*/(gdb)726OidFunctionCall1(languageValidator,ObjectIdGetDatum(retval));(gdb)728if(set_items)(gdb)732returnmyself;(gdb)733}(gdb)
完成調用
(gdb)733}(gdb)CreateFunction(pstate=0x1199c88,stmt=0x11748c8)atfunctioncmds.c:11761176}(gdb)
“分析PostgreSQL CreateFunction中的ProcedureCreate函數”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注本站網站,小編將為大家輸出更多高質量的實用文章!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
迪寧波,我們繼續逛地鐵1號線最后一站霞浦(站)吧。先說一座山的故事,不為別的,只因為這座矮山在歷史上有過太多的名字。昨天談完龍順,我們提到今天的山有一個時髦的名字——鳳凰山。沒錯,他就是曾經鳳凰山主題公園的幕后黑手。為什么說“時尚”這個名字?因為我們現在習慣稱呼的“鳳凰山”這個名字,并不是他最初的正式名字,甚至可以說是在北侖這幾年的不斷發展中慢慢誕生的。后來包括鳳凰山天堂,今天的鳳凰城一帶,都沿用...
做為京東集團的CEO,相信不少人對劉強東的身價有諸多疑問,他一年到底賺多少錢呢?現如今,京東已經成為淘寶的強力競爭對手,相信他的資產定然是不會少了,可是據了解,他一年只拿一塊錢的工資,你們信么,跟隨小編一起來看看。眾所周知,劉強東是京東集團的創始人,在短短十幾年內將京東從一個銷售光磁產品的銷售公司發展成了如今的網絡零售巨頭,而劉強東也被評為了“全球50位最偉大的領導者”。那...
a股單日最大跌幅是哪一天?1996年12月16日,滬深兩交易所發出通知,決定自16日起對在兩交易所上市和交易的股票(含A、B股)和基金類證券的交易價格實行10%的漲跌幅限制。當時大盤連續暴跌4天,其中兩天的跌幅是5.44%,5.70%,9.91%,9.44%。2007年2月27日,A股各指數跌幅均超過8%,其中上證綜指和深成指創近10年最大單日跌幅,分別為8.84%和9.29%。兩市1327只可交...