英文:
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 '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?
答案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_name
和parent_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, 'i', &parents_datums, &parent_nulls, &elem_count);
for (i=0;i<elem_count;i++){
elog(NOTICE, "Value at the %d index: %s", i, DatumGetCString(parents_datums[i]));
}
//print the value at the first index
elog(NOTICE, "Value at the first index: %d", keys[0].elemtype);
//print the number of elements in the array
elog(NOTICE, "Number of elements in the array: %d", elem_count);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论