You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改create_vlabel函数接收name[]参数后调用报错:函数不存在

问题描述

我修改了ag_catalog.create_vlabel函数,将参数从2个调整为3个:

  • 原函数定义(在age--1.2.0.sql中):
CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name)
    RETURNS void
    LANGUAGE c
AS 'MODULE_PATHNAME';
  • 修改后的函数定义:
CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list name[])
    RETURNS void
    LANGUAGE c
AS 'MODULE_PATHNAME';

接着我在label_commands.c文件中修改了函数实现,新增第三个参数的处理逻辑:如果参数不为空,就遍历数组将父标签添加到List *parent中,实现标签继承,核心代码如下:

// [...]

// 新增变量
ArrayType *list_parents;
Datum *elements_parent_names;
Name parent_name;
char *parent_name_str;
int num_parents;

// [...]

// 创建默认标签表
graph = graph_name->data;
label = label_name->data;

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

// 检查用户是否传入父标签列表
if (!PG_ARGISNULL(2)) {
    // 获取第三个参数的数组内容
    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);
    
    // 遍历每个父标签
    for (int i = 0; i < num_parents; i++) {
        parent_name = DatumGetName(elements_parent_names[i]);
        parent_name_str = NameStr(*parent_name);

        // 检查父标签是否存在
        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);

测试时,不传第三个参数可以正常执行:

-- 执行成功
SELECT * FROM ag_catalog.create_vlabel('demo', 'Book');
NOTICE:  VLabel "Book" has been created
 create_vlabel 
---------------
 
(1 row)

但传入数组参数时触发错误:

-- 报错
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.

请问如何修复该问题,使函数能正常接收并处理传入的数组参数?

解决方案

错误原因是:调用时传入的ARRAY['Book']属于text[]类型,但函数定义的第三个参数是name[]类型,PostgreSQL无法自动完成这种类型转换,因此找不到匹配的函数。

有两种可行修复方式:

方式1:调用时显式转换数组类型

在调用语句中把text[]数组强制转换为name[]类型:

SELECT * FROM ag_catalog.create_vlabel('demo', 'Fantasy', ARRAY['Book']::name[]);

方式2:修改函数定义兼容text[]类型

如果希望用户调用时无需手动转换,可以调整函数参数类型并修改C代码逻辑:

  1. 更新SQL函数定义:
CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, parent_list text[])
    RETURNS void
    LANGUAGE c
AS 'MODULE_PATHNAME';
  1. 修改C代码中的参数处理逻辑,将text类型元素转换为Name类型:
// 遍历父标签的循环中修改
for (int i = 0; i < num_parents; i++) {
    // 获取text类型的父标签名并转为字符串
    text *parent_text = DatumGetTextPP(elements_parent_names[i]);
    parent_name_str = text_to_cstring(parent_text);
    // 转换为Name类型
    parent_name = makeString(parent_name_str);

    // 后续检查与添加逻辑保持不变
    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_str);
    lappend(parent, rv);
}

额外建议:保留原有的2参数版本函数,避免破坏原有代码兼容性:

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

内容的提问来源于stack exchange,提问作者Matheus Farias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 07:05:23