存储过程返回结果集_PostgreSQL函数返回结果集
有时我们需要定义返回结果集的函数,本文演示如何编码。
遂古之初,谁传道之?上下未形,何由考之?《天问》
1、函数定义
C语言定义部分
PG_FUNCTION_INFO_V1(quanzl_dummy_setof);Datumquanzl_dummy_setof(PG_FUNCTION_ARGS){...}
这里与一般的SQL函数的C语言定义没什么区别,目前调用协议也只有V1。
SQL定义,如果希望返回三个字段的值:
CREATE FUNCTION quanzl_dummy_setof(OUT int, OUT int, OUT int)AS 'quanzl_dummy' LANGUAGE C;
可以指定出参名,不指定它们自动生成为:column1、column2、column3。
2、函数调用上下文FuncCallContext
src/include/funcapi.h
,这里也定义了结果集函数需要的其他宏。
uint64 call_cntr;uint64 max_calls;void *user_fctx;
call_cntr:已调用次数,不包含本次,由PG函数调用系统自动维护。
max_calls:最大调用次数,但PG不会以它为依据结束函数的调用,它是给用户代码使用的,至少目前是这样。
user_fctx:可用于在调用间传递用户自定义数据,PG对它不做任何处理。
3、结果集函数的开始
FuncCallContext *funcctx;char ***values;if (SRF_IS_FIRSTCALL()){ TupleDesctupdesc; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); tupdesc = CreateTemplateTupleDesc(2); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "col1", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "col2", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "col3", INT4OID, -1, 0); funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); ... 生成 values 的数据 ... funcctx->user_fctx = values; funcctx->max_calls = length of values; MemoryContextSwitchTo(oldcontext);}
多次调用内存上下文在SRF_FIRSTCALL_INIT
之后才有效,这里顺序不能错。切换上下文不是必须的,一般我们会这么做,将函数专用的数据生成在这里,即使忘记回收调用结束后会自动清理。
TupleDesc的定义必须与SQL定义匹配,轻则结果错误,重则直接崩溃。
funcctx->attinmeta 照葫芦画瓢即可,没什么特别,后边生成元祖时会用得到。
values的生成根据业务需要编写,演示用可以写死一个固定数组。
4、单次调用与函数结束
funcctx = SRF_PERCALL_SETUP();values = (char ***) funcctx->user_fctx;if (funcctx->call_cntr < funcctx->max_calls){ ... 返回单条结果 ...}else SRF_RETURN_DONE(funcctx);
第一个看名字也知道,是每次必须调用的。
第一次调用时生成的user_fctx,在后续调用中取出来继续利用。
在没有结束之前,每次调用只返回一条记录;当调用次数达到上限时,结束调用。
5、返回单条结果
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values[funcctx->call_cntr]);result = HeapTupleGetDatum(tuple);SRF_RETURN_NEXT(funcctx, result);
实际实现根据业务需求的不同,要复杂的多,这里只是演示,所以简单这么一写。PG代码中有很多例子,搜索一下 SRF_IS_FIRSTCALL 可以发现很多。
6、完整示例
连起来看看我们的演示代码,会更清晰一些:
PG_FUNCTION_INFO_V1(quanzl_dummy_setof);Datumquanzl_dummy_setof(PG_FUNCTION_ARGS){ FuncCallContext *funcctx; char ***values; if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); tupdesc = CreateTemplateTupleDesc(2); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "col1", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "col2", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "col3", INT4OID, -1, 0); funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); ... 生成 values 的数据 ... funcctx->user_fctx = values; funcctx->max_calls = length of values; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); values = (char ***) funcctx->user_fctx; if (funcctx->call_cntr < funcctx->max_calls) { tuple = BuildTupleFromCStrings(funcctx->attinmeta, values[funcctx->call_cntr]); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else SRF_RETURN_DONE(funcctx);}
返回结果集还有另一种写法,有时间再补充。
欢迎关注
存储过程返回结果集_PostgreSQL函数返回结果集相关推荐
- pandas使用groupby函数和count函数返回的是分组下每一列的统计值(不统计NaN缺失值)、如果多于一列返回dataframe、size函数返回分组下的行数结果为Series(缺失值不敏感)
pandas使用groupby函数和count函数返回的是分组下每一列的统计值(不统计NaN缺失值).如果多于一列返回dataframe.size函数返回分组下的行数结果为Series(不区分缺失值和 ...
- “正话反说”:A和B在玩一个游戏,两人轮流说一句话,这句话正读反读都一样,如adgda,谁先说错,谁出局,另一个人胜出。编写一个函数用于判断这句话是否符合要求,符合要求时,函数返回1,否则函数返回0
"正话反说":A和B在玩一个游戏,两人轮流说一句话,这句话正读反读都一样,如adgda,谁先说错,谁出局,另一个人胜出. 编写一个函数用于判断这句话是否符合要求,符合要求时,函数返 ...
- 模板引擎不关心内容之——art-template,碰见的同步与fs.readFile异步以及函数回调问题的描述,针对fs的readfille读取文件时,返回不了异步函数返回值的解决方法
模板引擎不关心内容 art-template art-template不仅可以在浏览器使用,也可以在node中使用 npm install art-template该命令在哪执行就会把包下载在哪里,默 ...
- c语言自定义函数多个返回值,C语言函数返回值
C语言函数返回值教程 如果,我们希望函数不返回任何值,那么我们需要显式的指明其返回类型为 C语言函数不返回值 语法 void funcName(paramType1 param1, paramType ...
- python函数能返回列表吗_Python函数返回列表还是作为生成器工作?
我正在尝试创建一个返回对象或作为生成器的函数. 这是一个坏主意,因为作为一种最佳实践,您希望函数可靠地返回相同类型的值,但为了科学的利益-- 我正在使用Python 2,因此range返回一个列表,x ...
- c语言怎么返回数组,c++从函数返回数组的方法代码
c++如何从函数返回数组? C++ 从函数返回数组 C++ 不允许返回一个完整的数组作为函数的参数.但是,您可以通过指定不带索引的数组名来返回一个指向数组的指针. 如果您想要从函数返回一个一维数组,您 ...
- mysql linux 函数返回值_linux recv函数返回值分析
函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 该函数第一个参数制定接收端套接字描述符; 第二个参数指明一个缓冲区, ...
- C++ opencv返回一幅图像返回以及vector作为函数返回值用法
C++ opencv返回一幅图像返回 https://blog.csdn.net/mao_hui_fei/article/details/109349244 vector作为函数返回值用法 https ...
- c++_函数返回值,引用作为函数返回值
catalog 函数返回值 返回值是`[const] T &` 返回值的类型是 T 返回的对象是 局部对象 实现原理 返回的对象是 全局对象 实例 函数返回值 返回值是[const] T &a ...
最新文章
- Python超越Java,Rust持续称王!Stack Overflow 2019开发者报告
- 7-2一元多项式的乘法与加法运算
- CopyOnWriteArrayList简介
- php 某一天时间凌晨,PHP获得今天 天凌晨时间戳的例子
- [云炬创业管理笔记]第二章成为创业者讨论4
- C# List.sort排序详解(多权重,升序降序)
- 统一元数据,数据湖Catalog让大数据存算分离不再是问题
- linux系统设置服务开机启动3种方法,Linux开机启动程序详解
- mysql 清空或删除表数据后,控制表自增列值的方法
- dos命令集--江南技术联盟
- POJ 3278(Catch That Cow)
- Android运行原理及运行机制知识汇总
- linux系统装psp,如何在Linux中玩PSP游戏
- 8086汇编实现 加密解密软件
- 非常哇塞的 SpringBoot性能优化长文!
- react骨架屏自动生成_网页骨架屏自动生成方案(dps)
- 除了LoRa和SigFox,物联网低功耗广域网络还有哪些
- java编写实现更新_Android实现APP自动更新功能
- supervisorctl error (no such process)
- python中文分词,生成标签云,生成指定形状图片标签云
热门文章
- php最难,那个PHP中号称最难的‘递归函数’
- c语言正则表达式库,c语言正则表达式库--PCRE
- 沙发家具网站源码_小户型装修不会选家具?大湾网推荐你了解这些装修风格家具,装修省心空间大!...
- CMake配置OpenCV时,显示错误:find_host_package(PythonInterp 2.7)' found wrong Python version
- gradle 刷新打包的时候报错
- vue npm run dev 报错 semver\semver.js:312 throw new TypeError('Invalid Version: ' + version)
- iView 实现可编辑表格 1
- MYSQL 浅谈MyISAM 存储引擎
- BZOJ 2738: 矩阵乘法 [整体二分]
- 初窥Javascript单元测试,附带掌握一门新技能的学习方式。