本篇内容主要讲解“怎么实现PostgreSQL中的类型转换”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么实现PostgreSQL中的类型转换”吧!

解析表达式,涉及不同数据类型时:
1.如有相应类型的Operator定义(pg_operator),则尝试进行类型转换,否则报错;
2.如有相应类型的转换规则,转换为目标类型后解析,否则报错.

一、数据结构

Form_pg_operator
pg_operator中的定义,代码会其中的定义转换为FormData_pg_operator结构体

/*----------------*pg_operatordefinition.cppturnsthisinto*typedefstructFormData_pg_operator*----------------*/CATALOG(pg_operator,2617,OperatorRelationId){Oidoid;/*oid*//*nameofoperator*/NameDataoprname;/*OIDofnamespacecontainingthisoper*/OidoprnamespaceBKI_DEFAULT(PGNSP);/*operatorowner*/OidoprownerBKI_DEFAULT(PGUID);/*'l','r',or'b'*/charoprkindBKI_DEFAULT(b);/*canbeusedinmergejoin?*/booloprcanmergeBKI_DEFAULT(f);/*canbeusedinhashjoin?*/booloprcanhashBKI_DEFAULT(f);/*leftargtype,or0if'l'oprkind*/OidoprleftBKI_LOOKUP(pg_type);/*rightargtype,or0if'r'oprkind*/OidoprrightBKI_LOOKUP(pg_type);/*resultdatatype*/OidoprresultBKI_LOOKUP(pg_type);/*OIDofcommutatoroper,or0ifnone*/OidoprcomBKI_DEFAULT(0)BKI_LOOKUP(pg_operator);/*OIDofnegatoroper,or0ifnone*/OidoprnegateBKI_DEFAULT(0)BKI_LOOKUP(pg_operator);/*OIDofunderlyingfunction*/regprocoprcodeBKI_LOOKUP(pg_proc);/*OIDofrestrictionestimator,or0*/regprocoprrestBKI_DEFAULT(-)BKI_LOOKUP(pg_proc);/*OIDofjoinestimator,or0*/regprocoprjoinBKI_DEFAULT(-)BKI_LOOKUP(pg_proc);}FormData_pg_operator;/*----------------*Form_pg_operatorcorrespondstoapointertoatuplewith*theformatofpg_operatorrelation.*----------------*/typedefFormData_pg_operator*Form_pg_operator;二、源码解读

coerce_type函数实现具体的类型转换.

/**coerce_type()*Convertanexpressiontoadifferenttype.*类型转换**Thecallershouldalreadyhavedeterminedthatthecoercionispossible;*seecan_coerce_type.*调用者应确定转换是OK的.**Normally,nocoerciontoatypmod(length)isperformedhere.Thecaller*mustcallcoerce_type_typmodaswell,ifatypmodconstraintiswanted.*(Butifthetargettypeisadomain,itmayinternallycontaina*typmodconstraint,whichwillbeappliedinsidecoerce_to_domain.)*Insomecasespg_castspecifiesatypecoercionfunctionthatalso*applieslengthconversion,andinthosecasesonly,theresultwill*alreadybeproperlycoercedtothespecifiedtypmod.*通常来说,在这里不会执行转换为typmod(length)的操作.**pstateisonlyusedinthecasethatweareabletoresolvethetypeof*apreviouslyUNKNOWNParam.Itisokaytopasspstate=NULLifthe*callerdoesnotwanttypeinformationupdatedforParams.**Note:thisfunctionmustnotmodifythegivenexpressiontree,onlyadd*decorationontopofit.SeetransformSetOperationTree,forexample.*/Node*coerce_type(ParseState*pstate,Node*node,OidinputTypeId,OidtargetTypeId,int32targetTypeMod,CoercionContextccontext,CoercionFormcformat,intlocation){Node*result;//结果NodeCoercionPathTypepathtype;OidfuncId;if(targetTypeId==inputTypeId||node==NULL){/*noconversionneeded*///不需要转换returnnode;}if(targetTypeId==ANYOID||targetTypeId==ANYELEMENTOID||targetTypeId==ANYNONARRAYOID){/**Assumecan_coerce_typeverifiedthatimplicitcoercionisokay.**Note:byreturningtheunmodifiednodehere,wearesayingthat*it'sOKtotreatanUNKNOWNconstantasavalidinputfora*functionacceptingANY,ANYELEMENT,orANYNONARRAY.Thisshouldbe*allright,sinceanUNKNOWNvalueisstillaperfectlyvalidDatum.**NB:wedoNOTwantaRelabelTypehere:theexposedtypeofthe*functionargumentmustbeitsactualtype,notthepolymorphic*pseudotype.*///目标类型可以为任意类型(ANYXXX)returnnode;}if(targetTypeId==ANYARRAYOID||targetTypeId==ANYENUMOID||targetTypeId==ANYRANGEOID){/**Assumecan_coerce_typeverifiedthatimplicitcoercionisokay.**Thesecasesareunliketheonesabovebecausetheexposedtypeof*theargumentmustbeanactualarray,enum,orrangetype.In*particulartheargumentmust*not*beanUNKNOWNconstant.Ifit*is,wejustfallthrough;below,we'llcallanyarray_in,*anyenum_in,oranyrange_in,whichwillproduceanerror.Also,if*whatwehaveisadomainoverarray,enum,orrange,wehaveto*relabelittoitsbasetype.**Note:currently,wecan'tactuallyseeadomain-over-enumhere,*sincetheotherfunctionsinthisfilewillnotmatchsucha*parametertoANYENUM.Butthatshouldgetchangedeventually.*/if(inputTypeId!=UNKNOWNOID){//获取基本类型OidbaseTypeId=getBaseType(inputTypeId);if(baseTypeId!=inputTypeId){RelabelType*r=makeRelabelType((Expr*)node,baseTypeId,-1,InvalidOid,cformat);r->location=location;return(Node*)r;}/*Notadomaintype,soreturnitas-is*/returnnode;}}if(inputTypeId==UNKNOWNOID&&IsA(node,Const)){//----------------输入类型为unknown并且是常量/**Inputisastringconstantwithpreviouslyundeterminedtype.Apply*thetargettype'stypinputfunctiontoittoproduceaconstantof*thetargettype.*应用目标类型的typinput函数,生成目标类型常量**NOTE:thiscasecannotbefoldedtogetherwiththeother*constant-inputcase,sincethetypinputfunctiondoesnot*necessarilybehavethesameasatypeconversionfunction.For*example,int4'stypinputfunctionwillreject"1.2",whereas*float-to-inttypeconversionwillroundtointeger.**XXXifthetypinputfunctionisnotimmutable,wereallyoughtto*postponeevaluationofthefunctioncalluntilruntime.Butthere*isnowaytorepresentatypinputfunctioncallasanexpression*tree,becauseC-stringvaluesarenotDatums.(XXXThis*is**possibleasof7.3,dowewanttodoit?)*/Const*con=(Const*)node;//常量Const*newcon=makeNode(Const);//转换后逇常量OidbaseTypeId;//基本类型Oidint32baseTypeMod;//基本typmodeint32inputTypeMod;//输入typmodeTypebaseType;//基本类型ParseCallbackStatepcbstate;//解析回调函数/**Ifthetargettypeisadomain,wewanttocallitsbasetype's*inputroutine,notdomain_in().Thisistoavoidprematurefailure*whenthedomainappliesatypmod:existinginputroutinesfollow*implicit-coercionsemanticsforlengthchecks,whichisnotalways*whatwewanthere.Theneededcheckwillbeappliedproperly*insidecoerce_to_domain().*/baseTypeMod=targetTypeMod;baseTypeId=getBaseTypeAndTypmod(targetTypeId,&baseTypeMod);/**Formosttypeswepasstypmod-1totheinputroutine,because*existinginputroutinesfollowimplicit-coercionsemanticsfor*lengthchecks,whichisnotalwayswhatwewanthere.Anylength*constraintwillbeappliedlaterbyourcaller.Anexception*howeveristheINTERVALtype,forwhichwe*must*passthetypmod*oritwon'tbeabletoobeythebizarreSQL-specinputrules.(Ugly*assin,butsoisthispartofthespec...)*/if(baseTypeId==INTERVALOID)inputTypeMod=baseTypeMod;elseinputTypeMod=-1;baseType=typeidType(baseTypeId);//构造输出常量Constnewcon->consttype=baseTypeId;newcon->consttypmod=inputTypeMod;newcon->constcollid=typeTypeCollation(baseType);newcon->constlen=typeLen(baseType);newcon->constbyval=typeByVal(baseType);newcon->constisnull=con->constisnull;/**Weusetheoriginalliteral'slocationregardlessoftheposition*ofthecoercion.Thisisachangefrompre-9.2behavior,meantto*simplifylifeforpg_stat_statements.*///使用原始位置newcon->location=con->location;/**Setuptopointattheconstant'stextiftheinputroutinethrows*anerror.*///如果报错,则指向该常量文本setup_parser_errposition_callback(&pcbstate,pstate,con->location);/**WeassumeherethatUNKNOWN'sinternalrepresentationisthesame*asCSTRING.*内部表示跟CSTRING一样*/if(!con->constisnull)newcon->constvalue=stringTypeDatum(baseType,DatumGetCString(con->constvalue),inputTypeMod);elsenewcon->constvalue=stringTypeDatum(baseType,NULL,inputTypeMod);/**Ifit'savarlenavalue,forceittobeinnon-expanded*(non-toasted)format;thisavoidsanypossibledependencyon*externalvaluesandimprovesconsistencyofrepresentation.*///如为可变长度值,则强制其为非扩展格式.if(!con->constisnull&&newcon->constlen==-1)newcon->constvalue=PointerGetDatum(PG_DETOAST_DATUM(newcon->constvalue));#ifdefRANDOMIZE_ALLOCATED_MEMORY/**Forpass-by-referencedatatypes,repeattheconversiontoseeif*theinputfunctionleavesanyuninitializedbytesintheresult.We*canonlydetectthatreliablyifRANDOMIZE_ALLOCATED_MEMORYis*enabled,sowedon'tbothertestingotherwise.Thereasonwedon't*wantanyinstabilityintheinputfunctionisthatcomparisonof*Constnodesreliesonbytewisecomparisonofthedatums,soifthe*inputfunctionleavesgarbagethensubexpressionsthatshouldbe*identicalmaynotgetrecognizedassuch.Seepgsql-hackers*discussionof2008-04-04.*/if(!con->constisnull&&!newcon->constbyval){Datumval2;val2=stringTypeDatum(baseType,DatumGetCString(con->constvalue),inputTypeMod);if(newcon->constlen==-1)val2=PointerGetDatum(PG_DETOAST_DATUM(val2));if(!datumIsEqual(newcon->constvalue,val2,false,newcon->constlen))elog(WARNING,"type%shasunstableinputconversionfor\"%s\"",typeTypeName(baseType),DatumGetCString(con->constvalue));}#endifcancel_parser_errposition_callback(&pcbstate);//结果Noderesult=(Node*)newcon;/*Iftargetisadomain,applyconstraints.*/if(baseTypeId!=targetTypeId)result=coerce_to_domain(result,baseTypeId,baseTypeMod,targetTypeId,ccontext,cformat,location,false);ReleaseSysCache(baseType);//返回returnresult;}if(IsA(node,Param)&&pstate!=NULL&&pstate->p_coerce_param_hook!=NULL){/**AllowtheCoerceParamHooktodecidewhathappens.Itcanreturna*transformednode(verypossiblythesameParamnode),orreturn*NULLtoindicateweshouldproceedwithnormalcoercion.*/result=pstate->p_coerce_param_hook(pstate,(Param*)node,targetTypeId,targetTypeMod,location);if(result)returnresult;}if(IsA(node,CollateExpr)){/**IfwehaveaCOLLATEclause,wehavetopushthecoercion*underneaththeCOLLATE.Thisisreallyugly,butthereislittle*choicebecausetheabovehacksonConstsandParamswouldn'thappen*otherwise.Thisklugehasconsequencesincoerce_to_target_type.*/CollateExpr*coll=(CollateExpr*)node;CollateExpr*newcoll=makeNode(CollateExpr);newcoll->arg=(Expr*)coerce_type(pstate,(Node*)coll->arg,inputTypeId,targetTypeId,targetTypeMod,ccontext,cformat,location);newcoll->collOid=coll->collOid;newcoll->location=coll->location;return(Node*)newcoll;}pathtype=find_coercion_pathway(targetTypeId,inputTypeId,ccontext,&funcId);if(pathtype!=COERCION_PATH_NONE){if(pathtype!=COERCION_PATH_RELABELTYPE){/**Generateanexpressiontreerepresentingrun-timeapplication*oftheconversionfunction.Ifwearedealingwithadomain*targettype,theconversionfunctionwillyieldthebasetype,*andweneedtoextractthecorrecttypmodtousefromthe*domain'styptypmod.*/OidbaseTypeId;int32baseTypeMod;baseTypeMod=targetTypeMod;baseTypeId=getBaseTypeAndTypmod(targetTypeId,&baseTypeMod);result=build_coercion_expression(node,pathtype,funcId,baseTypeId,baseTypeMod,ccontext,cformat,location);/**Ifdomain,coercetothedomaintypeandrelabelwithdomain*typeID,hidingthepreviouscoercionnode.*/if(targetTypeId!=baseTypeId)result=coerce_to_domain(result,baseTypeId,baseTypeMod,targetTypeId,ccontext,cformat,location,true);}else{/**Wedon'tneedtodoaphysicalconversion,butwedoneedto*attachaRelabelTypenodesothattheexpressionwillbeseen*tohavetheintendedtypewheninspectedbyhigher-levelcode.**Also,domainsmayhavevaluerestrictionsbeyondthebasetype*thatmustbeaccountedfor.Ifthedestinationisadomain*thenwewon'tneedaRelabelTypenode.*/result=coerce_to_domain(node,InvalidOid,-1,targetTypeId,ccontext,cformat,location,false);if(result==node){/**XXXcouldwelabelresultwithexprTypmod(node)insteadof*default-1typmod,tosaveapossiblelength-coercion*later?Wouldworkifbothtypeshavesameinterpretationof*typmod,whichislikelybutnotcertain.*/RelabelType*r=makeRelabelType((Expr*)result,targetTypeId,-1,InvalidOid,cformat);r->location=location;result=(Node*)r;}}returnresult;}if(inputTypeId==RECORDOID&&ISCOMPLEX(targetTypeId)){/*CoerceaRECORDtoaspecificcomplextype*/returncoerce_record_to_complex(pstate,node,targetTypeId,ccontext,cformat,location);}if(targetTypeId==RECORDOID&&ISCOMPLEX(inputTypeId)){/*CoerceaspecificcomplextypetoRECORD*//*NB:wedoNOTwantaRelabelTypehere*/returnnode;}#ifdefNOT_USEDif(inputTypeId==RECORDARRAYOID&&is_complex_array(targetTypeId)){/*Coercerecord[]toaspecificcomplexarraytype*//*notimplementedyet...*/}#endifif(targetTypeId==RECORDARRAYOID&&is_complex_array(inputTypeId)){/*Coerceaspecificcomplexarraytypetorecord[]*//*NB:wedoNOTwantaRelabelTypehere*/returnnode;}if(typeInheritsFrom(inputTypeId,targetTypeId)||typeIsOfTypedTable(inputTypeId,targetTypeId)){/**Inputclasstypeisasubclassoftarget,sogeneratean*appropriateruntimeconversion(removingunneededcolumnsand*possiblyrearrangingtheonesthatarewanted).**Wewillalsogetherewhentheinputisadomainoverasubclassof*thetargettype.Tokeeplifesimplefortheexecutor,wedefine*ConvertRowtypeExprasonlyworkingbetweenregularcompositetypes;*therefore,insuchcasesinsertaRelabelTypetosmashtheinput*expressiondowntoitsbasetype.*/OidbaseTypeId=getBaseType(inputTypeId);ConvertRowtypeExpr*r=makeNode(ConvertRowtypeExpr);if(baseTypeId!=inputTypeId){RelabelType*rt=makeRelabelType((Expr*)node,baseTypeId,-1,InvalidOid,COERCE_IMPLICIT_CAST);rt->location=location;node=(Node*)rt;}r->arg=(Expr*)node;r->resulttype=targetTypeId;r->convertformat=cformat;r->location=location;return(Node*)r;}/*Ifwegethere,callerblewit*/elog(ERROR,"failedtofindconversionfunctionfrom%sto%s",format_type_be(inputTypeId),format_type_be(targetTypeId));returnNULL;/*keepcompilerquiet*/}/**Givenatypestructureandastring,returnstheinternalrepresentation*ofthatstring.The"string"canbeNULLtoperformconversionofaNULL*(whichmightresultinfailure,iftheinputfunctionrejectsNULLs).*/DatumstringTypeDatum(Typetp,char*string,int32atttypmod){Form_pg_typetypform=(Form_pg_type)GETSTRUCT(tp);Oidtypinput=typform->typinput;Oidtypioparam=getTypeIOParam(tp);//调用函数进行转换returnOidInputFunctionCall(typinput,string,typioparam,atttypmod);}/**Asabove,forI/OfunctionsidentifiedbyOID.Theseareonlytobeused*inseldom-executedcodepaths.Theyarenotonlyslowbutleakmemory.*/DatumOidInputFunctionCall(OidfunctionId,char*str,Oidtypioparam,int32typmod){FmgrInfoflinfo;//构造函数调用参数fmgr_info(functionId,&flinfo);returnInputFunctionCall(&flinfo,str,typioparam,typmod);}/**Callapreviously-looked-updatatypeinputfunction.**"str"maybeNULLtoindicatewearereadingaNULL.Inthiscase*thecallershouldassumetheresultisNULL,butwe'llcalltheinput*functionanywayifit'snotstrict.Sothisisalmostbutnotquite*thesameasFunctionCall3.*/DatumInputFunctionCall(FmgrInfo*flinfo,char*str,Oidtypioparam,int32typmod){LOCAL_FCINFO(fcinfo,3);Datumresult;if(str==NULL&&flinfo->fn_strict)return(Datum)0;/*justreturnnullresult*/InitFunctionCallInfoData(*fcinfo,flinfo,3,InvalidOid,NULL,NULL);fcinfo->args[0].value=CStringGetDatum(str);fcinfo->args[0].isnull=false;fcinfo->args[1].value=ObjectIdGetDatum(typioparam);fcinfo->args[1].isnull=false;fcinfo->args[2].value=Int32GetDatum(typmod);fcinfo->args[2].isnull=false;//调用函数result=FunctionCallInvoke(fcinfo);/*ShouldgetnullresultifandonlyifstrisNULL*/if(str==NULL){if(!fcinfo->isnull)elog(ERROR,"inputfunction%ureturnednon-NULL",flinfo->fn_oid);}else{if(fcinfo->isnull)elog(ERROR,"inputfunction%ureturnedNULL",flinfo->fn_oid);}returnresult;}/**int4in-converts"num"toint4*/Datumint4in(PG_FUNCTION_ARGS){char*num=PG_GETARG_CSTRING(0);PG_RETURN_INT32(pg_strtoint32(num));}/**Convertinputstringtoasigned32bitinteger.**Allowsanynumberofleadingortrailingwhitespacecharacters.Willthrow*ereport()uponbadinputformatoroverflow.**NB:Accumulateinputasanegativenumber,todealwithtwo'scomplement*representationofthemostnegativenumber,whichcan'tberepresentedasa*positivenumber.*/int32pg_strtoint32(constchar*s){constchar*ptr=s;int32tmp=0;boolneg=false;/*skipleadingspaces*/while(likely(*ptr)&&isspace((unsignedchar)*ptr))ptr++;/*handlesign*/if(*ptr=='-'){ptr++;neg=true;}elseif(*ptr=='+')ptr++;/*requireatleastonedigit*/if(unlikely(!isdigit((unsignedchar)*ptr)))gotoinvalid_syntax;/*processdigits*/while(*ptr&&isdigit((unsignedchar)*ptr))//如'123',-1->-12->-123{int8digit=(*ptr++-'0');//获取数字if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||//tmp*10unlikely(pg_sub_s32_overflow(tmp,digit,&tmp)))//tmp-digitgotoout_of_range;}/*allowtrailingwhitespace,butnotothertrailingchars*/while(*ptr!='\0'&&isspace((unsignedchar)*ptr))ptr++;if(unlikely(*ptr!='\0'))gotoinvalid_syntax;if(!neg){/*couldfailifinputismostnegativenumber*/if(unlikely(tmp==PG_INT32_MIN))gotoout_of_range;tmp=-tmp;//符号取反,-123->123}returntmp;out_of_range:ereport(ERROR,(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),errmsg("value\"%s\"isoutofrangefortype%s",s,"integer")));invalid_syntax:ereport(ERROR,(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),errmsg("invalidinputsyntaxfortype%s:\"%s\"","integer",s)));return0;/*keepcompilerquiet*/}三、跟踪分析

SQL脚本

testdb=#select*fromt_convwhereid='1';

跟踪分析

(gdb)bcoerce_typeBreakpoint1at0x6055f0:fileparse_coerce.c,line164.(gdb)cContinuing.Breakpoint1,coerce_type(pstate=0x2c89e30,node=0x2c8a678,inputTypeId=705,targetTypeId=23,targetTypeMod=-1,ccontext=COERCION_IMPLICIT,cformat=COERCE_IMPLICIT_CAST,location=-1)atparse_coerce.c:164164if(targetTypeId==inputTypeId||(gdb)

输入参数,输入类型ID为705(unknown),目标类型为23(int4)

(gdb)p*pstate$1={parentParseState=0x0,p_sourcetext=0x2c88e08"select*fromt_convwhereid='1';",p_rtable=0x2c8a2a0,p_joinexprs=0x0,p_joinlist=0x2c8a3a8,p_namespace=0x2c8a328,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_WHERE,p_next_resno=2,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*node$2={type=T_Const}(gdb)p*(Const*)node$3={xpr={type=T_Const},consttype=705,consttypmod=-1,constcollid=0,constlen=-2,constvalue=46701384,constisnull=false,constbyval=false,location=32}(gdb)x/1cb467013840x2c89b48:49'1'(gdb)

进入常量转换分支

(gdb)n170if(targetTypeId==ANYOID||(gdb)171targetTypeId==ANYELEMENTOID||(gdb)188if(targetTypeId==ANYARRAYOID||(gdb)189targetTypeId==ANYENUMOID||(gdb)225if(inputTypeId==UNKNOWNOID&&IsA(node,Const))(gdb)244Const*con=(Const*)node;(gdb)245Const*newcon=makeNode(Const);(gdb)260baseTypeMod=targetTypeMod;(gdb)p*con$4={xpr={type=T_Const},consttype=705,consttypmod=-1,constcollid=0,constlen=-2,constvalue=46701384,constisnull=false,constbyval=false,location=32}(gdb)n261baseTypeId=getBaseTypeAndTypmod(targetTypeId,&baseTypeMod);(gdb)272if(baseTypeId==INTERVALOID)(gdb)275inputTypeMod=-1;(gdb)277baseType=typeidType(baseTypeId);(gdb)279newcon->consttype=baseTypeId;(gdb)280newcon->consttypmod=inputTypeMod;(gdb)281newcon->constcollid=typeTypeCollation(baseType);(gdb)282newcon->constlen=typeLen(baseType);(gdb)283newcon->constbyval=typeByVal(baseType);(gdb)284newcon->constisnull=con->constisnull;(gdb)291newcon->location=con->location;(gdb)297setup_parser_errposition_callback(&pcbstate,pstate,con->location);(gdb)p*newcon$5={xpr={type=T_Const},consttype=23,consttypmod=-1,constcollid=0,constlen=4,constvalue=0,constisnull=false,constbyval=true,location=32}(gdb)

完成转换

(gdb)n303if(!con->constisnull)(gdb)305DatumGetCString(con->constvalue),(gdb)304newcon->constvalue=stringTypeDatum(baseType,(gdb)317if(!con->constisnull&&newcon->constlen==-1)(gdb)349cancel_parser_errposition_callback(&pcbstate);(gdb)351result=(Node*)newcon;(gdb)p*newcon$6={xpr={type=T_Const},consttype=23,consttypmod=-1,constcollid=0,constlen=4,constvalue=1,constisnull=false,constbyval=true,location=32}(gdb)n354if(baseTypeId!=targetTypeId)(gdb)361ReleaseSysCache(baseType);(gdb)363returnresult;(gdb)

转换的实现
跟踪InputFunctionCall

(gdb)bInputFunctionCallBreakpoint2at0xa6fabe:filefmgr.c,line1533.(gdb)cContinuing.Breakpoint2,InputFunctionCall(flinfo=0x7ffd8b1da1f0,str=0x2c89b48"1",typioparam=23,typmod=-1)atfmgr.c:15331533LOCAL_FCINFO(fcinfo,3);(gdb)n1536if(str==NULL&&flinfo->fn_strict)(gdb)1539InitFunctionCallInfoData(*fcinfo,flinfo,3,InvalidOid,NULL,NULL);(gdb)1541fcinfo->args[0].value=CStringGetDatum(str);(gdb)1542fcinfo->args[0].isnull=false;(gdb)1543fcinfo->args[1].value=ObjectIdGetDatum(typioparam);(gdb)1544fcinfo->args[1].isnull=false;(gdb)1545fcinfo->args[2].value=Int32GetDatum(typmod);(gdb)1546fcinfo->args[2].isnull=false;(gdb)1548result=FunctionCallInvoke(fcinfo);(gdb)p*fcinfo$7={flinfo=0x7ffd8b1da1f0,context=0x0,resultinfo=0x0,fncollation=0,isnull=false,nargs=3,args=0x7ffd8b1da180}(gdb)p*fcinfo->flinfo$8={fn_addr=0x9694fc<int4in>,fn_oid=42,fn_nargs=1,fn_strict=true,fn_retset=false,fn_stats=2'\002',fn_extra=0x0,fn_mcxt=0x2c88cf0,fn_expr=0x0}(gdb)

实现函数是int4in->pg_strtoint32

(gdb)bpg_strtoint32Breakpoint3at0x9b8b45:filenumutils.c,line201.(gdb)cContinuing.Breakpoint3,pg_strtoint32(s=0x2c89b48"123")atnumutils.c:201201constchar*ptr=s;(gdb)n202int32tmp=0;(gdb)203boolneg=false;(gdb)206while(likely(*ptr)&&isspace((unsignedchar)*ptr))(gdb)210if(*ptr=='-')(gdb)215elseif(*ptr=='+')(gdb)219if(unlikely(!isdigit((unsignedchar)*ptr)))(gdb)223while(*ptr&&isdigit((unsignedchar)*ptr))(gdb)225int8digit=(*ptr++-'0');(gdb)227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)pdigit$9=1'\001'(gdb)n228unlikely(pg_sub_s32_overflow(tmp,digit,&tmp)))(gdb)ptmp$10=0(gdb)n227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)ptmp$11=-1(gdb)n223while(*ptr&&isdigit((unsignedchar)*ptr))(gdb)ptmp$12=-1(gdb)n225int8digit=(*ptr++-'0');(gdb)227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)pdigit$13=2'\002'(gdb)n228unlikely(pg_sub_s32_overflow(tmp,digit,&tmp)))(gdb)227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)ptmp$14=-12(gdb)n223while(*ptr&&isdigit((unsignedchar)*ptr))(gdb)225int8digit=(*ptr++-'0');(gdb)227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)pdigit$15=3'\003'(gdb)n228unlikely(pg_sub_s32_overflow(tmp,digit,&tmp)))(gdb)227if(unlikely(pg_mul_s32_overflow(tmp,10,&tmp))||(gdb)ptmp$16=-123(gdb)n223while(*ptr&&isdigit((unsignedchar)*ptr))(gdb)233while(*ptr!='\0'&&isspace((unsignedchar)*ptr))(gdb)236if(unlikely(*ptr!='\0'))(gdb)239if(!neg)(gdb)242if(unlikely(tmp==PG_INT32_MIN))(gdb)ptmp$17=-123(gdb)n244tmp=-tmp;(gdb)247returntmp;

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