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

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

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:

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

And then I changed to:

  1. CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list name[])
  2. RETURNS void
  3. LANGUAGE c
  4. 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:

  1. // [...]
  2. // Added these variables:
  3. ArrayType *list_parents;
  4. Datum *elements_parent_names;
  5. Name parent_name;
  6. char *parent_name_str;
  7. int num_parents;
  8. // [...]
  9. //Create the default label tables
  10. graph = graph_name->data;
  11. label = label_name->data;
  12. rv = get_label_range_var(graph, graph_oid, AG_DEFAULT_LABEL_VERTEX);
  13. parent = list_make1(rv);
  14. // checking if user has provided the parent's name list.
  15. if (!PG_ARGISNULL(2)) {
  16. // Get the content from the third argument - which is an array.
  17. list_parents = PG_GETARG_ARRAYTYPE_P(2);
  18. num_parents = ArrayGetNItems(ARR_NDIM(list_parents), ARR_DIMS(list_parents));
  19. elements_parent_names = (Datum *) ARR_DATA_PTR(list_parents);
  20. // Check for each parent in the list.
  21. for (int i = 0; i < num_parents; i++) {
  22. parent_name = DatumGetName(elements_parent_names[i]);
  23. parent_name_str = NameStr(*parent_name);
  24. // Check if parent label does not exist
  25. if (!label_exists(parent_name_str, graph_oid)) {
  26. ereport(ERROR,
  27. (errcode(ERRCODE_UNDEFINED_SCHEMA),
  28. errmsg("parent label \"%s\" does not exist.", parent_name_str)));
  29. }
  30. rv = get_label_range_var(graph, graph_oid, parent_name->data);
  31. lappend(parent, rv);
  32. }
  33. }
  34. 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:

  1. --(this works)
  2. SELECT * FROM ag_catalog.create_vlabel('demo', 'Book');
  3. NOTICE: VLabel "Book" has been created
  4. create_vlabel
  5. ---------------
  6. (1 row)

But then if I call like this:

  1. --(I get an error)
  2. SELECT * FROM ag_catalog.create_vlabel('demo', 'Fantasy', ARRAY['Book']);
  3. ERROR: function ag_catalog.create_vlabel(unknown, unknown, text[]) does not exist
  4. LINE 1: SELECT * FROM ag_catalog.create_vlabel('demo', 'Fantasy', ARRAY...
  5. ^
  6. 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:

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

And then I changed to:

  1. CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list name[])
  2. RETURNS void
  3. LANGUAGE c
  4. 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:

  1. // [...]
  2. // Added these variables:
  3. ArrayType *list_parents;
  4. Datum *elements_parent_names;
  5. Name parent_name;
  6. char *parent_name_str;
  7. int num_parents;
  8. // [...]
  9. //Create the default label tables
  10. graph = graph_name-&gt;data;
  11. label = label_name-&gt;data;
  12. rv = get_label_range_var(graph, graph_oid, AG_DEFAULT_LABEL_VERTEX);
  13. parent = list_make1(rv);
  14. // checking if user has provided the parent&#39;s name list.
  15. if (!PG_ARGISNULL(2)) {
  16. // Get the content from the third argument - which is an array.
  17. list_parents = PG_GETARG_ARRAYTYPE_P(2);
  18. num_parents = ArrayGetNItems(ARR_NDIM(list_parents), ARR_DIMS(list_parents));
  19. elements_parent_names = (Datum *) ARR_DATA_PTR(list_parents);
  20. // Check for each parent in the list.
  21. for (int i = 0; i &lt; num_parents; i++) {
  22. parent_name = DatumGetName(elements_parent_names[i]);
  23. parent_name_str = NameStr(*parent_name);
  24. // Check if parent label does not exist
  25. if (!label_exists(parent_name_str, graph_oid)) {
  26. ereport(ERROR,
  27. (errcode(ERRCODE_UNDEFINED_SCHEMA),
  28. errmsg(&quot;parent label \&quot;%s\&quot; does not exist.&quot;, parent_name_str)));
  29. }
  30. rv = get_label_range_var(graph, graph_oid, parent_name-&gt;data);
  31. lappend(parent, rv);
  32. }
  33. }
  34. 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:

  1. --(this works)
  2. SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Book&#39;);
  3. NOTICE: VLabel &quot;Book&quot; has been created
  4. create_vlabel
  5. ---------------
  6. (1 row)

But then if I call like this:

  1. --(I get an error)
  2. SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Fantasy&#39;, ARRAY[&#39;Book&#39;]);
  3. ERROR: function ag_catalog.create_vlabel(unknown, unknown, text[]) does not exist
  4. LINE 1: SELECT * FROM ag_catalog.create_vlabel(&#39;demo&#39;, &#39;Fantasy&#39;, ARRAY...
  5. ^
  6. 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

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

  1. DROP EXTENSION age CASCADE;
  2. CREATE EXTENSION age;
  3. LOAD age;
英文:

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

  1. DROP EXTENSION age CASCADE;
  2. CREATE EXTENSION age;
  3. 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命令:

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

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

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

  1. if (!PG_ARGISNULL(2))
  2. {
  3. // 检查第三个参数是否为字符串
  4. ArrayType *keys = PG_GETARG_ARRAYTYPE_P(2);
  5. int elem_count = 0;
  6. Datum *parents_datums;
  7. bool *parent_nulls;
  8. int i;
  9. // 获取数组中的元素和父元素数据
  10. deconstruct_array(keys, NAMEOID, 63, false, 'i', &parents_datums, &parent_nulls, &elem_count);
  11. for (i = 0; i < elem_count; i++) {
  12. elog(NOTICE, "第 %d 个索引处的值:%s", i, DatumGetCString(parents_datums[i]));
  13. }
  14. // 打印第一个索引处的值
  15. elog(NOTICE, "第一个索引处的值:%d", keys[0].elemtype);
  16. // 打印数组中的元素数量
  17. elog(NOTICE, "数组中的元素数量:%d", elem_count);
  18. }
英文:

You should run the make command in age folder again:

  1. 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:

  1. if (!PG_ARGISNULL(2))
  2. {
  3. //check if the third argument is a string
  4. ArrayType *keys = PG_GETARG_ARRAYTYPE_P(2);
  5. int elem_count=0;
  6. Datum *parents_datums;
  7. bool *parent_nulls;
  8. int i;
  9. // elem_count = ArrayGetNItems(ARR_NDIM(keys), ARR_DIMS(keys));
  10. //get the elements in the array and parents data
  11. deconstruct_array(keys, NAMEOID, 63, false, &#39;i&#39;, &amp;parents_datums, &amp;parent_nulls, &amp;elem_count);
  12. for (i=0;i&lt;elem_count;i++){
  13. elog(NOTICE, &quot;Value at the %d index: %s&quot;, i, DatumGetCString(parents_datums[i]));
  14. }
  15. //print the value at the first index
  16. elog(NOTICE, &quot;Value at the first index: %d&quot;, keys[0].elemtype);
  17. //print the number of elements in the array
  18. elog(NOTICE, &quot;Number of elements in the array: %d&quot;, elem_count);
  19. }

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:

确定