PostgreSQL C函数获取值
PostgreSQL C function to get values
我正在尝试用 C 编写 PostgreSQL 函数。
我的目标是找到列表的最小值。所以,我的函数将像这样执行:
SELECT min_to_max(val) FROM (VALUES(1),(2),(3)) x(val);
SELECT min_to_max(val) FROM my_table;
这是我的 C 代码,我在这里丢失了。例如,有一个名为“PG_GETARG_INT32”的函数可以获取整数值,但我不知道如何从 table 中获取值以便进行处理。有什么想法吗?
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(get_sum);
Datum
get_sum(PG_FUNCTION_ARGS)
{
ArrayType *v1,
bool isnull;
isnull = PG_ARGISNULL(0);
if (isnull)
ereport( ERROR,
( errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("The input cannot be empty")));
List a = PG_GETARR_SOMEFUNCTION_2_GET_LIST(0);
# for loop iteration to find min_val
# return min_val
}
已编辑(2022.05.13 - 以下为编辑部分):
感谢@Laurenz Albe。我取得了一些进步。
然而,现在我想走得更远(不需要使用 C 语言。正如 Laurenz Albe 所说,我只是迈出了一小步)。
我的函数和聚合如下所示,用于查找最小值和最大值:
CREATE or replace FUNCTION find_min_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
begin
if <= then min_val := ;
elsif < then min_val := ;
end if;
return min_val;
END;
$$;
CREATE or replace AGGREGATE find_min(integer)
(
SFUNC = find_min_func,
STYPE = integer
);
CREATE or replace FUNCTION find_max_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
max_val integer;
begin
if >= then max_val := ;
elsif > then max_val := ;
end if;
return max_val;
END;
$$;
CREATE or replace AGGREGATE find_max(integer)
(
SFUNC = find_max_func, -- State function
STYPE = integer -- State type
);
他们工作得很好,但现在我想做一些类似
的事情
SELECT min_to_max(val) 来自 (VALUES(1),(2),(3)) x(val);
预期输出:
1 -> 3
所以,我只是写了一个状态函数和聚合对,如下所示(我知道这是错误的):
CREATE or replace FUNCTION find_min_and_max_func(
state integer,
next integer
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
output varchar;
begin
if <= then min_val := ; max_val := ;
elsif < then min_val := ; max_val := ;
end if;
output = cast(min_val as varchar) || '->' || cast(max_val as varchar) ;
return output;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = varchar -- State type
);
这是错误的,因为状态函数将参数作为整数但 returns(?) varchar,所以它会变化。
如何在这里安排我的状态函数?
谢谢!
要创建聚合函数,您必须使用 CREATE AGGREGATE
。您在 SQL 中创建它。您可能需要在 C 中实现的是 状态转换函数 (SFUNC
),也许还有其他函数,具体取决于您要创建的聚合类型。
聚合函数不必从table中读取; PostgreSQL 执行器将向它提供所需的数据。
如果您开始编写 C 函数,您或许应该从比聚合函数更简单的东西开始。
在@Laurenz Albe(再次感谢他)的帮助下,我找到了解决方案。另外,我查看了:
- https://hoverbear.org/blog/postgresql-aggregates-with-rust/
- https://hashrocket.com/blog/posts/custom-aggregates-in-postgresql
这是我的解决方案:
CREATE or replace FUNCTION find_min_and_max_func(
state point,
next integer
) RETURNS point
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
begin
if state[0] <= next then min_val := state[0];
elsif next < state[0] then min_val := next;
end if;
if state[1] >= next then max_val := state[1];
elsif next > state[1] then max_val := next;
end if;
return point(min_val, max_val) ;
END;
$$;
CREATE or replace FUNCTION find_min_and_max_final_func(
state point
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
begin
return cast(state[0] as varchar) || '->' || cast(state[1] as varchar) ;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = point, -- State type
FINALFUNC = find_min_and_max_final_func,
initcond = '(1231231232131,0)'
);
SELECT find_min_and_max(value) FROM UNNEST(ARRAY [1, 2, 3]) as value;
find_min_and_max
------------------
1->6
(1 row)
谢谢!
我正在尝试用 C 编写 PostgreSQL 函数。
我的目标是找到列表的最小值。所以,我的函数将像这样执行:
SELECT min_to_max(val) FROM (VALUES(1),(2),(3)) x(val);
SELECT min_to_max(val) FROM my_table;
这是我的 C 代码,我在这里丢失了。例如,有一个名为“PG_GETARG_INT32”的函数可以获取整数值,但我不知道如何从 table 中获取值以便进行处理。有什么想法吗?
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(get_sum);
Datum
get_sum(PG_FUNCTION_ARGS)
{
ArrayType *v1,
bool isnull;
isnull = PG_ARGISNULL(0);
if (isnull)
ereport( ERROR,
( errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("The input cannot be empty")));
List a = PG_GETARR_SOMEFUNCTION_2_GET_LIST(0);
# for loop iteration to find min_val
# return min_val
}
已编辑(2022.05.13 - 以下为编辑部分):
感谢@Laurenz Albe。我取得了一些进步。
然而,现在我想走得更远(不需要使用 C 语言。正如 Laurenz Albe 所说,我只是迈出了一小步)。
我的函数和聚合如下所示,用于查找最小值和最大值:
CREATE or replace FUNCTION find_min_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
begin
if <= then min_val := ;
elsif < then min_val := ;
end if;
return min_val;
END;
$$;
CREATE or replace AGGREGATE find_min(integer)
(
SFUNC = find_min_func,
STYPE = integer
);
CREATE or replace FUNCTION find_max_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
max_val integer;
begin
if >= then max_val := ;
elsif > then max_val := ;
end if;
return max_val;
END;
$$;
CREATE or replace AGGREGATE find_max(integer)
(
SFUNC = find_max_func, -- State function
STYPE = integer -- State type
);
他们工作得很好,但现在我想做一些类似
的事情SELECT min_to_max(val) 来自 (VALUES(1),(2),(3)) x(val);
预期输出: 1 -> 3
所以,我只是写了一个状态函数和聚合对,如下所示(我知道这是错误的):
CREATE or replace FUNCTION find_min_and_max_func(
state integer,
next integer
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
output varchar;
begin
if <= then min_val := ; max_val := ;
elsif < then min_val := ; max_val := ;
end if;
output = cast(min_val as varchar) || '->' || cast(max_val as varchar) ;
return output;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = varchar -- State type
);
这是错误的,因为状态函数将参数作为整数但 returns(?) varchar,所以它会变化。
如何在这里安排我的状态函数?
谢谢!
要创建聚合函数,您必须使用 CREATE AGGREGATE
。您在 SQL 中创建它。您可能需要在 C 中实现的是 状态转换函数 (SFUNC
),也许还有其他函数,具体取决于您要创建的聚合类型。
聚合函数不必从table中读取; PostgreSQL 执行器将向它提供所需的数据。
如果您开始编写 C 函数,您或许应该从比聚合函数更简单的东西开始。
在@Laurenz Albe(再次感谢他)的帮助下,我找到了解决方案。另外,我查看了:
- https://hoverbear.org/blog/postgresql-aggregates-with-rust/
- https://hashrocket.com/blog/posts/custom-aggregates-in-postgresql
这是我的解决方案:
CREATE or replace FUNCTION find_min_and_max_func(
state point,
next integer
) RETURNS point
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
begin
if state[0] <= next then min_val := state[0];
elsif next < state[0] then min_val := next;
end if;
if state[1] >= next then max_val := state[1];
elsif next > state[1] then max_val := next;
end if;
return point(min_val, max_val) ;
END;
$$;
CREATE or replace FUNCTION find_min_and_max_final_func(
state point
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
begin
return cast(state[0] as varchar) || '->' || cast(state[1] as varchar) ;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = point, -- State type
FINALFUNC = find_min_and_max_final_func,
initcond = '(1231231232131,0)'
);
SELECT find_min_and_max(value) FROM UNNEST(ARRAY [1, 2, 3]) as value;
find_min_and_max
------------------
1->6
(1 row)
谢谢!