一个KADB报错分析及实验

想把UDF的返回结果保存在表里面,结果执行报错:

test=# insert into footest select * from f5();

ERROR: function cannot execute on a QE slice because it accesses relation "public.foo" (entry db 192.168.85.133:5432 pid=4212)

CONTEXT: SQL statement "select * from (select * from foo where fooid<5 limit 100)a"

PL/pgSQL function f5() line 3 at RETURN QUERY

函数定义:

原始定义:

test=# CREATE OR REPLACE FUNCTION f5() RETURNS SETOF foo AS

test-# BODY

test$# BEGIN

test$# RETURN query select * from foo;

test$# END;

test# BODY$

test-# LANGUAGE plpgsql;

修改为:

CREATE OR REPLACE FUNCTION f5(out fooid int,out foosubid int,out fooname text) RETURNS SETOF record AS

BODY

declare

row record;

BEGIN

for row in select * from foo where foo.fooid<5 loop

fooid:=row.fooid;

foosubid:=row.foosubid;

fooname:=row.fooname;

return next;

end loop;

return;

END;

BODY

LANGUAGE plpgsql;

根据高通的一个issue:

https://knowledge.broadcom.com/external/article/296772/why-we-got-error-like-function-cannot-ex.html

报错原因:

Greenplum is an MPP database, under such architecture, in most cases, the master (AKA: QD, Query Dispatcher) will dispatch the job to the segments (AKA: Query Executor), then gather the result from QE at the end.
one of the limitations of such architecture is, we can not execute non-SELECT statement queries on QE

An example use case that may trigger such error is like below:
the user would like to collect the AO compaction info based on the list inside a table.

复制代码
gpadmin=# select oid,gp_toolkit.__gp_aovisimap_compaction_info(oid) from oid_list ;
ERROR:  function cannot execute on a QE slice because it issues a non-SELECT statement  (seg0 slice1 192.168.6.198:20000 pid=100663)

That is because:

  • the user table "oid_list" was distributed across all the segments

  • the query plan will first indentify the segmentID of target row of table "oid_list", the run the UDF __gp_aovisimap_compaction_info() on it

  • In this UDF there is an "EXECUTE" command inside it, Since EXECUTE is a non-select query, it can not run on QE, so get such error.

实验:

源表和目标表都必须为复制分布

目标表:

test=# create table footest(a text);

源表:

CREATE TABLE foo (fooid INT, foosubid INT, fooname TEXT);

INSERT INTO foo VALUES (1, 2, 'three');

INSERT INTO foo VALUES (4, 5, 'six');

保留数据:

test=# insert into footest select distinct(f5) from (select f5() from gp_dist_random('foo'))a;

INSERT 0 2

test=# select * from footest;

a


(1,2,three)

(4,5,six)

相关推荐
秋饼4 分钟前
Computer Use Agent Java 落地实战:感知-行动循环、执行器与安全围栏生产级实现
java·ai·技术分享·后端开发
文丑颜不良啊2 小时前
LeetCode2161~2180题目解析
java·leetcode
文丑颜不良啊4 小时前
LeetCode2141~2160题目解析
java·leetcode
Penge6664 小时前
《Go 后端开发者学 TypeScript:typescript 类型断言》
javascript
LabVIEW开发4 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
Penge6664 小时前
《Go 后端开发者学 TypeScript:Symbol》
javascript
lambo mercy4 小时前
AI智能租房助手
数据库
天天被压力4 小时前
【A股分钟级高频数据完全手册 #07】北交所历史分钟K线接口:京市Pro版分时批量
java·人工智能·python
天天被压力4 小时前
【A股分钟级高频数据完全手册 #08】股票日、分时数据接口对比:普通分时与Pro版差异实测
java·人工智能·python
特立独行的猫A5 小时前
AI 时代,我为什么推荐用 cj-tauri 开发桌面应用
java·后端·python