postgresql SQL文件如何链接到C函数?

00jrzges  于 2023-04-20  发布在  PostgreSQL
关注(0)|答案(2)|浏览(124)

在浏览AGE代码时,我发现了这个age-1.3.0.sql文件,我相信所有的表都是在这里创建的,所有的函数都是在这里声明的。
例如行号94

CREATE FUNCTION ag_catalog.create_graph(graph_name name)
RETURNS void
LANGUAGE c
AS 'MODULE_PATHNAME';

我假设这是create_graph函数的声明。
我在age.control文件的第20行找到了MODULE_PATHNAME可能引用的内容

module_pathname = '$libdir/age'

和C函数的定义来创建一个图,我想是这个函数在/src/backend/commands/graph_commands. c行号60:-

/* function that is evoked for creating a graph */
Datum create_graph(PG_FUNCTION_ARGS)
{
    char *graph;
    Name graph_name;
    char *graph_name_str;
    Oid nsp_id;

    //if no argument is passed with the function, graph name cannot be null
    if (PG_ARGISNULL(0))
    {
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("graph name can not be NULL")));
    }

    //gets graph name as function argument
    graph_name = PG_GETARG_NAME(0);  

    graph_name_str = NameStr(*graph_name);

    //checking if the name of the graph falls under the pre-decided graph naming conventions(regex)
    if (!is_valid_graph_name(graph_name_str))
    {
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("graph name is invalid")));
    }

    //graph name must be unique, a graph with the same name should not exist
    if (graph_exists(graph_name_str))
    {
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_SCHEMA),
                 errmsg("graph \"%s\" already exists", graph_name_str)));
    }

    nsp_id = create_schema_for_graph(graph_name);

    //inserts the graph info into the relation which has all the other existing graphs info
    insert_graph(graph_name, nsp_id);  

    //Increment the Command counter before create the generic labels.
    CommandCounterIncrement();

    //Create the default label tables
    graph = graph_name->data;
    create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL);
    create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL);

    ereport(NOTICE,
            (errmsg("graph \"%s\" has been created", NameStr(*graph_name))));

    //according to postgres specification of c-language functions if function returns void this is the syntax
    PG_RETURN_VOID(); 
}

我想问的是,当一个SQL查询

SELECT * FROM ag_catalog.create_graph('graph_name');

执行时,执行上述文件中的C函数?两者之间的链接在哪里?在哪里可以找到?
我已经深入挖掘了大量的代码,但无济于事,我仍然不明白这一切是如何联系在一起的。

koaltpgm

koaltpgm1#

CREATE EXTENSION命令在控制文件中用module_pathname的值替换MODULE_PATHNAME。通常,这被设置为$libdir/shared_library_name,然后在C语言函数的CREATE FUNCTION命令中使用MODULE_PATHNAME,这样脚本文件就不需要硬连接共享库的名称。
CREATE FUNCTION命令提供共享库文件的路径和所提供函数的链接符号。如果省略链接符号,则假定它与正在定义的SQL函数的名称相同。PostgreSQL按以下顺序搜索共享库:
1.如果名称是绝对路径,则加载给定的文件。
1.如果名称以字符串$libdir开头,则该部分将替换为PostgreSQL包库目录名称,该名称在构建时确定。
1.如果名称不包含目录部分,则在配置变量dynamic_library_path指定的路径中搜索文件。
1.否则(在路径中找不到文件,或者它包含非绝对目录部分),动态加载器将尝试采用给定的名称,这很可能会失败。(依赖于当前工作目录是不可靠的。)
如果这个序列不起作用,则将特定于平台的共享库文件扩展名(通常为.so)附加到给定的名称后,然后重试这个序列。如果同样失败,则加载将失败。

bqf10yzr

bqf10yzr2#

此外,SQL查询和代码中的C函数之间的链接是在PostgreSQL中通过使用MODULE_PATHNAME和CREATE FUNCTION命令建立的。
带有C函数定义的共享库文件建立了SQL查询和C函数定义之间的连接,PostgreSQL读取共享库文件并搜索SQL查询中提供的链接符号;一旦找到,它将使用SQL查询的参数运行相应的C函数。
当您运行SQL查询时,如

SELECT * FROM ag_catalog.create_graph('graph_name');

PostgreSQL搜索包含SQL查询中提供的create_graph函数的C函数定义的共享库文件。
在这个特殊的例子中,CREATE FUNCTION命令中的MODULE_PATHNAME关键字被age.control文件的module_pathname变量的值所取代。这个变量被设置为$libdir/age,这意味着PostgreSQL将在PostgreSQL包库目录中查找名为age的共享库文件。
PostgreSQL在找到create_graph函数的链接符号后加载共享库文件。在AGE示例中,链接符号与函数名相同,因此PostgreSQL在共享库中搜索名为create_graph的C函数。
PostgreSQL在找到create_graph时使用SQL查询中提供的参数调用C函数定义。C函数定义负责处理参数,执行任何所需的检查或操作,并在必要时返回一个值。

相关问题