这篇文章主要介绍“分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”,在日常操作中,相信很多人在分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一、数据结构
Form_pg_language
plpgsql语言定义结构体
CATALOG(pg_language,2612,LanguageRelationId)
{
Oid oid;
NameData lanname;
Oid lanowner BKI_DEFAULT(PGUID);
bool lanispl BKI_DEFAULT(f);
bool lanpltrusted BKI_DEFAULT(f);
Oid lanplcallfoid BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
Oid laninline BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
Oid lanvalidator BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
#ifdef CATALOG_VARLEN
aclitem lanacl[1] BKI_DEFAULT(_null_);
#endif
} FormData_pg_language;
typedef FormData_pg_language *Form_pg_language;
ArrayType
typedef struct
{
//可变的header
int32 vl_len_;
//维度
int ndim;
//指向数据的偏移量,如为0则表示没有位图
int32 dataoffset;
//元素类型的OID
Oid elemtype;
} ArrayType;
DefElem
typedef struct DefElem
{
NodeTag type;
char *defnamespace;
char *defname;
Node *arg;
DefElemAction defaction;
int location;
} DefElem;
FunctionParameter
typedef enum FunctionParameterMode
{
FUNC_PARAM_IN = 'i',
FUNC_PARAM_OUT = 'o',
FUNC_PARAM_INOUT = 'b',
FUNC_PARAM_VARIADIC = 'v',
FUNC_PARAM_TABLE = 't'
} FunctionParameterMode;
typedef struct FunctionParameter
{
NodeTag type;
char *name;
TypeName *argType;
FunctionParameterMode mode;
Node *defexpr;
} FunctionParameter;
二、源码解读
void
interpret_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;
*requiredResultType = InvalidOid;
//输入参数类型
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;
//扫描链表,提前数据到结果数组中
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)
{
if (languageOid == SQLlanguageId)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL function cannot accept shell type %s",
TypeNameToString(t))));
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;
}
//权限检查
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."))));
}
//处理输入参数
if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
{
//非OUT参数并且不是TABLE参数
if (varCount > 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("VARIADIC parameter must be the last input parameter")));
//写入到输入类型数组中
inTypes[inCount++] = toid;
isinput = true;
}
//处理输出参数
if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
{
if (objtype == OBJECT_PROCEDURE)
//存储过程:要求输出结果类型为RECORD
*requiredResultType = RECORDOID;
else if (outCount == 0)
//第一个OID
*requiredResultType = toid;
outCount++;
}
if (fp->mode == FUNC_PARAM_VARIADIC)
{
//variadic参数
*variadicArgType = toid;
varCount++;
//验证variadic参数类型
switch (toid)
{
case ANYARRAYOID:
case ANYOID:
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;
foreach(px, parameters)
{
//循环判断参数是否重复
FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
if (prevfp == fp)
break;
//输入和输出不冲突
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);
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")));
*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++;
}
//如需要,构建合适的输出
*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;
}
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
$$
declare
begin
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) c
Continuing.
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:195
195 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) n
197 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;
(gdb)
209 *requiredResultType = InvalidOid;
(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) n
228 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_bits
0x7ff12a2c3c57: -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_bits
0x7ff12a2c3c57: -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' <repeats 59 times>}, 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) n
251 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) n
264 if (aclresult != ACLCHECK_OK)
(gdb)
267 if (t->setof)
(gdb)
处理输入参数
(gdb) p t->setof
$16 = false
(gdb) n
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)
(gdb) n
334 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) n
348 foreach(px, parameters)
(gdb)
判断是否重名
(gdb) n
350 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) n
420 if (isinput && have_defaults)
(gdb)
426 i++;
(gdb) p *fp->defexpr
Cannot access memory at address 0x0
(gdb) n
219 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) n
229 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' <repeats 56 times>},
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) n
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)
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) n
350 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) n
355 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) n
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)
下一参数,这时候是一个INOUT参数(在IN和OUT数组中均记录)
(gdb) n
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)
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' <repeats 56 times>},
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) n
252 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)
(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) n
355 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) n
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)
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) n
221 FunctionParameter *fp = (FunctionParameter *) lfirst(x);
(gdb) n
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))
$31 = {oid = 23, typname = {data = "int4", '\000' <repeats 59 times>}, 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) n
252 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)
(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) n
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) n
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)
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) n
436 *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) n
438 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:1065
1065 if (stmt->is_procedure)
(gdb)
到此,关于“分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!