【介绍php源码】【e语言仓库源码】【易语言源码句柄】pg源码行数

时间:2024-12-23 05:40:26 分类:获取网页api源码 来源:aosp源码阅读工具

1.linux joe命令详解
2.pg插件5人限制怎么解决
3.GnuPG命令行
4.PGP工作原理
5.PGRelief的源码功能?
6.PostgreSQL内核Trigger的一生

pg源码行数

linux joe命令详解

       joe命令用于编辑文本文件,是行数一个功能强大的全屏幕文本编辑程序,操作的源码复杂度要比Pico高一点,但是行数功能较为齐全,joe一次可开启多个文件,源码每个文件各放在一个编辑区内,行数介绍php源码并可在文件之间执行剪贴的源码动作。

       语法:joe [-asis][-beep][-csmode][-dopadding][-exask][-force][-help][-keepup][-lightoff][-arking][-mid][-nobackups][-nonotice][-nosta][-noxon][-orphan][-backpath<目录>][-columns<栏位>][-lines<行数>][-pg<行数>][-skiptop<行数>][-autoindent crlf linums overwrite rdonly wordwrap][+<行数>][-indentc<缩排字符>][-istep<缩排字符数>][-keymap<按键配置文件>][-lmargin<栏数>][-rmargin<栏数>][-tab<栏数>][要编辑的行数文件]</p>

       参考例子:

       利用joe编辑C语言源代码txt.c:

       [root@linux ~]# joe txt.c

       参数:

       -columns 设置栏数

       -help 执行程序时一并显示帮助

       -lines 设置行数

       -marking 在选取区块时,反白区块会随着光标移动

       -nosta 程序执行时,源码不显示状态列

       -pg 按”PageUp”或”PageDown”换页时,行数所要保留前一页的源码行数

       -linums 在每行前面加上行号

pg插件5人限制怎么解决

       通过调整配置或编写特定代码来解决pg插件的5人限制。

       一、行数了解限制原因

       pg插件的源码5人限制可能是由插件本身的设置或者服务器端的配置所设定的。在解决限制之前,行数需要明确这一限制的源码具体来源。

       二、查找配置调整方法

       对于大部分的插件,其限制人数都可以通过调整插件的配置文件来解决。你可以查看pg插件的官方文档或者相关的配置说明,寻找是否有关于人数限制的设定,并进行相应的调整。

       三、编写代码解决限制

       如果通过配置无法调整人数限制,那么可能需要通过编写代码来实现。这需要具备一定的编程能力,并且需要了解pg插件的源代码或相关接口。你可以尝试联系插件的开发者或者寻求技术社区的帮助,获取相关的e语言仓库源码指导和建议。

       四、注意事项

       1. 在调整任何配置或编写代码之前,请确保你了解操作的风险,并备份好相关的文件和配置。

       2. 如果你不确定如何操作,最好寻求专业人士的帮助,避免因为误操作导致系统出现问题。

       3. 在解决限制的同时,也要考虑到系统的稳定性和安全性,不要盲目追求人数的增加而忽视了其他重要的因素。

       以上内容是对如何解决pg插件5人限制的具体解释,希望对你有所帮助。

GnuPG命令行

       GnuPG (Gnu Privacy Guard) 是一个自由且开源的加密工具,版本为1.4.1。它由Free Software Foundation提供,且完全无任何保证。这个程序支持公钥加密,如RSA、RSA-E、RSA-S、ELG-E和DSA,以及对称加密算法,如3DES、CAST5、BLOWFISH、AES、AES、易语言源码句柄AES和TWOFISH。散列算法包括MD5、SHA1、RIPEMD、SHA、SHA和SHA。同时,它还支持压缩功能,如不压缩、ZIP、ZLIB和BZIP2。

       在命令行操作中,gpg的基本语法是gpg [选项] [文件名],其默认行为根据输入数据自动决定。一些主要的命令和选项包括:

       -s, --sign [文件名]:用于生成一个文件的签名。

       --clearsign [文件名]:生成一个明文签名的文件。

       -b, --detach-sign:创建可分离的签名。

       -e, --encrypt:加密数据。

       -c, --symmetric:仅使用对称加密。

       -d, --decrypt:解密数据(默认)。

       --verify:验证签名。

       --list-keys:列出密钥。

       --export:导出密钥。

       --import:导入或合并密钥。

       范例中,如要为Bob签名并加密文件,可以使用命令:`-se -r Bob [file]`。个人记账系统源码对于密钥管理,你可以通过`--edit-key`进行编辑,`save`保存并退出,`help`查看帮助信息,以及`fpr`、`list`等选项来查看和操作密钥信息。

扩展资料

       GnuPG(GNU Privacy Guard或GPG)是一个以GNU通用公共许可证释出的开放源码用于加密或签名的软件,可用来取代PGP。大多数gpg软件仅支持命令行方式,一般人较难掌握。由于gpg软件开放源代码,很难隐藏后门,因此比pgp等商业软件安全。

PGP工作原理

       PGP是一个基于RSA公匙加密体系的邮件加密软件。可以用它对你的邮件保密以防止非授权者阅读,它还能对你的邮件加上数字签名从而使收信人可以确信邮件是你发来的。它让你可以安全地和你从未见过的人们通讯,事先并不需要任何保密的渠道用来传递密匙。它采用了:审慎的密匙管理,一种RSA和传统加密的杂合算法,用于数字签名的邮件文摘算法,加密前压缩等,还有一个良好的人机工程设计。它的功能强大有很快的速度。而且它的源代码是免费的。

       å®žé™…上PGP的功能还不止上面说的:;PGP可以用来加密文件,还可以用PGP代替UUencode;生成;RADIX;;格式(就是MIME;的;BASE;格式)的编码文件。

       PGP;的创始人是美国的;Phil;Zimmermann。他的创造性在于他把RSA公匙体系的方便和传统加密体系的高速度结合起来,并且在数字签名和密匙认证管理机制上有巧妙的设计。因此PGP成为几乎最流行的公匙加密软件包。

       PGP是一种供大众使用的加密软件。加密是为了安全,私密权是一种基本人权。在现代社会里,电子邮件和网络上的文件传输已经成为生活的一部分。邮件的安全问题就日益突出了,大家都知道在Internet上传输的数据是不加密的。如果你自己不保护自己的信息,第三者就会轻易获得你的隐秘。;还有一个问题就是信息认证,如何让收信人确信邮件没有被第三者篡改,就需要数字签名技术。RSA公匙体系的特点使它非常适合用来满足上述两个要求:

       ä¿å¯†æ€§ï¼ˆPrivacy)和认证性(Authentication)。

       RSA(Rivest-Shamir-Adleman)算法是一种基于大数不可能质因数分解假设的公匙体系。简单地说就是找两个很大的质数,一个公开给世界,一个不告诉任何人。一个称为“公匙”,另一个叫“私匙”(Public;key;&;Secretkey;or;Private;key)。这两个密匙是互补的,就是说用公匙加密的密文可以用私匙解密,反过来也一样。假设甲要寄信给乙,他们互相知道对方的公匙。甲就用乙的公匙加密邮件寄出,乙收到后就可以用自己的私匙解密出甲的原文。由于没别人知道乙的私匙所以即使是甲本人也无法解密那封信,这就解决了信件保密的问题。另一方面由于每个人都知道乙的公匙,他们都可以给乙发信,那么乙就无法确信是不是甲的来信。认证的问题就出现了,这时候数字签名就有用了。

       åœ¨è¯´æ˜Žæ•°å­—签名前先要解释一下什么是“邮件文摘”(message;digest),单地讲就是对一封邮件用某种算法算出一个能体现这封邮件“精华”的数来,一旦邮件有任何改变这个数都会变化,那么这个数加上作者的名字(实际上在作者的密匙里)还有日期等等,就可以作为一个签名了。确切地说PGP是用一个位的二进制数作为“邮件文摘”的,用来产生它的算法叫MD5(message;digest;5),MD5的提出者是Ron;Rivest,PGP中使用的代码是由Colin;Plumb编写的,MD5本身是公用软件。所以PGP的法律条款中没有提到它。MD5是一种单向散列算法,它不像CRC校验码,很难找到一份替代的邮件而与原件具有一样的“精华”。

       å›žåˆ°æ•°å­—签名上来,甲用自己的私匙将上述的位的“精华”加密,附加在邮件上,再用乙的公匙将整个邮件加密。这样这份密文被乙收到以后,乙用自己的私匙将邮件解密,得到甲的原文和签名,乙的PGP也从原文计算出一个位的 “精华”来再用甲的公匙解密签名得到的数比较,如果符合就说明这份邮件确实是甲寄来的。这样两个要求都得到了满足。

       PGP还可以只签名而不加密,这适用于公开发表声明时,声明人为了证实自己的身份(在网络上只能如此了),可以用自己的私匙签名。这样就可以让收件人能确认发信人的身份,也可以防止发信人抵赖自己的声明。这一点在商业领域有很大的应用前途,它可以防止发信人抵赖和信件被途中篡改。

       é‚£ä¹ˆä¸ºä»€ä¹ˆè¯´PGP用的是RSA和传统加密的杂合算法呢?因为RSA算法计算量极大在速度上不适合加密大量数据,所以PGP实际上用来加密的不是RSA本身,而是采用了一种叫IDEA的传统加密算法。我先解释一下什么叫传统加密,简单地说就是用一个密匙加密明文,然后用同样的密匙解密。这种方法的代表是DES(US;Fed eral;DataEncryption;Standard),也就是乘法加密,它的主要缺点就是密匙的传递渠道解决不了安全性问题,不适合网络环境邮件加密需要。

       -1- : 回复

       æ„å¤§åˆ©

       lvchenyang_

       ä½ç²‰ä¸

        2楼

       IDEA;是一个有专利的算法,专利持有者是ETH和一个瑞士公司:Ascom-Tech;AG。

       éžå•†ä¸šç”¨é€”çš„IDEA实现不用向他们交纳费用。IDEA的加(解)密速度比RSA快得多,所以实际上PGP是用一个随机生成密匙(每次加密不同)用IDEA算法对明文加密,然后用RSA算法对该密匙加密。这样收件人同样是用RSA解密出这个随机密匙,再用IDEA解密邮件本身。这样的链式加密就做到了既有RSA体系的保密性,又有IDEA算法的快捷性。PGP的创意有一半就在这一点上了,为什么RSA体系年代就提出来,一直没有推广应用呢?速度太慢!那么PGP创意的另一半在哪儿呢?下面我再谈PGP的密匙管理。

       ä¸€ä¸ªæˆç†Ÿçš„加密体系必然要有一个成熟的密匙管理机制配套。公匙体制的提出就是为了解决传统加密体系的密匙分配难保密的缺点。比如网络hacker们常用的手段之一就是“监听”,如果密匙是通过网络传送就太危险了。举个例子:NovellNetware;的老版本中,用户的密码是以明文在线路中传输的,这样监听者轻易就获得了他人的密码。当然;Netware;4.1;中数据包头的用户密码现在是加密的了。对PGP来说公匙本来就要公开,就没有防监听的问题。但公匙的发布中仍然存在安全性问题,例如公匙的被篡改(Public;Key;Tampering),这可能是公匙密码体系中最大的漏洞,因为大多数新手不能很快发现这一点。你必须确信你拿到的公匙属于它看上去属于的那个人。为了把这个问题说清楚,我举个例子,然后再说如何正确地用PGP堵住这个漏洞。

       ä»¥ä½ å’ŒAlice的通信为例,假设你想给Alice发封信,那你必须有Alice的公匙,你从BBS上下载了Alice的公匙,并用它加密了信件用BBS的Email功能发给了Alice。不幸地,你和Alice都不知道,另一个用户叫Charlie的用户潜入BBS,把他自己用Alice的名字生成的密匙对中的公匙替换了Alice的公匙。那你用来发信的公匙就不是Alice的而是Charlie的,一切看来都很正常,因为你拿到的公匙的用户名是“Alice”。于是Charlie就可以用他手中的私匙来解密你给Alice的信,甚至他还可以用Alice真正的公匙来转发你给Alice的信,这样谁都不会起疑心,他如果想改动你给Alice的信也没问题。更有甚者,他还可以伪造Alice的签名给你或

       å…¶ä»–人发信,因为你们手中的公匙是伪造的,你们会以为真是Alice的来信。

       é˜²æ­¢è¿™ç§æƒ…况出现的最好办法是避免让任何其他人有机会篡改公匙,比如直接从Alice手中得到她的公匙,然而当她在千里之外或无法见到时,这是很困难的。PGP发展了一种公匙介绍机制来解决这个问题。举例来说:如果你和Alice有一个共同的朋友David,而David知道他手中的Alice的公匙是正确的(关于如何认证公匙,PGP还有一种方法,后面会谈到,这里假设David已经和Alice认证过她的公匙)。这样David可以用他自己的私匙在Alice的公匙上签名(就是用上面讲的签名方法),表示他担保这个公匙属于Alice。当然你需要用David的公匙来校验他给你的Alice的公匙,同样David也可以向Alice认证你的公匙,这样David就成为你和Alice之间的“介绍人”。这样Alice或David就可以放心地把David签过字的Alice的公匙上载到BBS上让你去拿,没人可能去篡改它而不被你发现,即使是BBS的管理员。 这就是从公共渠道传递公匙的安全手段。

       æœ‰äººä¼šé—®ï¼šé‚£ä½ æ€Žä¹ˆå®‰å…¨åœ°å¾—到David的公匙呢,这不是个先有鸡还是先有蛋的问题吗?确实有可能你拿到的David的公匙也是假的,但这就要求这个捣蛋者参与这整个过程,他必须对你们三人都很熟悉,还要策划很久,这一般不可能。当然,PGP对这种可能也有预防的建议,那就是由一个大家普遍信任的人或机构担当这个角色。他被称为“密匙侍者”或“认证权威”,每个由他签字的公匙都被认为是真的,这样大家只要有一份他的公匙就行了,认证这个人的公匙是方便的,因为他广泛提供这个服务,假冒他的公匙是很极困难的,因为他的公匙流传广泛。 这样的“权威”适合由非个人控制组织或政府机构充当,现在已经有等级认证制度的机构存在。

       -1- : 回复

       æ„å¤§åˆ©

       lvchenyang_

       ä½ç²‰ä¸

        3楼

       å¯¹äºŽé‚£äº›éžå¸¸åˆ†æ•£çš„人们,PGP更赞成使用私人方式的密匙转介方式,因为这样有机的非官方更能反映出人们自然的社会交往,而且人们也能自由地选择信任的人来介绍。总之和不认识的人们见面一样。每个公匙有至少一个“用户名”(User;ID),请尽量用自己的全名,最好再加上本人的Email地址,以免混淆。

       æ³¨æ„ï¼ä½ æ‰€å¿…须遵循的一条规则是:在你使用任何一个公匙之前,一定要首先认证它!!!无论你受到什么诱惑,当然会有这种诱惑,你都不要,绝对不要, 直接信任一个从公共渠道(由其是那些看起来保密的)得来的公匙,记得要用熟人介绍的公匙,或者自己与对方亲自认证。同样你也不要随便为别人签字认证他们的公匙,就和你在现实生活中一样,家里的房门钥匙你是只会交给信任的人的。

       ä¸‹é¢ï¼Œæˆ‘讲讲如何通过电话认证密匙。每个密匙有它们自己的标识(keyID),keyID是一个八位十六进制数,两个密匙具有相同keyID的可能性是几十亿分之一,

       è€Œä¸”PGP还提供了一种更可靠的标识密匙的方法:“密匙指纹”(key"s;fingerprint)。每个密匙对应一串数字(十六个八位十六进制数),这个数字重复的可能就更微乎其微了。而且任何人无法指定生成一个具有某个指纹的密匙,密匙是随机生成的,从指纹也无法反推出密匙来。这样你拿到某人的公匙后就可以和他在电话上核对这个指纹,从而认证他的公匙。如果你无法和Alice通电话的话,你可以和David通电话认证David的公匙,从而通过David认证了Alice的公匙,这就是直接认证和间接介绍的结合。

       è¿™æ ·åˆå¼•å‡ºä¸€ç§æ–¹æ³•ï¼Œå°±æ˜¯æŠŠå…·ä¸åŒäººç­¾åçš„自己的公匙收集在一起,发送到公共场合,这样可以希望大部分人至少认识其中一个人,从而间接认证了你的公匙。同样你签了朋友的公匙后应该寄回给他,这样就可以让他可以通过你被你其他朋友认证。有点意思吧,和现实社会中人们的交往一样。PGP会自动为你找出你拿到的公匙中有哪些是你的朋友介绍来的,那些是你朋友的朋友介绍来的,哪些则是朋友的朋友的朋友介绍的……它会帮你把它们分为不同的信任级别,让你参考决定对它们的信任程度。你可以指定某人有几层转介公匙的能力,这种能力是随着认证的传递而递减的。

       è½¬ä»‹è®¤è¯æœºåˆ¶å…·æœ‰ä¼ é€’性,这是个有趣的问题。PGP的作者Phil;Zimmermann。

       æœ‰å¥è¯ï¼š;“;信赖不具有传递性;我有个我相信决不撒谎的朋友。可是他是个认定总统不撒谎的傻瓜,可很显然我并不认为总统决不撒谎。”

       å…³äºŽå…¬åŒ™çš„安全性问题是PGP安全的核心,我在这里就不细说了。和传统单密匙体系一样,私匙的保密也是决定性的。相对公匙而言,私匙不存在被篡改的问题,但存在泄露的问题。RSA的私匙是很长的一个数字,用户不可能将它记住,PGP的办法是让用户为随机生成的RSA私匙指定一个口令(pass;phase)。只有通过给出口令才能将私匙释放出来使用,用口令加密私匙的方法保密程度和PGP本身是一样的。所以私匙的安全性问题实际上首先是对用户口令的保密。当然私匙文件本身失密也很危险,因为破译者所需要的只是用穷举法试探出你的口令了,虽说很困难但毕竟是损失了一层安全性。在这里只用简单地记住一点,要像任何隐私一样保藏你的私匙,不要让任何人有机会接触到它。

       PGP在安全性问题上的精心考虑体现在PGP的各个环节。比如每次加密的实际密匙是个随机数,大家都知道计算机是无法产生真正的随机数的。PGP程序对随机数的产生是很审慎的,关键的随机数像RSA密匙的产生是从用户瞧键盘的时间间隔上取得随机数种子的。对于磁盘上的;randseed.bin;文件是采用和邮件同样强度的加密的。这有效地防止了他人从你的randseed.bin文件中分析出你的加密实际密匙的规律来。

       åœ¨è¿™é‡Œæˆ‘提一下PGP的加密前预压缩处理,PGP内核使用PKZIP算法来压缩加密前的明文。一方面对电子邮件而言,压缩后加密再经过7bits编码密文有可能比明文更短,这就节省了网络传输的时间。另一方面,明文经过压缩,实际上相当于经过一次变换,信息更加杂乱无章,对明文攻击的抵御能力更强。PGP中使用的PKZIP算法是经过原作者同意的。PKZIP算法是一个公认的压缩率和压缩速度都相当

       å¥½çš„压缩算法。在PGP中使用的是PKZIP;2.0版本兼容的算法。

       å¥½äº†ï¼Œå…³äºŽPGP安全性的问题我会在《PGP的安全性》一文中专门介绍。我上面讲了这么多只是为了让大家知道PGP会是非常安全的,只要你自己遵循正确的使用方法。关于PGP的安装和使用请参考《PGP;2.6.3i的安装与使用》一文。如果在看英文文档时有些不太明白的词汇,请试试能不能从《PGP名词解释》一文中找到线索。PGP;2.6.3i是我推荐大家使用的PGP版本,有关这个版本的详细问题请参见《PGPi;问答集》一文。

       åœ¨ä»Šå¤©çš„Internet上随处可见用PGP签名的文章,PGP的版本也在飞快地更新,据说PGP;3.0;再有几个月就要推出了。世界上越来越多的人们在使用PGP,我们中国人也应该重视保护自己合法的私密权。我翻译整理这几篇文章就是为了在国内宣传推广PGP的使用。尽管它还是个新生事物,可是我们要看到在网际空间(CyberSpace)中它肯定能迅速成长起来,中国虽然起步晚,但比美国也差不太多,我们应该迎头赶上。

PGRelief的功能?

       丰富的代码检查功能

       PGRelief对C/C++的源程序进行检查,既能指出单纯的编码失误,也能指出复杂的逻辑错误。此外,对不正确的内存访问、内存泄漏、内存释放以及性能恶化等问题也能进行检查。同时,能够对已确定不是问题的地方不再重复检查,以此来减轻开发人员的负担。

       代码评审辅助功能

       n

       可以通过PGRelief的GUI查看检查结果

       n

       可以选择输出认为需要的检查结果

       n

       屏蔽不需要的检查结果

       n

       对关注的检查点进行自由分组

       提供了易用的用户接口,可以高效率地进行各种检查的验证作业。

       例如,可以按照检查的论坛首页源码修改类别(可靠性、可维护性、可移植性、效率性等),或检查点编号进行过滤,从而仅显示希望调查的检查结果。另外,通过简单的操作就可以显示对应的代码内容及检查点的含义、处理方法等。

       编码规范检查功能

       检查源程序是否符合以下编码规范的要求,并指出违反的相应规范之处。通过确保源程序符合这些规范,使程序品质具备坚实基础。

       n

       IPA/SEC

       n

       MISRA-C(//)/MISRA-C++()(可选产品)

       n

       ISO

       复杂度度量功能

       不仅对程序中的问题进行检查,还可以对程序的控制结构等指标进行测量。基于该测量结果,可以计算出函数的复杂度。将这些复杂度作为程序开发的指标,可以推进更高品质的软件开发。

       n

       对十余种度量值进行计算

       包括对代码行数、注释以外行数、最大嵌套层数、MaCabe的TYPE1和TYPE2两种复杂度等多种程序复杂度度量值。

       注:McCabe是什么?

       McCabe是基于对程序拓扑结构复杂度的分析的一种度量方法。包括TYPE1圈复杂度和TYPE2基本复杂度。

       n

       可以自由设定各个度量值的阈值

       及时避免引入过分复杂的代码,有效降低程序整体复杂度。

       命名规则检查功能

       可以对函数名或变量名的命名规则进行定义和检查。

       统计功能

       可以对项目中的所有源代码的检查结果数据进行统计,并保存到文件。

PostgreSQL内核Trigger的一生

       本文简要介绍 PostgreSQL 数据库的 Trigger 从创建、存储、触发、执行、修改到删除的过程,贯穿 Trigger 的一生。

       文中引用的函数、结构体来源于 PG 源码,分支为 REL__STABLE,对应的 commit id 如下。此外还引用了 PG 官方文档。

       触发器简介

       Trigger 即触发器,它可以在特定事件发生时,对数据库中的对象执行特定操作:

       根据触发事件的不同,PG 的触发器分为两类:

       不同数据库中触发器的分类有所不同,比如 Oracle 分为 DML Trigger 和 System Trigger,SQL Server 分为 DML Trigger、DDL Trigger 和 Login Trigger,不论其如何划分,多数都可以与 PG 的触发器对应上。

       创建触发器语法

       首先介绍创建触发器的 SQL 和 PLpgSQL 语法。

       Trigger

       根据 PG 官方文档,创建 Trigger 的语法如下:

       下面以表 t1、t2 为例创建一个简单的触发器示例。表的定义如下:

       触发器定义如下,是表 t1 上的行级触发器,对 t1 进行 INSERT 之后会触发,并执行 insert_into_t2 函数,将插入到 t1 的数据也插入到 t2。

       insert_into_t2 函数定义如下,其中引用了上下文信息 NEW,表示插入到 t1 的数据,并将其插入到 t2。

       Event Trigger

       创建 Event Trigger 的语法如下,相比 Trigger 的语法要简单很多

       以下是 PG 官方文档中的一个简单示例,该 Event Trigger 可以在任何 DDL 语句执行之前触发,并抛出异常,禁止执行任何 DDL 语句。

       创建流程

       简单介绍创建触发器时 PG 内核中的函数调用流程。

       Trigger

       CREATE TRIGGER 命令都属于 DDL 语句,所以会进入 DDL 的处理流程,关键的调用路径为: ProcessUtilitySlow-->CreateTrigger-->CreateTriggerFiringOn,CreateTriggerFiringOn 函数代码超过 行,因此只介绍其中的关键步骤:

       Event Trigger

       CREATE EVENT TRIGGER 的关键调用路径为: standard_ProcessUtility-->CreateEventTrigger,该函数流程相对简单很多:

       触发器的存储

       用户创建的触发器必须持久化到数据库中,具体的存储位置是触发器相关的系统表中。

       Trigger

       Trigger 存储在 pg_trigger 系统表中,表中的关键字段如下,包含触发器所在的表、触发器名、触发器调用的函数、是否可推迟等属性。总之,通过 CREATE TRIGGER 创建触发器时指定的任何信息都会存储到系统表中。

       pg_trigger 系统表的各个字段在内存中用Trigger 结构体表示,定义如下,可见其成员变量与 pg_trigger 的属性是一一对应的。

       在内存中的 relcache(表缓存)中也同样保存有 Trigger 的信息:

       Event Trigger

       Event Trigger 存储在 pg_event_trigger 系统表中,关键字段如下,包含触发器名、调用的函数等信息。与 Trigger 不同的是,这里并不包含触发器所在的表,因为 Event Trigger 不属于任何一个表。

       触发过程

       触发器会在特定事件场景下被触发,它识别这些事件的方式也很简单,就是在对应事件的代码处调用触发器函数。

       Trigger

       对于普通的触发器,触发时机是 INSERT、UPDATE、DELETE 等操作之前或者之后,所以在 PG 的执行器阶段触发,多数在 ProcessQuery-->ExecutorRun-->ExecModifyTable 函数中

       我们将执行触发操作的函数称为“触发器的执行函数”,各类触发器的执行函数命名格式比较统一,在此列举几种:

       以ExecBRInsertTriggers 为例说明触发过程:

       Event Trigger

       事件触发器支持的事件仅有 ddl_command_start、ddl_command_end、table_rewrite 和 sql_drop 这四类,分别对应四个执行函数,其触发时机说明如下:

       以 EventTriggerDDLCommandStart 为例说明触发过程:

       调用功能函数

       用户在创建触发器的 EXECUTE { FUNCTION | PROCEDURE } function_name 语句中指定了该触发器要执行的功能函数。在触发器被触发后,会执行该函数。

       Trigger

       在执行器阶段触发时,ResultRelInfo 结构体中存有表上的各项信息,其中就包括表上的触发器、函数等,所以直接从中就可以拿到触发器信息。关键结构体为 ResultRelInfo、TriggerDesc、Trigger,其嵌套关系如下:

       将ResultRelInfo 中获取的 Trigger 结构体的全部内容都填充到 TriggerData 结构体,ExecCallTriggerFunc 函数再从 TriggerData 中获取函数 oid,并执行该函数。

       TriggerData 结构体定义如下,其中除了 Trigger 以外还保存了各种执行上下文信息,heap 表信息等,与函数的执行有关。

       TriggerData 最终会保存到PLpgSQL_execstate 中,这是 PLpgSQL 执行过程中的一个重要结构体:

       触发器的功能函数执行的方法与普通的 PLpgSQL 函数、存储过程执行方法是类似的,关键调用路径是: ExecCallTriggerFunc-->plpgsql_call_handler-->plpgsql_exec_trigger-->exec_toplevel_block-->exec_stmt_block-->…………

       Event Trigger

       对于事件触发器,在触发阶段的EventTriggerCommonSetup 函数中,通过 EventCacheLookup 从缓存中查找触发器功能函数,然后在 EventTriggerInvoke 中根据触发器函数的 oid 进行调用。

       EventTriggerCommonSetup 中还会填充 EventTriggerData 结构体,其中保存了调用过程中的一些关键信息:

       与普通触发器的 TriggerData 结构一样,EventTriggerData 结构体也会保存到PLpgSQL_execstate 中,在 PLpgSQL 执行过程中使用:

       事件触发器的功能函数实际执行步骤与普通触发器也基本相同,关键调用路径为: ExecCallTriggerFunc-->plpgsql_call_handler-->plpgsql_exec_event_trigger-->exec_toplevel_block-->exec_stmt_block-->…………

       修改触发器

       使用 ALTER 语句修改触发器的定义

       Trigger

       根据 PG 官方文档,ALTER TRIGGER 的语法如下:

       仅支持重命名和修改依赖的插件。

       重命名触发器的关键调用流程为:standard_ProcessUtility-->ExecRenameStmt-->renametrig,基本原理也是读取 pg_trigger 系统表的信息,修改以后写回系统表。

       修改触发器依赖插件的关键调用流程为:standard_ProcessUtility-->ExecAlterObjectDependsStmt,会修改 pg_depend 系统表。

       Event Trigger

       根据 PG 官方文档,ALTER EVENT TRIGGER 语法为:

       支持对事件触发器进行重命名、禁用、启用、修改 owner 的操作。

       ALTER TRIGGER 的关键函数是AlterEventTrigger,其内容较为简单:

       删除触发器

       使用 DROP 语句删除触发器

       Trigger

       PG 文档中 DROP TRIGGER 语法如下:

       删除触发器的关键函数是RemoveTriggerById,调用流程如下: ProcessUtilitySlow-->ExecDropStmt-->RemoveObjects-->performMultipleDeletions-->deleteObjectsInList-->deleteOneObject-->doDeletion-->RemoveTriggerById

       RemoveTriggerById 函数流程:

       Event Trigger

       PG 文档中 DROP EVENT TRIGGER 语法如下:

       删除事件触发器的关键函数是DropObjectById,这是一个公用的函数,可以删除多种类型的对象。

       调用流程如下: ProcessUtilitySlow-->ExecDropStmt-->RemoveObjects-->performMultipleDeletions-->deleteObjectsInList-->deleteOneObject-->doDeletion-->DropObjectById