# 第 56 章编写过程语言处理程序
所有对以编译语言的当前“版本 1”接口以外的语言编写的函数(这包括用户定义的过程语言中的函数和用 SQL 编写的函数)的所有调用都经过一个呼叫处理程序特定语言的功能。调用处理程序有责任以有意义的方式执行函数,例如通过解释提供的源文本。本章概述了如何编写新的过程语言的调用处理程序。
过程语言的调用处理程序是一个“普通”函数,必须用编译语言(如 C)编写,使用 version-1 接口,并在 PostgreSQL 中注册为不带参数并返回类型语言处理程序
.这种特殊的伪类型将函数标识为调用处理程序,并防止在 SQL 命令中直接调用它。有关 C 语言调用约定和动态加载的更多详细信息,请参阅第 38.10 节.
调用处理程序的调用方式与任何其他函数相同:它接收指向FunctionCallInfoBaseData
结构
包含参数值和有关被调用函数的信息,并且预计会返回一个基准
结果(并可能设置一片空白
的领域FunctionCallInfoBaseData
结构,如果它希望返回 SQL 空结果)。调用处理程序和普通被调用函数之间的区别在于flinfo->fn_oid
的领域FunctionCallInfoBaseData
结构将包含要调用的实际函数的 OID,而不是调用处理程序本身的 OID。调用处理程序必须使用此字段来确定要执行的函数。此外,传递的参数列表是根据目标函数的声明而不是调用处理程序的声明设置的。
由调用处理程序从pg_proc
系统目录并分析被调用函数的参数和返回类型。这作为
从条款创建函数
该功能的命令将在prorc
的列pg_proc
排。这通常是过程语言中的源文本,但理论上它可能是其他内容,例如文件的路径名,或任何其他告诉调用处理程序详细内容的内容。
通常,每个 SQL 语句都会多次调用同一个函数。调用处理程序可以避免重复查找有关被调用函数的信息,方法是使用flinfo->fn_extra
场地。这最初将是空值
, 但可以由调用处理程序设置为指向有关被调用函数的信息。在随后的调用中,如果flinfo->fn_extra
已经是非空值
然后可以使用它并跳过信息查找步骤。呼叫处理程序必须确保flinfo->fn_extra
指向至少会持续到当前查询结束的内存,因为管理信息
数据结构可以保持那么长。一种方法是在指定的内存上下文中分配额外的数据flinfo->fn_mcxt
;此类数据通常具有与管理信息
本身。但处理程序也可以选择使用寿命更长的内存上下文,以便它可以跨查询缓存函数定义信息。
当一个过程语言函数作为触发器被调用时,不会以通常的方式传递任何参数,但是FunctionCallInfoBaseData
的语境
场点在触发数据
结构,而不是空值
就像在普通的函数调用中一样。语言处理程序应该为过程语言函数提供获取触发信息的机制。
提供了作为 C 扩展编写的过程语言处理程序的模板src/test/modules/plsample
.这是一个工作示例,演示了一种创建过程语言处理程序、处理参数和返回值的方法。
尽管提供调用处理程序足以创建最小的过程语言,但可以选择提供另外两个函数以使语言更方便使用。这些是一个验证器和内联处理程序.可以提供一个验证器以允许在运行期间进行特定于语言的检查创建函数.可以提供一个内联处理程序以允许该语言支持通过做命令。
如果验证器由过程语言提供,则必须将其声明为采用单个参数类型的函数样的
.验证器的结果被忽略,因此习惯上声明返回空白
.验证器将在结束时调用创建函数
已创建或更新以过程语言编写的函数的命令。传入的 OID 是函数的 OIDpg_proc
排。验证器必须以通常的方式获取这一行,并进行任何适当的检查。首先,打电话CheckFunctionValidatorAccess()
诊断用户无法通过验证程序实现的显式调用创建函数
。然后,典型检查包括验证函数的参数和结果类型是否受语言支持,以及函数体在语言中的语法是否正确。如果验证器发现函数没有问题,它应该返回。如果发现错误,应通过正常的ereport()
错误报告机制。抛出错误将强制事务回滚,从而防止提交错误的函数定义。
验证器函数通常应该遵循检查_作用_身体参数:如果关闭,则应跳过任何昂贵或上下文敏感的检查。如果语言在编译时提供代码执行,那么验证器必须抑制可能导致这种执行的检查。特别是,该参数由pg关闭_转储,以便加载过程语言函数,而不必担心函数体对其他数据库对象的副作用或依赖性。(由于这一要求,调用处理程序应该避免假设验证器已经完全检查了该函数。拥有验证器的目的不是让调用处理程序忽略检查,而是在函数中出现明显错误时立即通知用户。)创建函数
命令。)虽然检查内容的选择主要由验证器函数自行决定,但请注意创建函数
代码只执行设置
附加在函数上的子句检查功能
正在播放。因此,如果检查结果可能会受到GUC参数的影响,则在检查功能
关闭,以避免重新加载转储时出现错误故障。
如果内联处理程序是由过程语言提供的,则必须将其声明为使用单个类型参数的函数内部的
。内联处理程序的结果被忽略,因此通常会声明为返回无效的
。当做
语句的执行指定了过程语言。实际传递的参数是指向内联码块
结构,其中包含有关做
语句的参数,尤其是要执行的匿名代码块的文本。内联处理程序应该执行此代码并返回。
建议您包装所有这些函数声明,以及创造语言
命令自己进入一个扩大所以一个简单的创建扩展
命令足以安装该语言。看见第38.17节有关编写扩展名的信息。
在尝试编写自己的语言处理程序时,标准发行版中包含的过程语言是很好的参考。调查src/pl
源树的子目录。这个创造语言参考页也有一些有用的细节。