本篇内容主要讲解“分析postgresql的CreateFunction函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析Postgresql的CreateFunction函数”吧!一、数据
本篇内容主要讲解“分析postgresql的CreateFunction函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析Postgresql的CreateFunction函数”吧!
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;
ObjectAddressCreateFunction(ParseState *pstate, CreateFunctionStmt *stmt){ char *probin_str; char *prosrc_str; Oid prorettype; bool returnsSet; char *language; Oid languageOid; Oid languageValidator; node *transformDefElem = NULL; char *funcname; Oid namespaceId;//命名空间ID(schema ID) AclResult aclresult;//权限检查 oidvector *parameterTypes; ArrayType *allParameterTypes; ArrayType *parameterModes; ArrayType *parameterNames; List *parameterDefaults; Oid variadicArgType; List *trftypes_list = NIL; ArrayType *trftypes; Oid requiredResultType; bool isWindowFunc, isStrict, security, isLeakProof; char volatility; ArrayType *proconfig; float4 procost; float4 prorows; Oid prosupport; HeapTuple languageTuple; Form_pg_language languageStruct; List *as_clause; char parallel; //转换名称列表为函数名称和命名空间 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname, &funcname); //检查权限是否足够(是否可以在目标命名空间中创建对象) aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, OBJECT_SCHEMA, get_namespace_name(namespaceId)); //设置默认的属性 isWindowFunc = false;//是否窗口函数 isStrict = false;//是否严格的函数 security = false;//安全性 isLeakProof = false;// volatility = PROVOLATILE_VOLATILE; proconfig = NULL; procost = -1; prorows = -1; prosupport = InvalidOid; parallel = PROPARALLEL_UNSAFE;//非并行安全 //从stmt->options链表中抽取非默认属性 compute_function_attributes(pstate, stmt->is_procedure,//是否过程? stmt->options,//选项 &as_clause, &language, &transformDefElem, &isWindowFunc, &volatility, &isStrict, &security, &isLeakProof, &proconfig, &procost, &prorows, &prosupport, ¶llel); //检索语言并验证授权(比如pl/python这类语言,不一定会支持) languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language)); if (!HeapTupleIsValid(languageTuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("language \"%s\" does not exist", language), (PLTemplateExists(language) ? errhint("Use CREATE EXTENSION to load the language into the database.") : 0))); //语言结构体和OID languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); languageOid = languageStruct->oid; if (languageStruct->lanpltrusted) { //可信语言,需要USAGE权限 AclResult aclresult; aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, OBJECT_LANGUAGE, NameStr(languageStruct->lanname)); } else { //非可信语言,必须是超级用户才能创建 if (!superuser()) aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE, NameStr(languageStruct->lanname)); } languageValidator = languageStruct->lanvalidator; ReleaseSysCache(languageTuple); if (isLeakProof && !superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("only superuser can define a leakproof function"))); if (transformDefElem) { ListCell *lc; foreach(lc, castNode(List, transformDefElem)) { //获取类型ID Oid typeid = typenameTypeId(NULL, lfirst_node(TypeName, lc)); //基础类型 Oid elt = get_base_element_type(typeid); //如有基础类型则用基础类型,否则用类型ID typeid = elt ? elt : typeid; // get_transform_oid(typeid, languageOid, false); //写入到trftypes_list中 trftypes_list = lappend_oid(trftypes_list, typeid); } } interpret_function_parameter_list(pstate, stmt->parameters, languageOid, stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION, ¶meterTypes, &allParameterTypes, ¶meterModes, ¶meterNames, ¶meterDefaults, &variadicArgType, &requiredResultType); if (stmt->is_procedure) { //过程 Assert(!stmt->returnType); prorettype = requiredResultType ? requiredResultType : VOIDOID; returnsSet = false; } else if (stmt->returnType) { //存在返回类型:显式的RETURNS语句 //获取返回类型 compute_return_type(stmt->returnType, languageOid, &prorettype, &returnsSet); if (OidIsValid(requiredResultType) && prorettype != requiredResultType) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("function result type must be %s because of OUT parameters", format_type_be(requiredResultType)))); } else if (OidIsValid(requiredResultType)) { //通过OUT参数作为返回参数 prorettype = requiredResultType; returnsSet = false; } else { //没有指定结果类型 ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("function result type must be specified"))); prorettype = VOIDOID; returnsSet = false; } if (list_length(trftypes_list) > 0) { //处理类型链表 ListCell *lc; Datum *arr; int i; arr = palloc(list_length(trftypes_list) * sizeof(Datum)); i = 0; foreach(lc, trftypes_list) arr[i++] = ObjectIdGetDatum(lfirst_oid(lc)); trftypes = construct_array(arr, list_length(trftypes_list), OIDOID, sizeof(Oid), true, 'i'); } else { trftypes = NULL; } //解析AS语句 interpret_AS_clause(languageOid, language, funcname, as_clause, &prosrc_str, &probin_str); if (procost < 0) { //SQL和PL-XXX函数假定成本更高 if (languageOid == INTERNALlanguageId || languageOid == ClanguageId) procost = 1; else procost = 100; } if (prorows < 0) { if (returnsSet) prorows = 1000; else prorows = 0; } else if (!returnsSet) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("ROWS is not applicable when function does not return a set"))); return ProcedureCreate(funcname, namespaceId, stmt->replace, returnsSet, prorettype, GetUserId(), languageOid, languageValidator, prosrc_str, probin_str, stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION), security, isLeakProof, isStrict, volatility, parallel, parameterTypes, PointerGetDatum(allParameterTypes), PointerGetDatum(parameterModes), PointerGetDatum(parameterNames), parameterDefaults, PointerGetDatum(trftypes), PointerGetDatum(proconfig), prosupport, procost, prorows);}
测试脚本
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) b CreateFunction Breakpoint 1 at 0x670b94: file functioncmds.c, line 929.(gdb) cContinuing.Breakpoint 1, CreateFunction (pstate=0x2b02cb8, stmt=0x2add8f8) at functioncmds.c:929929 Node *transformDefElem = NULL;(gdb) bt#0 CreateFunction (pstate=0x2b02cb8, stmt=0x2add8f8) at functioncmds.c:929#1 0x00000000008f61a6 in ProcessUtilitySlow (pstate=0x2b02cb8, pstmt=0x2addc78, queryString=0x2adbf08 "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 :="..., context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2aDDD70, completionTag=0x7fffef099ca0 "") at utility.c:1478#2 0x00000000008f5069 in standard_ProcessUtility (pstmt=0x2addc78, queryString=0x2adbf08 "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 :="..., context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2addd70, completionTag=0x7fffef099ca0 "") at utility.c:927#3 0x00000000008f418f in ProcessUtility (pstmt=0x2addc78, queryString=0x2adbf08 "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 :="..., context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2addd70, completionTag=0x7fffef099ca0 "") at utility.c:360#4 0x00000000008f3188 in PortalRunUtility (portal=0x2b43278, pstmt=0x2addc78, ---Type <return> to continue, or q <return> to quit--- isTopLevel=true, setHoldSnapshot=false, dest=0x2addd70, completionTag=0x7fffef099ca0 "") at pquery.c:1175#5 0x00000000008f339e in PortalRunMulti (portal=0x2b43278, isTopLevel=true, setHoldSnapshot=false, dest=0x2addd70, altdest=0x2addd70, completionTag=0x7fffef099ca0 "") at pquery.c:1321#6 0x00000000008f28d3 in PortalRun (portal=0x2b43278, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x2addd70, altdest=0x2addd70, completionTag=0x7fffef099ca0 "") at pquery.c:796#7 0x00000000008ec882 in exec_simple_query ( query_string=0x2adbf08 "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 :="...) at postgres.c:1215#8 0x00000000008f0b04 in PostgresMain (arGC=1, argv=0x2b09318, dbname=0x2b09160 "testdb", username=0x2ad8b28 "pg12") at postgres.c:4247#9 0x0000000000846fa8 in BackendRun (port=0x2afdb10) at postmaster.c:4437#10 0x0000000000846786 in BackendStartup (port=0x2afdb10) at postmaster.c:4128#11 0x00000000008429b4 in ServerLoop () at postmaster.c:1704#12 0x000000000084226a in PostmasterMain (argc=1, argv=0x2ad6ae0) at postmaster.c:1377#13 0x0000000000762364 in main (argc=1, argv=0x2ad6ae0) at main.c:228(gdb) (gdb)
输入参数,pstate是ParseState结构体,stmt类型是CreateFunctionStmt结构体
(gdb) p *pstate$1 = {parentParseState = 0x0, p_sourcetext = 0x2adbf08 "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) p *stmt$2 = {type = T_CreateFunctionStmt, is_procedure = false, replace = true, funcname = 0x2adcb58, parameters = 0x2adcd60, returnType = 0x2add580, options = 0x2add818}
获取namespace
(gdb) n939 List *trftypes_list = NIL;(gdb) 957 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,(gdb) 961 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);(gdb) p namespaceId$3 = 2200(gdb)
namespace是public
[local:/data/run/pg12]:5120 pg12@testdb=# select * from pg_namespace; oid | nspname | nspowner | nspacl -------+--------------------+----------+------------------------- 99 | pg_toast | 10 | 12314 | pg_temp_1 | 10 | 12315 | pg_toast_temp_1 | 10 | 11 | pg_catalog | 10 | {pg12=UC/pg12,=U/pg12} 2200 | public | 10 | {pg12=UC/pg12,=UC/pg12} 13291 | information_schema | 10 | {pg12=UC/pg12,=U/pg12}(6 rows)
执行权限检查,初始化属性默认值
(gdb) n962 if (aclresult != ACLCHECK_OK)(gdb) p aclresult$4 = ACLCHECK_OK(gdb) n967 isWindowFunc = false;(gdb) 968 isStrict = false;(gdb) 969 security = false;(gdb) 970 isLeakProof = false;(gdb) 971 volatility = PROVOLATILE_VOLATILE;(gdb) 972 proconfig = NULL;(gdb) 973 procost = -1; (gdb) 974 prorows = -1; (gdb) 975 prosupport = InvalidOid;(gdb) 976 parallel = PROPARALLEL_UNSAFE;(gdb) 979 compute_function_attributes(pstate,
调用compute_function_attributes从stmt->options链表中抽取非默认属性
(gdb) 989 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));(gdb) p *language$33 = 112 'p'(gdb) p *transformDefElemCannot access memory at address 0x0(gdb) p isWindowFunc$34 = false(gdb) p volatility$35 = 118 'v'(gdb) p isStrict$36 = false(gdb) p security$37 = false(gdb) p isLeakProof$38 = false(gdb) p proconfig$39 = (ArrayType *) 0x0(gdb) p procost$40 = -1(gdb) p prorows$41 = -1(gdb) p prosupport$42 = 0(gdb) p parallel$43 = 117 'u'(gdb) p stmt->options$44 = (List *) 0x2add818(gdb) p *stmt->options$45 = {type = T_List, length = 2, head = 0x2add7f0, tail = 0x2add8d0}(gdb) p *(Node *)stmt->options->head->data.ptr_value$46 = {type = T_DefElem}(gdb) p *(DefElem *)stmt->options->head->data.ptr_value$47 = {type = T_DefElem, defnamespace = 0x0, defname = 0xbbf727 "as", arg = 0x2add760, defaction = DEFELEM_UNSPEC, location = 134}(gdb) p *((DefElem *)stmt->options->head->data.ptr_value)->arg$48 = {type = T_List}
(gdb) p *pstate$5 = {parentParseState = 0x0, p_sourcetext = 0x2adbf08 "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) x/1024c pstate->p_sourcetext0x2adbf08: 99 'c' 114 'r' 101 'e' 97 'a' 116 't' 101 'e' 32 ' ' 111 'o'0x2adbf10: 114 'r' 32 ' ' 114 'r' 101 'e' 112 'p' 108 'l' 97 'a' 99 'c'0x2adbf18: 101 'e' 32 ' ' 102 'f' 117 'u' 110 'n' 99 'c' 116 't' 105 'i'0x2adbf20: 111 'o' 110 'n' 32 ' ' 102 'f' 117 'u' 110 'n' 99 'c' 95 '_'0x2adbf28: 116 't' 101 'e' 115 's' 116 't' 40 '(' 112 'p' 105 'i' 95 '_'0x2adbf30: 118 'v' 49 '1' 32 ' ' 105 'i' 110 'n' 32 ' ' 105 'i' 110 'n'0x2adbf38: 116 't' 44 ',' 112 'p' 105 'i' 95 '_' 118 'v' 50 '2' 32 ' '0x2adbf40: 118 'v' 97 'a' 114 'r' 99 'c' 104 'h' 97 'a' 114 'r' 44 ','0x2adbf48: 112 'p' 105 'i' 111 'o' 95 '_' 118 'v' 51 '3' 32 ' ' 105 'i'0x2adbf50: 110 'n' 111 'o' 117 'u' 116 't' 32 ' ' 118 'v' 97 'a' 114 'r'0x2adbf58: 99 'c' 104 'h' 97 'a' 114 'r' 44 ',' 112 'p' 111 'o' 95 '_'0x2adbf60: 118 'v' 52 '4' 32 ' ' 111 'o' 117 'u' 116 't' 32 ' ' 105 'i'0x2adbf68: 110 'n' 116 't' 44 ',' 112 'p' 111 'o' 95 '_' 118 'v' 53 '5'0x2adbf70: 32 ' ' 111 'o' 117 'u' 116 't' 32 ' ' 118 'v' 97 'a' 114 'r'0x2adbf78: 99 'c' 104 'h' 97 'a' 114 'r' 41 ')' 10 '\n' 114 'r' 101 'e'0x2adbf80: 116 't' 117 'u' 114 'r' 110 'n' 115 's' 32 ' ' 114 'r' 101 'e'0x2adbf88: 99 'c' 111 'o' 114 'r' 100 'd' 32 ' ' 10 '\n' 97 'a' 115 's'0x2adbf90: 10 '\n' 36 '$' 36 '$' 10 '\n' 100 'd' 101 'e' 99 'c' 108 'l'0x2adbf98: 97 'a' 114 'r' 101 'e' 10 '\n' 98 'b' 101 'e' 103 'g' 105 'i'0x2adbfa0: 110 'n' 10 '\n' 32 ' ' 32 ' ' 114 'r' 97 'a' 105 'i' 115 's'---Type <return> to continue, or q <return> to quit---0x2adbfa8: 101 'e' 32 ' ' 110 'n' 111 'o' 116 't' 105 'i' 99 'c' 101 'e'0x2adbfb0: 32 ' ' 39 '\'' 112 'p' 105 'i' 95 '_' 118 'v' 49 '1' 32 ' '0x2adbfb8: 58 ':' 61 '=' 32 ' ' 37 '%' 44 ',' 112 'p' 105 'i' 95 '_'0x2adbfc0: 118 'v' 50 '2' 32 ' ' 58 ':' 61 '=' 32 ' ' 37 '%' 44 ','0x2adbfc8: 112 'p' 105 'i' 95 '_' 118 'v' 51 '3' 32 ' ' 58 ':' 61 '='0x2adbfd0: 32 ' ' 37 '%' 39 '\'' 44 ',' 112 'p' 105 'i' 95 '_' 118 'v'0x2adbfd8: 49 '1' 44 ',' 112 'p' 105 'i' 95 '_' 118 'v' 50 '2' 44 ','0x2adbfe0: 112 'p' 105 'i' 111 'o' 95 '_' 118 'v' 51 '3' 59 ';' 10 '\n'0x2adbfe8: 32 ' ' 32 ' ' 112 'p' 105 'i' 111 'o' 95 '_' 118 'v' 51 '3'0x2adbff0: 32 ' ' 58 ':' 61 '=' 32 ' ' 39 '\'' 112 'p' 105 'i' 111 'o'0x2adbff8: 95 '_' 118 'v' 51 '3' 32 ' ' 105 'i' 47 '/' 111 'o' 39 '\''0x2adc000: 59 ';' 10 '\n' 32 ' ' 32 ' ' 112 'p' 111 'o' 95 '_' 118 'v'0x2adc008: 52 '4' 32 ' ' 58 ':' 61 '=' 32 ' ' 49 '1' 48 '0' 48 '0'0x2adc010: 59 ';' 10 '\n' 32 ' ' 32 ' ' 112 'p' 111 'o' 95 '_' 118 'v'0x2adc018: 53 '5' 32 ' ' 58 ':' 61 '=' 32 ' ' 39 '\'' 112 'p' 111 'o'0x2adc020: 95 '_' 118 'v' 53 '5' 32 ' ' 111 'o' 117 'u' 116 't' 39 '\''0x2adc028: 59 ';' 10 '\n' 101 'e' 110 'n' 100 'd' 59 ';' 10 '\n' 36 '$'0x2adc030: 36 '$' 32 ' ' 76 'L' 65 'A' 78 'N' 71 'G' 85 'U' 65 'A'0x2adc038: 71 'G' 69 'E' 32 ' ' 112 'p' 108 'l' 112 'p' 103 'g' 115 's'0x2adc040: 113 'q' 108 'l' 59 ';' 0 '\000' 0 '\000' 127 '\177' 127 '\1---Type <return> to continue, or q <return> to quit---^CQuit(gdb) (gdb) n
获取language
990 if (!HeapTupleIsValid(languageTuple))(gdb) p languageTuple$7 = (HeapTuple) 0x7fcc407e0bf8(gdb) p *languageTuple$8 = {t_len = 120, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 4}, t_tableOid = 2612, t_data = 0x7fcc407e0c20}(gdb) n997 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);(gdb) 998 languageOid = languageStruct->oid;(gdb) p *languageStruct$9 = {oid = 13581, lanname = {data = "plpgsql", '\000' <repeats 56 times>}, lanowner = 10, lanispl = true, lanpltrusted = true, lanplcallfoid = 13578, laninline = 13579, lanvalidator = 13580}(gdb) n1000 if (languageStruct->lanpltrusted)(gdb) 1005 aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);(gdb) 1006 if (aclresult != ACLCHECK_OK)(gdb) 1018 languageValidator = languageStruct->lanvalidator;(gdb) 1020 ReleaseSysCache(languageTuple);(gdb) 1027 if (isLeakProof && !superuser())(gdb) 1032 if (transformDefElem)(gdb) 1056 stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,(gdb)
转换CREATE中剩下的参数,用于ProcedureCreate调用
1053 interpret_function_parameter_list(pstate,(gdb) 1065 if (stmt->is_procedure)(gdb) p *pstate$10 = {parentParseState = 0x0, p_sourcetext = 0x2adbf08 "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) p *stmt$11 = {type = T_CreateFunctionStmt, is_procedure = false, replace = true, funcname = 0x2adcb58, parameters = 0x2adcd60, returnType = 0x2add580, options = 0x2add818}(gdb) p *stmt->parameters$12 = {type = T_List, length = 5, head = 0x2adcd38, tail = 0x2add4b0}(gdb) p parameterTypes$13 = (oidvector *) 0x2bed1a8(gdb) p *parameterTypes$14 = {vl_len_ = 144, ndim = 1, dataoffset = 0, elemtype = 26, dim1 = 3, lbound1 = 0, values = 0x2bed1c0}(gdb) x/144h 0x2bed1c00x2bed1c0: 23 '\027' 0 '\000' 19 '\023' 0 '\000' 19 '\023' 0 '\000' 126 '~' 127 '\177'0x2bed1d0: 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177'0x2bed1e0: 127 '\177' 127 '\177' 127 '\177' 127 '\177' 64 '@' 0 '\000' 0 '\000' 0 '\000'0x2bed1f0: 44 ',' 0 '\000' 0 '\000' 0 '\000' -96 '\240' -80 '\260' 0 '\000' 0 '\000'0x2bed200: -80 '\260' 0 '\000' 1 '\001' 0 '\000' 0 '\000' 0 '\000' 26 '\032' 0 '\000'0x2bed210: 5 '\005' 0 '\000' 1 '\001' 0 '\000' 23 '\027' 0 '\000' 19 '\023' 0 '\000'0x2bed220: 19 '\023' 0 '\000' 23 '\027' 0 '\000' 19 '\023' 0 '\000' 126 '~' 127 '\177'0x2bed230: 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177' 127 '\177'0x2bed240: 32 ' ' 0 '\000' 0 '\000' 0 '\000' 29 '\035' 0 '\000' 0 '\000' 0 '\000'0x2bed250: -96 '\240' -80 '\260' 0 '\000' 0 '\000' 116 't' 0 '\000' 1 '\001' 0 '\000'---Type <return> to continue, or q <return> to quit---^CQuit(gdb) n1071 else if (stmt->returnType)(gdb) p *stmt->returnType$15 = {type = T_TypeName, names = 0x2add548, typeOid = 0, setof = false, pct_type = false, typmods = 0x0, typemod = -1, arrayBounds = 0x0, location = 126}(gdb) p *stmt->returnType->names$16 = {type = T_List, length = 1, head = 0x2add520, tail = 0x2add520}(gdb) n1074 compute_return_type(stmt->returnType, languageOid,(gdb) 1076 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)(gdb) p *prorettypeCannot access memory at address 0x8c9(gdb) p prorettype$17 = 2249(gdb) p returnsSet$18 = false(gdb) p $19 = false(gdb) p *allParameterTypes$20 = {vl_len_ = 176, ndim = 1, dataoffset = 0, elemtype = 26}(gdb) p parameterModes$21 = (ArrayType *) 0x2bed258(gdb) p *parameterModes$22 = {vl_len_ = 116, ndim = 1, dataoffset = 0, elemtype = 18}(gdb) p *parameterNames$23 = {vl_len_ = 336, ndim = 1, dataoffset = 0, elemtype = 25}(gdb) p *parameterDefaultsCannot access memory at address 0x0(gdb) p *variadicArgTypeCannot access memory at address 0x0(gdb) p *requiredResultTypeCannot access memory at address 0x8c9(gdb) p requiredResultType$24 = 2249(gdb) n1098 if (list_length(trftypes_list) > 0)(gdb) p trftypes_list$25 = (List *) 0x0(gdb) n1114 trftypes = NULL;(gdb) 1117 interpret_AS_clause(languageOid, language, funcname, as_clause,(gdb) 1125 if (procost < 0)(gdb) p *prosrc_str$26 = 10 '\n'(gdb) p *probin_strCannot access memory at address 0x0(gdb) p as_clause$27 = (List *) 0x2add760(gdb) p *as_clause$28 = {type = T_List, length = 1, head = 0x2add738, tail = 0x2add738}(gdb) p *as_clause->head$29 = {data = {ptr_value = 0x2add710, int_value = 44947216, oid_value = 44947216}, next = 0x0}(gdb) p (Node *)as_clause->head->data.ptr_value$30 = (Node *) 0x2add710(gdb) p (Node **)as_clause->head->data.ptr_value$31 = (Node **) 0x2add710(gdb) p *as_clause->head->data.ptr_valueAttempt to dereference a generic pointer.(gdb) p (Node *)as_clause->head->data.ptr_value$32 = (Node *) 0x2add710(gdb) n1128 if (languageOid == INTERNALlanguageId ||(gdb) 1132 procost = 100;(gdb) 1134 if (prorows < 0)(gdb) 1136 if (returnsSet)(gdb) 1139 prorows = 0; (gdb) 1150 return ProcedureCreate(funcname,(gdb) 1160 stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),(gdb) 1150 return ProcedureCreate(funcname,(gdb) 1152 stmt->replace,(gdb) 1150 return ProcedureCreate(funcname,(gdb) 1176 }(gdb) ProcessUtilitySlow (pstate=0x2b02cb8, pstmt=0x2addc78, queryString=0x2adbf08 "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 :="..., context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2addd70, completionTag=0x7fffef099ca0 "") at utility.c:14791479 break;(gdb)
到此,相信大家对“分析PostgreSQL的CreateFunction函数”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
--结束END--
本文标题: 分析PostgreSQL的CreateFunction函数
本文链接: https://www.lsjlt.com/news/227356.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
一口价域名售卖能注册吗?域名是网站的标识,简短且易于记忆,为在线用户提供了访问我们网站的简单路径。一口价是在域名交易中一种常见的模式,而这种通常是针对已经被注册的域名转售给其他人的一种方式。
一口价域名买卖的过程通常包括以下几个步骤:
1.寻找:买家需要在域名售卖平台上找到心仪的一口价域名。平台通常会为每个可售的域名提供详细的描述,包括价格、年龄、流
443px" 443px) https://www.west.cn/docs/wp-content/uploads/2024/04/SEO图片294.jpg https://www.west.cn/docs/wp-content/uploads/2024/04/SEO图片294-768x413.jpg 域名售卖 域名一口价售卖 游戏音频 赋值/切片 框架优势 评估指南 项目规模
0