更改函数以检索数组类型参数会导致错误:函数不存在

huangapple go评论59阅读模式
英文:

Changing function so that it retrieves an array type argument causes ERROR: FUNCTION DOES NOT EXIST

问题

I changed a function so that it receives three arguments instead of only two. In the age--1.2.0.sql file, it was set before as:

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

And then I changed to:

CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list name[])
    RETURNS void
    LANGUAGE c
AS 'MODULE_PATHNAME';

After this, I modified the same function in label_commands.c file so that it checks if the third argument is null. If it is not, it iterates through the list, adds the parent labels to a List *parent, and then creates the label inheriting from the parent labels. Here is the block of code where I add this functionality:

    // [...]

    // Added these variables:

    ArrayType *list_parents;
    Datum *elements_parent_names;
    Name parent_name;
    char *parent_name_str;
    int num_parents;

    // [...]

    //Create the default label tables
    graph = graph_name->data;
    label = label_name->data;

    rv = get_label_range_var(graph, graph_oid, AG_DEFAULT_LABEL_VERTEX);
    parent = list_make1(rv);

    // checking if user has provided the parent's name list.
    if (!PG_ARGISNULL(2)) {

        // Get the content from the third argument - which is an array.
        list_parents = PG_GETARG_ARRAYTYPE_P(2);
        num_parents = ArrayGetNItems(ARR_NDIM(list_parents), ARR_DIMS(list_parents));
        elements_parent_names = (Datum *) ARR_DATA_PTR(list_parents);

        // Check for each parent in the list.
        for (int i = 0; i < num_parents; i++) {

            parent_name = DatumGetName(elements_parent_names[i]);
            parent_name_str = NameStr(*parent_name);

            // Check if parent label does not exist
            if (!label_exists(parent_name_str, graph_oid)) {
                ereport(ERROR,
                        (errcode(ERRCODE_UNDEFINED_SCHEMA),
                                errmsg("parent label \"%s\" does not exist.", parent_name_str)));
            }

            rv = get_label_range_var(graph, graph_oid, parent_name->data);

            lappend(parent, rv);
        }
    }

    create_label(graph, label, LABEL_TYPE_VERTEX, parent);

You guys can view the original code here.

After this, I tried calling the function like this:

--(this works)

SELECT * FROM ag_catalog.create_vlabel('demo', 'Book');
NOTICE:  VLabel "Book" has been created
 create_vlabel 
---------------

(1 row)

But then if I call like this:

--(I get an error)

SELECT * FROM ag_catalog.create_vlabel('demo', 'Fantasy', ARRAY['Book']);
ERROR:  function ag_catalog.create_vlabel(unknown, unknown, text[]) does not exist
LINE 1: SELECT * FROM ag_catalog.create_vlabel('demo', 'Fantasy', ARRAY...
                      ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

How can I fix this so that it successfully gets all the elements from the passed array?

英文:

I changed a function so that it receives three arguments instead of only two. In the age--1.2.0.sql file, it was set before as:

CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name)
    RETURNS void
    LANGUAGE c
AS &#39;MODULE_PATHNAME&#39;;

And then I changed to:

CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list name[])
    RETURNS void
    LANGUAGE c
AS &#39;MODULE_PATHNAME&#39;;

After this, I modified the same function in label_commands.c file so that it checks if the third argument is null. If it is not, it iterates through the list, adds the parent labels to a List *parent, and then creates the label inheriting from the parent labels. Here is the block of code where I add this functionality:

    // [...]
    
    // Added these variables:
    
    ArrayType *list_parents;
    Datum *elements_parent_names;
    Name parent_name;
    char *parent_name_str;
    int num_parents;
    
    // [...]
    
    //Create the default label tables
    graph = graph_name-&gt;data;
    label = label_name-&gt;data;

    rv = get_label_range_var(graph, graph_oid, AG_DEFAULT_LABEL_VERTEX);
    parent = list_make1(rv);

    // checking if user has provided the parent&#39;s name list.
    if (!PG_ARGISNULL(2)) {

        // Get the content from the third argument - which is an array.
        list_parents = PG_GETARG_ARRAYTYPE_P(2);
        num_parents = ArrayGetNItems(ARR_NDIM(list_parents), ARR_DIMS(list_parents));
        elements_parent_names = (Datum *) ARR_DATA_PTR(list_parents);
        
        // Check for each parent in the list.
        for (int i = 0; i &lt; num_parents; i++) {
            
            parent_name = DatumGetName(elements_parent_names[i]);
            parent_name_str = NameStr(*parent_name);

            // Check if parent label does not exist
            if (!label_exists(parent_name_str, graph_oid)) {
                ereport(ERROR,
                        (errcode(ERRCODE_UNDEFINED_SCHEMA),
                                errmsg(&quot;parent label \&quot;%s\&quot; does not exist.&quot;, parent_name_str)));
            }

            rv = get_label_range_var(graph, graph_oid, parent_name-&gt;data);

            lappend(parent, rv);
        }
    }

    create_label(graph, label, LABEL_TYPE_VERTEX, parent);

You guys can view the original code here.

After this, I tried calling the function like this:

--(this works)

SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Book&#39;);
NOTICE:  VLabel &quot;Book&quot; has been created
 create_vlabel 
---------------
 
(1 row)

But then if I call like this:

--(I get an error)

SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Fantasy&#39;, ARRAY[&#39;Book&#39;]);
ERROR:  function ag_catalog.create_vlabel(unknown, unknown, text[]) does not exist
LINE 1: SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Fantasy&#39;, ARRAY...
                      ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

How can I fix this so that it successfully gets all the elements from the passed array?

答案1

得分: 3

尝试删除扩展,然后重新创建它。

DROP EXTENSION age CASCADE;
CREATE EXTENSION age;
LOAD age;
英文:

Try dropping the extension, and then re-creating it.

DROP EXTENSION age CASCADE;
CREATE EXTENSION age;
LOAD age;

答案2

得分: 2

这是一个好主意,如Rafsun所提到的,删除扩展名是一个好主意。如果即使这样也不起作用,我注意到您在list_parents上使用了ArrayType。我观察到每当源代码中使用ArrayType时,都使用了deconstruct_array()。也许这就是它无法访问parent_nameparent_name_str内存的原因。我们可能需要将数组处理成其他形式,然后再使用它们。

有关如何使用deconstruct_array的详细信息,请参考这张图片:

更改函数以检索数组类型参数会导致错误:函数不存在

英文:

It's a good thing to drop the extension as mentioned by Rafsun. If even that doesn't work, I see that you've used ArrayType for list_parents. I've observed whenever ArrayType was used in source code, deconstruct_array() has been used. Maybe that's the reason it's unable to access the memory of parent_name and parent_name_str. We might have to process the array into something and then use those.

Refer this image for details on how to use deconstruct_array

更改函数以检索数组类型参数会导致错误:函数不存在

答案3

得分: 1

你应该再次在age文件夹中运行make命令:

sudo make PG_CONFIG=/path/to/postgres/bin/pg_config install

然后删除扩展,并按Rafsun的指示重新创建它。

然后,你应该添加以下代码:

if (!PG_ARGISNULL(2))
{
    // 检查第三个参数是否为字符串
    ArrayType *keys = PG_GETARG_ARRAYTYPE_P(2);
    int elem_count = 0;

    Datum *parents_datums;
    bool *parent_nulls;
    int i;

    // 获取数组中的元素和父元素数据
    deconstruct_array(keys, NAMEOID, 63, false, 'i', &parents_datums, &parent_nulls, &elem_count);

    for (i = 0; i < elem_count; i++) {
        elog(NOTICE, "第 %d 个索引处的值:%s", i, DatumGetCString(parents_datums[i]));
    }

    // 打印第一个索引处的值
    elog(NOTICE, "第一个索引处的值:%d", keys[0].elemtype);

    // 打印数组中的元素数量
    elog(NOTICE, "数组中的元素数量:%d", elem_count);
}
英文:

You should run the make command in age folder again:

sudo make PG_CONFIG=/path/to/postgres/bin/pg_config install

Then drop the extension, and re-create it as told by Rafsun.

Then you should add the following code:

if (!PG_ARGISNULL(2))
{
    //check if the third argument is a string
    ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(2);
    int elem_count=0;

    Datum *parents_datums;
    bool *parent_nulls;
    int i;

    
    // elem_count = ArrayGetNItems(ARR_NDIM(keys), ARR_DIMS(keys));

    //get the elements in the array and parents data
    deconstruct_array(keys, NAMEOID, 63, false, &#39;i&#39;, &amp;parents_datums, &amp;parent_nulls, &amp;elem_count);

    for (i=0;i&lt;elem_count;i++){
        elog(NOTICE, &quot;Value at the %d index: %s&quot;, i, DatumGetCString(parents_datums[i]));
    }

    //print the value at the first index
    elog(NOTICE, &quot;Value at the first index: %d&quot;, keys[0].elemtype);


    //print the number  of elements in the array
    elog(NOTICE, &quot;Number of elements in the array: %d&quot;, elem_count);

} 

huangapple
  • 本文由 发表于 2023年2月10日 04:21:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定