iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >分析PostgreSQL的CreateFunction函数
  • 396
分享到

分析PostgreSQL的CreateFunction函数

2023-05-31 18:05:24 396人浏览 泡泡鱼
摘要

本篇内容主要讲解“分析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, &parallel);    //检索语言并验证授权(比如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,                    &parameterTypes,                    &allParameterTypes,                    &parameterModes,                    &parameterNames,                    &parameterDefaults,                    &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文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 分析PostgreSQL的CreateFunction函数
    本篇内容主要讲解“分析PostgreSQL的CreateFunction函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析PostgreSQL的CreateFunction函数”吧!一、数据...
    99+
    2023-05-31
  • 分析PostgreSQL CreateFunction中的ProcedureCreate函数
    本篇内容介绍了“分析PostgreSQL CreateFunction中的ProcedureCreate函数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何...
    99+
    2024-04-02
  • 分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数
    这篇文章主要介绍“分析PostgreSQL CreateFunction中的interpret_function_parameter_list函数”,在日常操作中,相信很多人在分析PostgreSQL Cr...
    99+
    2024-04-02
  • PostgreSQL的set_base_rel_sizes函数分析
    这篇文章主要讲解了“PostgreSQL的set_base_rel_sizes函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL的s...
    99+
    2024-04-02
  • PostgreSQL中的ProcessRepliesIfAny函数分析
    本篇内容主要讲解“PostgreSQL中的ProcessRepliesIfAny函数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中的P...
    99+
    2024-04-02
  • PostgreSQL中make_rel_from_joinlist函数分析
    这篇文章主要介绍“PostgreSQL中make_rel_from_joinlist函数分析”,在日常操作中,相信很多人在PostgreSQL中make_rel_from_joinlist函数分析问题上存在...
    99+
    2024-04-02
  • PostgreSQL中match_unsorted_outer函数分析
    这篇文章主要讲解了“PostgreSQL中match_unsorted_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL中hash_inner_and_outer函数分析
    这篇文章主要讲解了“PostgreSQL中hash_inner_and_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL中sort_inner_and_outer函数分析
    这篇文章主要讲解了“PostgreSQL中sort_inner_and_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL的set_base_rel_pathlists函数及其子函数分析
    这篇文章主要讲解了“PostgreSQL的set_base_rel_pathlists函数及其子函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Pos...
    99+
    2024-04-02
  • 分析PostgreSQL创建函数的过程
    本篇内容主要讲解“分析PostgreSQL创建函数的过程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析PostgreSQL创建函数的过程”吧!一、数据结构F...
    99+
    2024-04-02
  • PostgreSQL中heap_insert->XLogInsert函数分析
    本篇内容介绍了“PostgreSQL中heap_insert->XLogInsert函数分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
    99+
    2024-04-02
  • PostgreSQL的vacuum过程中heap_vacuum_rel函数分析
    这篇文章主要介绍“PostgreSQL的vacuum过程中heap_vacuum_rel函数分析”,在日常操作中,相信很多人在PostgreSQL的vacuum过程中heap_vacuum_rel函数分析问...
    99+
    2024-04-02
  • PostgreSQL中vacuum过程HeapTupleSatisfiesVacuum函数分析
    本篇内容主要讲解“PostgreSQL中vacuum过程HeapTupleSatisfiesVacuum函数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“P...
    99+
    2024-04-02
  • PostgreSQL中set_base_rel_sizes函数及其子函数案例分析
    本篇内容介绍了“PostgreSQL中set_base_rel_sizes函数及其子函数案例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况...
    99+
    2024-04-02
  • PostgreSQL中query_planner函数的处理逻辑分析
    这篇文章主要介绍“PostgreSQL中query_planner函数的处理逻辑分析”,在日常操作中,相信很多人在PostgreSQL中query_planner函数的处理逻辑分析问题上存在疑惑,小编查阅了...
    99+
    2024-04-02
  • Oracle vs PostgreSQL Develop(14) - 分析函数KEEP DENSE_RANK
    在Oracle中聚合函数KEEP ...
    99+
    2024-04-02
  • PostgreSQL物理优化中的create_index_paths->generate_bitmap_or_paths函数分析
    这篇文章主要讲解了“PostgreSQL物理优化中的create_index_paths->generate_bitmap_or_paths函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大...
    99+
    2024-04-02
  • PostgreSQL物理优化中的create_index_paths->choose_bitmap_and函数分析
    这篇文章主要讲解了“PostgreSQL物理优化中的create_index_paths->choose_bitmap_and函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思...
    99+
    2024-04-02
  • 分析PostgreSQL中的synchronous_commit参数
    本篇内容主要讲解“分析PostgreSQL中的synchronous_commit参数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析PostgreSQL中的...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作