千家信息网

分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍"分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数",在日常操作中,相信很多人在分析PostgreSQL
千家信息网最后更新 2026年11月01日分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数

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

一、数据结构

Form_pg_language
plpgsql语言定义结构体

/* ---------------- *      pg_language definition.  cpp turns this into *      typedef struct FormData_pg_language * ---------------- */CATALOG(pg_language,2612,LanguageRelationId){    Oid         oid;            /* oid */    /* Language name */    NameData    lanname;    /* Language's owner */    Oid         lanowner BKI_DEFAULT(PGUID);    /* Is a procedural language */    bool        lanispl BKI_DEFAULT(f);    /* PL is trusted */    bool        lanpltrusted BKI_DEFAULT(f);    /* Call handler, if it's a PL */    Oid         lanplcallfoid BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);    /* Optional anonymous-block handler function */    Oid         laninline BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);    /* Optional validation function */    Oid         lanvalidator BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);#ifdef CATALOG_VARLEN           /* variable-length fields start here */    /* Access privileges */    aclitem     lanacl[1] BKI_DEFAULT(_null_);#endif} FormData_pg_language;/* ---------------- *      Form_pg_language corresponds to a pointer to a tuple with *      the format of pg_language relation. * ---------------- */typedef FormData_pg_language *Form_pg_language;

ArrayType

/* * Arrays are varlena objects, so must meet the varlena convention that * the first int32 of the object contains the total object size in bytes. * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though! * Arrays是可变对象集,必须符合varlena约定,即对象的第一个int32包含对象的总大小(以字节为单位)。 * 但是,一定要确保使用VARSIZE和SET_VARSIZE函数范围该结构体 * * CAUTION: if you change the header for ordinary arrays you will also * need to change the headers for oidvector and int2vector! */typedef struct{    //可变的header    int32       vl_len_;        /* varlena header (do not touch directly!) */    //维度    int         ndim;           /* # of dimensions */    //指向数据的偏移量,如为0则表示没有位图    int32       dataoffset;     /* offset to data, or 0 if no bitmap */    //元素类型的OID    Oid         elemtype;       /* element type OID */} ArrayType;

DefElem

typedef struct DefElem{  NodeTag   type;  char     *defnamespace; /* NULL if unqualified name */  char     *defname;  Node     *arg;      /* a (Value *) or a (TypeName *) */  DefElemAction defaction;  /* unspecified action, or SET/ADD/DROP */  int     location;   /* token location, or -1 if unknown */} DefElem;

FunctionParameter

typedef enum FunctionParameterMode{  /* the assigned enum values appear in pg_proc, don't change 'em! */  FUNC_PARAM_IN = 'i',    /* input only */  FUNC_PARAM_OUT = 'o',   /* output only */  FUNC_PARAM_INOUT = 'b',   /* both */  FUNC_PARAM_VARIADIC = 'v',  /* variadic (always input) */  FUNC_PARAM_TABLE = 't'    /* table function output column */} FunctionParameterMode;typedef struct FunctionParameter{  NodeTag   type;  char     *name;     /* parameter name, or NULL if not given */  TypeName   *argType;    /* TypeName for parameter type */  FunctionParameterMode mode; /* IN/OUT/etc */  Node     *defexpr;    /* raw default expr, or NULL if not given */} FunctionParameter;

二、源码解读

/* * Interpret the function parameter list of a CREATE FUNCTION or * CREATE AGGREGATE statement. * 解析CREATE FUNCTON/CREATE AGGREGATE语句中的参数链表 * * Input parameters: * parameters: list of FunctionParameter structs * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE) * objtype: needed only to determine error handling and required result type * 输入参数: * parameters:FunctionParameter结构体链表 * languageOid:语言ID * objtype:确定错误处理时需要,并且需要结果类型 * * Results are stored into output parameters.  parameterTypes must always * be created, but the other arrays are set to NULL if not needed. * variadicArgType is set to the variadic array type if there's a VARIADIC * parameter (there can be only one); or to InvalidOid if not. * requiredResultType is set to InvalidOid if there are no OUT parameters, * else it is set to the OID of the implied result type. * 结果存储在输出参数中.必须创建parameterTypes,如不需要其他数组将设置为NULL. * 如存在VARIADIC参数(有且仅有一个),variadicArgType将设置为variadic数组类型. * 如无OUT参数,则requiredResultType设置为InvalidOid,否则设置为结果类型. */voidinterpret_function_parameter_list(ParseState *pstate,//解析状态                  List *parameters,//参数链表                  Oid languageOid,//语言OID                  ObjectType objtype,//对象类型                  oidvector **parameterTypes,//参数类型oid vector                  ArrayType **allParameterTypes,//所有的参数类型                  ArrayType **parameterModes,//参数模式,i/o/b/v/t                  ArrayType **parameterNames,//参数名称                  List **parameterDefaults,//参数默认值链表                  Oid *variadicArgType,//variadic参数类型OID                  Oid *requiredResultType)//结果类型{  int     parameterCount = list_length(parameters);//参数个数  Oid      *inTypes;  int     inCount = 0;  Datum    *allTypes;  Datum    *paramModes;  Datum    *paramNames;  int     outCount = 0;  int     varCount = 0;  bool    have_names = false;  bool    have_defaults = false;  ListCell   *x;  int     i;  *variadicArgType = InvalidOid;  /* default result */  *requiredResultType = InvalidOid; /* default result */  //输入参数类型  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;  /* Scan the list and extract data into work arrays */  //扫描链表,提前数据到结果数组中  i = 0;  foreach(x, parameters)  {    //函数参数    FunctionParameter *fp = (FunctionParameter *) lfirst(x);    //类型名称    TypeName   *t = fp->argType;    //是否输入参数    bool    isinput = false;    Oid     toid;    //pg_proc元组    Type    typtup;    //权限检查结果    AclResult aclresult;    //检索type tuple    typtup = LookupTypeName(NULL, t, NULL, false);    if (typtup)    {      //      if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)      {        /* As above, hard error if language is SQL */        if (languageOid == SQLlanguageId)          ereport(ERROR,              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),               errmsg("SQL function cannot accept shell type %s",                  TypeNameToString(t))));        /* We don't allow creating aggregates on shell types either */        else if (objtype == OBJECT_AGGREGATE)          ereport(ERROR,              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),               errmsg("aggregate cannot accept shell type %s",                  TypeNameToString(t))));        else          ereport(NOTICE,              (errcode(ERRCODE_WRONG_OBJECT_TYPE),               errmsg("argument type %s is only a shell",                  TypeNameToString(t))));      }      //type的OID      toid = typeTypeId(typtup);      //释放缓存      ReleaseSysCache(typtup);    }    else    {      //该类型不存在      ereport(ERROR,          (errcode(ERRCODE_UNDEFINED_OBJECT),           errmsg("type %s does not exist",              TypeNameToString(t))));      toid = InvalidOid;  /* keep compiler quiet */    }    //权限检查    aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);    if (aclresult != ACLCHECK_OK)      aclcheck_error_type(aclresult, toid);    if (t->setof)    {      //存在setof      if (objtype == OBJECT_AGGREGATE)        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("aggregates cannot accept set arguments")));      else if (objtype == OBJECT_PROCEDURE)        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("procedures cannot accept set arguments")));      else        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("functions cannot accept set arguments")));    }    if (objtype == OBJECT_PROCEDURE)    {      //过程对象,不需要OUT参数,只允许inout参数      if (fp->mode == FUNC_PARAM_OUT)        ereport(ERROR,            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),             (errmsg("procedures cannot have OUT arguments"),              errhint("INOUT arguments are permitted."))));    }    /* handle input parameters */    //处理输入参数    if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)    {      //非OUT参数并且不是TABLE参数      /* other input parameters can't follow a VARIADIC parameter */      if (varCount > 0)        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("VARIADIC parameter must be the last input parameter")));      //写入到输入类型数组中      inTypes[inCount++] = toid;      isinput = true;    }    /* handle output parameters */    //处理输出参数    if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)    {      if (objtype == OBJECT_PROCEDURE)        //存储过程:要求输出结果类型为RECORD        *requiredResultType = RECORDOID;      else if (outCount == 0) /* save first output param's type */        //第一个OID        *requiredResultType = toid;      outCount++;    }    if (fp->mode == FUNC_PARAM_VARIADIC)    {      //variadic参数      *variadicArgType = toid;      varCount++;      /* validate variadic parameter type */      //验证variadic参数类型      switch (toid)      {        case ANYARRAYOID:        case ANYOID:          /* okay */          break;        default:          if (!OidIsValid(get_element_type(toid)))            ereport(ERROR,                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),                 errmsg("VARIADIC parameter must be an array")));          break;      }    }    //转换为Datum    allTypes[i] = ObjectIdGetDatum(toid);    //参数类型    paramModes[i] = CharGetDatum(fp->mode);    if (fp->name && fp->name[0])    {      //检查参数名称,参数名称不能重复      ListCell   *px;      /*       * As of Postgres 9.0 we disallow using the same name for two       * input or two output function parameters.  Depending on the       * function's language, conflicting input and output names might       * be bad too, but we leave it to the PL to complain if so.       */      foreach(px, parameters)      {        //循环判断参数是否重复        FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);        if (prevfp == fp)          break;        /* pure in doesn't conflict with pure out */        //输入和输出不冲突        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("parameter name \"%s\" used more than once",                  fp->name)));      }      //获取Datum      paramNames[i] = CStringGetTextDatum(fp->name);      have_names = true;    }    if (fp->defexpr)    {      Node     *def;      if (!isinput)        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("only input parameters can have default values")));      def = transformExpr(pstate, fp->defexpr,                EXPR_KIND_FUNCTION_DEFAULT);      def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");      assign_expr_collations(pstate, def);      /*       * Make sure no variables are referred to (this is probably dead       * code now that add_missing_from is history).       */      if (list_length(pstate->p_rtable) != 0 ||        contain_var_clause(def))        ereport(ERROR,            (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),             errmsg("cannot use table references in parameter default value")));      /*       * transformExpr() should have already rejected subqueries,       * aggregates, and window functions, based on the EXPR_KIND_ for a       * default expression.       *       * It can't return a set either --- but coerce_to_specific_type       * already checked that for us.       *       * Note: the point of these restrictions is to ensure that an       * expression that, on its face, hasn't got subplans, aggregates,       * etc cannot suddenly have them after function default arguments       * are inserted.       */      *parameterDefaults = lappend(*parameterDefaults, def);      have_defaults = true;    }    else    {      if (isinput && have_defaults)        ereport(ERROR,            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),             errmsg("input parameters after one with a default value must also have defaults")));    }    i++;  }  /* Now construct the proper outputs as needed */  //如需要,构建合适的输出  *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;    /* otherwise we set requiredResultType correctly above */  }  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;}

三、跟踪分析

测试脚本

create or replace function func_test(pi_v1 in int,pi_v2 varchar,pio_v3 inout varchar,po_v4 out int,po_v5 out varchar)returns record as$$declarebegin  raise notice 'pi_v1 := %,pi_v2 := %,pi_v3 := %',pi_v1,pi_v2,pio_v3;  pio_v3 := 'pio_v3 i/o';  po_v4 := 100;  po_v5 := 'po_v5 out';end;$$ LANGUAGE plpgsql;

启动GDB跟踪

(gdb) cContinuing.Breakpoint 1, 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) at functioncmds.c:195195   int     parameterCount = list_length(parameters);(gdb)

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

(gdb) p *pstate$1 = {parentParseState = 0x0,   p_sourcetext = 0x10c6ed8 "create or replace function func_test(pi_v1 in int,pi_v2 varchar,pio_v3 inout varchar,po_v4 out int,po_v5 out varchar)\nreturns record \nas\n$$\ndeclare\nbegin\n  raise notice '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) n197   int     inCount = 0;(gdb) 201   int     outCount = 0;(gdb) 202   int     varCount = 0;(gdb) 203   bool    have_names = false;(gdb) 204   bool    have_defaults = false;(gdb) 208   *variadicArgType = InvalidOid;  /* default result */(gdb) 209   *requiredResultType = InvalidOid; /* default result */(gdb) 211   inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));(gdb) 212   allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));(gdb) 213   paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));(gdb) 214   paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));(gdb) 215   *parameterDefaults = NIL;(gdb) 218   i = 0;(gdb) 219   foreach(x, parameters)(gdb)

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

(gdb) 221     FunctionParameter *fp = (FunctionParameter *) lfirst(x);(gdb) 222     TypeName   *t = fp->argType;(gdb) 223     bool    isinput = 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) n228     typtup = LookupTypeName(NULL, t, NULL, false);(gdb) 229     if (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/16c typtup->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/64c typtup->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' }, 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) n251       toid = typeTypeId(typtup);(gdb) 252       ReleaseSysCache(typtup);(gdb) 263     aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);(gdb) p toid$15 = 23(gdb)

检查权限

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

处理输入参数

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

判断是否重名

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

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

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

下一个参数

(gdb) n420       if (isinput && have_defaults)(gdb) 426     i++;(gdb) p *fp->defexprCannot access memory at address 0x0(gdb) n219   foreach(x, parameters)(gdb) 221     FunctionParameter *fp = (FunctionParameter *) lfirst(x);(gdb) 222     TypeName   *t = fp->argType;(gdb) 223     bool    isinput = false;(gdb) 228     typtup = LookupTypeName(NULL, t, NULL, false);(gdb) (gdb) n229     if (typtup)(gdb) 231       if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)(gdb) 251       toid = typeTypeId(typtup);(gdb) 252       ReleaseSysCache(typtup);(gdb) p *((Form_pg_type) GETSTRUCT(typtup))$22 = {oid = 1043, typname = {data = "varchar", '\000' },   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) n263     aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);(gdb) 264     if (aclresult != ACLCHECK_OK)(gdb) 267     if (t->setof)(gdb) 283     if (objtype == OBJECT_PROCEDURE)(gdb) 293     if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)(gdb) 296       if (varCount > 0)(gdb) 300       inTypes[inCount++] = toid;(gdb) 301       isinput = true;(gdb) 305     if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)(gdb) 314     if (fp->mode == FUNC_PARAM_VARIADIC)(gdb) 334     allTypes[i] = ObjectIdGetDatum(toid);(gdb) 336     paramModes[i] = CharGetDatum(fp->mode);(gdb)

判断参数是否重复

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

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

(gdb) n221     FunctionParameter *fp = (FunctionParameter *) lfirst(x);(gdb) 222     TypeName   *t = fp->argType;(gdb) 223     bool    isinput = false;(gdb) 228     typtup = LookupTypeName(NULL, t, NULL, false);(gdb) 229     if (typtup)(gdb) 231       if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)(gdb) 251       toid = typeTypeId(typtup);(gdb) p *((Form_pg_type) GETSTRUCT(typtup))$28 = {oid = 1043, typname = {data = "varchar", '\000' },   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) n252       ReleaseSysCache(typtup);(gdb) 263     aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);(gdb) 264     if (aclresult != ACLCHECK_OK)(gdb) 267     if (t->setof)(gdb) 283     if (objtype == OBJECT_PROCEDURE)(gdb) 293     if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)(gdb) 296       if (varCount > 0)(gdb) 300       inTypes[inCount++] = toid;(gdb) 301       isinput = true;(gdb) 305     if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)(gdb) 307       if (objtype == OBJECT_PROCEDURE)(gdb) 309       else if (outCount == 0) /* save first output param's type */(gdb) 310         *requiredResultType = toid;(gdb) 311       outCount++;(gdb) 314     if (fp->mode == FUNC_PARAM_VARIADIC)(gdb) 334     allTypes[i] = ObjectIdGetDatum(toid);(gdb) 336     paramModes[i] = CharGetDatum(fp->mode);(gdb) 338     if (fp->name && fp->name[0])(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) p *prevfp$29 = {type = T_FunctionParameter, name = 0x10c7b60 "pi_v1", argType = 0x10c7c58,   mode = FUNC_PARAM_IN, defexpr = 0x0}(gdb) n355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 356            fp->mode == FUNC_PARAM_VARIADIC) &&(gdb) p *fp$30 = {type = T_FunctionParameter, name = 0x10c7f38 "pio_v3", argType = 0x10c8030,   mode = FUNC_PARAM_INOUT, defexpr = 0x0}(gdb) n355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 361            prevfp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 363            fp->mode == FUNC_PARAM_TABLE))(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 366           strcmp(prevfp->name, fp->name) == 0)(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 356            fp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 361            prevfp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 363            fp->mode == FUNC_PARAM_TABLE))(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 366           strcmp(prevfp->name, fp->name) == 0)(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 353           break;(gdb) 373       paramNames[i] = CStringGetTextDatum(fp->name);(gdb) 374       have_names = true;(gdb) 377     if (fp->defexpr)(gdb) 420       if (isinput && have_defaults)(gdb) 426     i++;(gdb) 219   foreach(x, parameters)

下一个参数,OUT参数

(gdb) n221     FunctionParameter *fp = (FunctionParameter *) lfirst(x);(gdb) n222     TypeName   *t = fp->argType;(gdb) 223     bool    isinput = false;(gdb) 228     typtup = LookupTypeName(NULL, t, NULL, false);(gdb) 229     if (typtup)(gdb) 231       if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)(gdb) 251       toid = typeTypeId(typtup);(gdb) p *((Form_pg_type) GETSTRUCT(typtup))$31 = {oid = 23, typname = {data = "int4", '\000' }, 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) n252       ReleaseSysCache(typtup);(gdb) 263     aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);(gdb) 264     if (aclresult != ACLCHECK_OK)(gdb) 267     if (t->setof)(gdb) 283     if (objtype == OBJECT_PROCEDURE)(gdb) 293     if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)(gdb) 305     if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)(gdb) 307       if (objtype == OBJECT_PROCEDURE)(gdb) 309       else if (outCount == 0) /* save first output param's type */(gdb) 311       outCount++;(gdb) 314     if (fp->mode == FUNC_PARAM_VARIADIC)(gdb) 334     allTypes[i] = ObjectIdGetDatum(toid);(gdb) 336     paramModes[i] = CharGetDatum(fp->mode);(gdb) 338     if (fp->name && fp->name[0])(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 355         if ((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) n356            fp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 361            prevfp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 364           continue;(gdb) n348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 356            fp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 362           (fp->mode == FUNC_PARAM_OUT ||(gdb) 361            prevfp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 364           continue;(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 356            fp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 355         if ((fp->mode == FUNC_PARAM_IN ||(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 361            prevfp->mode == FUNC_PARAM_VARIADIC) &&(gdb) 360         if ((prevfp->mode == FUNC_PARAM_IN ||(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 366           strcmp(prevfp->name, fp->name) == 0)(gdb) 365         if (prevfp->name && prevfp->name[0] &&(gdb) 348       foreach(px, parameters)(gdb) 350         FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);(gdb) 352         if (prevfp == fp)(gdb) 353           break;(gdb) 373       paramNames[i] = CStringGetTextDatum(fp->name);(gdb) 374       have_names = true;(gdb) 377     if (fp->defexpr)(gdb) 420       if (isinput && have_defaults)(gdb) 426     i++;(gdb) 219   foreach(x, parameters)

下一个参数

......

完成所有参数的解析

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

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

参数 类型 输入 名称 结果 函数 对象 数组 输出 分析 结构 语言 处理 学习 检查 数据 权限 变量 更多 过程 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技企业和互联网企业 深圳科技互联网 互联网医疗科技 互联网科技视频 互联网高科技企业 阿里巴巴算科技企业还是互联网 科技互联网大厂 新兴科技互联网创新大赛颁奖典礼 东莞新华互联网科技学校 佛山市翊博互联网络科技有限公司 朱啸虎曾投资哪些互联网科技企业 中科明德北京互联网科技 高科技互联网套路 南通创西澳互联网科技有限公司 互联网科技快讯热点 互联网科技包装股份有限公司上市 易租星互联网科技有限公司 承德科技产业互联网平台 互联网科技创业有什么好项目 利用互联网等科技手段 互联网科技公司简介 涨乐互联网科技 金融科技和互联网金融 互联网科技股午盘股票涨跌 注册互联网科技公司经营范围大全 广州新华互联网科技学校电竞方面 特约风豹互联网科技为什么扣费 互联网科技如何创业 互联网科技手抄报图片 马化腾互联网科技教学
0