Vastbase编程利器:PL/pgSQL原理简介

PL/pgSQL是Vastbase提供的一种过程语言,在普通SQL语句的使用上增加了编程语言的特点,可以用于创建函数、存储过程、触发器过程以及创建匿名块等。

本文介绍Vastbase中PL/pgSQL的执行流程,包括PL/pgSQL的编译运行


1、编译

PL/pgSQL的编译部分核心是解释出可以被内核识别的变量、命名空间和语句节点链表

1.1 编译上下文

typedef struct PLpgSQL_compile_context {
    struct PLpgSQL_datum** plpgsql_Datums;
    struct PLpgSQL_function* plpgsql_curr_compile;
    struct PLpgSQL_nsitem* ns_top;
}

PLpgSQL_compile_context结构用来保存编译期间的上下文信息,其核心成员是plpgsql_Datums、ns_top和plpgsql_curr_compile。

  • plpgsql_Datums:保存识别出的变量,是一个数组
  • ns_top:保存识别出的命名空间,是一个链表
  • plpgsql_curr_compile:保存识别出的语句节点链表

1.2 变量数组

typedef struct PLpgSQL_datum { /* Generic datum array item */
    int dtype; /* 变量类型 */
    int dno; /* 变量在变量数组的下标,即变量是变量数组的第几个元素 */
} PLpgSQL_datum;

PL/pgSQL支持多种类型的变量,包括普通的变量、表达式、复合类型和数组类型等。不同的变量类型用相应的结构表示,例如:普通变量使用PLpgSQL_var表示,表达式使用PLpgSQL_expr表示等。

Vastbase使用面向对象的思想,设计PL/pgSQL的变量,PLpgSQL_datum结构表示变量的抽象父类,共有4个结构体成员,PLpgSQL_var和PLpgSQL_expr等表示子类,子类结构的前4个成员与PLpgSQL_datum结构保持一致。

PL/pgSQL变量的来源主要有:

  • 函数的入参
  • 声明部分声明的变量
  • 内置变量,例如found变量和游标变量等

1.3 命名空间链表

typedef struct PLpgSQL_nsitem { /* Item in the compilers namespace tree */
    int itemtype; /* 命名空间类型 */
    int itemno; /* 命名空间关联的变量在变量数组的下标 */
    struct PLpgSQL_nsitem* prev; /* 指向上一个命名空间 */
    char name[FLEXIBLE_ARRAY_MEMBER]; /* 命名空间字符串 */
} PLpgSQL_nsitem;

PL/pgSQL里,命名空间(namespace)表示变量或标签的名称。主要有以下类型的命名空间:

PL/pgSQL在运行语句时,通过标识符查找命名空间链表,若查找到命名空间,则根据命名空间的itemno在变量数组里获取变量,进行相应的操作。

1.4 语法解析

Vastbase的PL/pgSQL有独立的词法分析和语法分析器。PL/pgSQL主要有两种大类的块:声明块语句块

声明块

声明块是以DECLARE关键字作为开始标记以BEGIN关键字作为结束标记的语句块

在声明块内可以声明变量和定义类型。新定义的类型会被记录到系统表元信息中。声明的变量会被记录到变量数组和命名空间链表里,对于复合类型的变量,PL/pgSQL会对其进行展开,即会创建${变量名}.${属性}这样的变量和命名空间。

语句块

语句块是指以BEGIN关键字作为开始标记,以END关键字作为结束标记的语句块

语句块内可以嵌套新的声明块和语句块。内层语句块可以访问外层声明块的类型和变量,反之不允许。

语句块以分号作为语句分隔符,每个语句都会被解析为不同类型的语句节点。

typedef struct { /* One EXCEPTION ... WHEN clause */
    PLpgSQL_condition* conditions;
    List* action; /* List of statements */
} PLpgSQL_exception;

typedef struct PLpgSQL_stmt_block {
    List* body; /* List of statements */
    PLpgSQL_exception_block* exceptions;
} PLpgSQL_stmt_block;

PL/pgSQL使用PLpgSQL_stmt_block结构表示经过语法解析后的PL/pgSQL语句块,PLpgSQL_stmt_block结构有两个核心的成员,分别是body和exceptions。

body是语句块内正常运行的语句节点链表。

exceptions是PLpgSQL_exception类型变量链表。

当语句节点链表内的语句发生异常时,进入exceptions成员表示的异常处理流程。PLpgSQL_exception结构里,conditions成员表示该异常处理块的异常类型,action成员就是该类型异常的处理语句节点链表,当运行时发生了匹配conditions的异常,则执行该异常的action进行异常处理。

PL/pgSQL支持的语句类型比较丰富,以下是一些常用的语句类型归类:

  • 嵌套语句块:PLPGSQL_STMT_BLOCK
  • 赋值语句:PLPGSQL_STMT_ASSIGN
  • 条件分支:PLPGSQL_STMT_IF/PLPGSQL_STMT_GOTO/PLPGSQL_STMT_CASE
  • 循环控制:PLPGSQL_STMT_LOOP/PLPGSQL_STMT_WHILE/PLPGSQL_STMT_FORI/PLPGSQL_STMT_FORS/PLPGSQL_STMT_FORC/PLPGSQL_STMT_FOREACH_A/PLPGSQL_STMT_EXIT
  • 返回语句:PLPGSQL_STMT_RETURN/PLPGSQL_STMT_RETURN_NEXT/PLPGSQL_STMT_RETURN_QUERY
  • 打印输出:PLPGSQL_STMT_RAISE
  • 执行语句:PLPGSQL_STMT_EXECSQL/PLPGSQL_STMT_DYNEXECUTE/PLPGSQL_STMT_DYNFORS/PLPGSQL_STMT_PERFORM
  • 游标相关:PLPGSQL_STMT_OPEN/PLPGSQL_STMT_FETCH/PLPGSQL_STMT_CLOSE
  • 事务控制:PLPGSQL_STMT_COMMIT/PLPGSQL_STMT_ROLLBACK/PLPGSQL_STMT_SAVEPOINT
  • 其他:PLPGSQL_STMT_GETDIAG/PLPGSQL_STMT_NULL/PLPGSQL_STMT_SIGNAL/PLPGSQL_STMT_RESIGNAL

1.5 编译缓存

PL/pgSQL的编译是一个耗时操作,每次运行前都重新编译对性能来说影响非常大。为解决这个问题,对于使用PL/pgSQL定义的函数/存储过程,Vastbase 把编译结果缓存在会话的内存中。在会话运行期间,如果函数/存储过程的定义没有发生变化,则只需要编译一次,后续函数/存储过程的运行会从缓存获取编译结果。

2、运行

PL/pgSQL运行依赖SPI(Server Programming Interface)机制,把需要运行的SQL语句发送到内核模块中,内核模块通过预定义的钩子函数对语句中引用的变量进行解析处理。

2.1 SPI机制

SPI机制提供了一系列接口连接并访问数据库内核,

PLPGSQL_STMT_EXECSQL语句节点的工作流程大致如下图:

  • 流程说明
  • SPI_connect:PL/pgSQL语句块执行前,连接到内核服务端,整个语句块的执行只需要连接一次
  • SPI_prepare_params:发送待执行的sql语句到服务端,获取执行计划
  • setup_param_list:设置语句的参数
  • SPI_execute_plan_with_paramlist:发送参数到服务的,执行语句
  • SPI_finish:断开与内核服务端的连接,释放资源

2.2 执行语句块

PL/pgSQL经过编译后,编译上下文保存了变量数组、命名空间链表和语句节点链表。如下图,执行语句实际上就是遍历语句节点链表,根据不同的语句节点类型,调用不同的处理函数。

2.3 异常处理

如下图所示,异常处理块实际上是通过PG_TRY/PG_CATCH/PG_END_TRY实现

当调用exec_stmt_block执行的语句块时,如果PLpgSQL_stmt_block的exceptions成员不为空,即定义了异常处理块,则使用PG_TRY/PG_CATCH/PG_END_TRY异常处理工具进行exec_stmts(block→body)的调动,捕获异常后,调用exec_stmts(exception→action)进行异常处理。

2.4 参数处理

PL/pgSQL内允许语句内引用声明块内声明的变量或函数入参,代码如下:

CREATE TABLE t_test(id INT);
DECLARE 
    id INT;
BEGIN
    id := 1;
    INSERT INTO t_test values (id);
END;
/

第6行的INSERT语句会被语法解析器解析成PLPGSQL_STMT_EXECSQL语句节点,PL/pgSQL会把整个语句原封不动发送到内核服务端中并生成计划,那么内核的语义分析模块就需要识别出括号内的id标识符是一个参数。

Vastbase通过钩子函数实现参数识别和值替换,代码如下:

struct ParseState {
    PreParseColumnRefHook p_pre_columnref_hook;
    PostParseColumnRefHook p_post_columnref_hook;
    ParseParamRefHook p_paramref_hook;
}
typedef struct ParamListInfoData {
    ParamFetchHook paramFetch; /* parameter fetch hook */
} ParamListInfoData;

通过设置ParseState结构p_post_columnref_hook钩子,内核在进行对写入字段进行语义分析时,会调用钩子函数,该钩子函数对命名空间链表进行查找,如果查找到则构造Param节点记录变量在PL/pgSQL变量里数组中的位置和类型,并挂载Query树上。

通过设置ParamListInfoData结构paramFetch钩子,内核在生成执行计划的预处理表达式阶段,调用该钩子,根据Param结构信息拿到该参数的在变量值,并把该Param结构替换为Const结构。

通过两个钩子函数,使得PL/pgSQL执行sql语句时,可以引用声明块内声明的变量或函数入参。

3、总结

通过上述介绍可以看出,Vastbase的PL/pgSQL模块与常规的编程语言类似,均支持赋值、条件分支、循环等多种语句类型,通过PL/pgSQL模块,可以在Vastbase服务端编写较为复杂的逻辑。其生命周期分为编译和运行两个阶段,使用PL/pgSQL编写函数/存储过程时,还通过缓存编译结果,使得函数调用变得更加高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/494962.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows入侵排查

目录 0x00 前言 0x01 入侵排查思路 1.1 检查系统账号安全 1.2 检查异常端口、进程 1.3 检查启动项、计划任务、服务 0x00 前言 当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时…

CQ 社区版2.10.0 | 新增 SQL 审核、全新英文版上线…

三月中旬,我们预告了 CloudQuery 社区版即将上线的「SQL 审核」功能。现在,它来了! 本次社区版 v2.10.0,除了 SQL 审核功能,我们还在手动授权、连接分组等模块做了新功能和优化。 新增功能 新增 SQL 审核功能 支持…

政安晨:【深度学习神经网络基础】(二)—— 神经元与层

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 神经元是深度学习神经网络中的基本单元,模拟了…

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot 0.前言一、准备二、制作引导文件1.BL312.SCP firmware (Crust)3.uboot 三、烧录四、运行 0.前言 之前买了块香橙派zero3,CPU是全志H618,四核cortex-A53,烧录了官方的ubuntu系统后就…

nodejs中使用WebScoket的简单示例

前言 WebScoket可以用来实现即时通信,一般用于通信聊天工具或者是需要实时接受数据等功能 在浏览器环境中,WebScoket是一个构造函数,需要new创建连接的实例; 在nodejs环境中,则需要使用ws模块来完成服务的创建。 示例 下面是可以直接使用的代码,不需要修改 node创建服务端…

Avalonia笔记4-Rider如何添加xaml支持

在Linux Rider中,File Type中是有XAML文件的,但是新增xaml文件并不能正确的添加到项目中,而且就算是新增文件,直接命名为“XXX.xaml”,也是没有智能提示的。 在引用Style文件的时候,需要新建一个axaml的文…

STM32H743驱动SSD1309(2)

接前一篇文章:STM32H743驱动SSD1309(1) 二、芯片详解 1. 概览 上一回已提到,SSD1309是一个单片CMOS OLED/PLED驱动芯片可以驱动有机/聚合发光二极管点阵图形显示系统。由128个segments和64个commons组成。该芯片专为共阴极OLED…

机器学习——聚类算法-KMeans聚类

机器学习——聚类算法-KMeans聚类 在机器学习中,聚类是一种无监督学习方法,用于将数据集中的样本划分为若干个簇,使得同一簇内的样本相似度高,不同簇之间的样本相似度低。KMeans聚类是一种常用的聚类算法之一,本文将介…

【设计经验】0Ω电阻在电路中有什么作用

电路设计与调试过程中,我们很多时候要用到0Ω电阻(如下图),那么0Ω电阻到底在这过程中充当了什么样的角色呢? 0R电阻在电路中有什么作用? #创作灵感#:脑海存留的如下几点疑惑需要解开。 1、电路初次设计使用串接电阻为什么是0R电阻; 2、单板调试时为什么有时候会用到0R…

VMware Live Recovery 9.0 发布 - 多云实时恢复

VMware Live Recovery 9.0 - 多云实时恢复 VMware Live Cyber Recovery VMware Live Site Recovery 请访问原文链接:https://sysin.org/blog/vmware-live-recovery/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.or…

Unity学习笔记 9.2D射线

下载源码 UnityPackage 1.Ray2D 让小球向右发射射线: Ray2D ray;void Start() {// Ray2D(起点,终点)ray new Ray2D(this.transform.position, Vector2.right);// Debug.DrawLine(起点,终点,颜色,显示时间)Debug.DrawL…

[实战]Springboot与GB28181摄像头对接。摄像头注册上线(一)

与支持国标摄像头对接 前言:不想看教程?1、准备阶段1.1、我们会学到什么?1.2、创建项目1.3、pom中用到的依赖1.4 打开摄像头的网址(了解配置方式) 2、代码编写2.1、增加项目配置2.2、在config目录下创建SipConfig2.3、在service目录下创建Sip…

如何在Windows 10中打开屏幕键盘?这里有详细步骤

本文解释了在Windows 10中打开或关闭屏幕键盘的不同方法,还解释了如何将屏幕键盘固定到开始菜单。 使用屏幕键盘的快捷键 如果你喜欢快捷方式,你会喜欢这个:按物理键盘上的Win+CTRL+O。这将立即显示屏幕键盘,而无需通过轻松使用。 ​提示:使用运行窗口也可以打开键盘。…

Tuxera for Mac2024软件产品密钥及下载安装教程

Tuxera for Mac在安全性和稳定性方面表现出色,为用户提供了可靠的数据保障和无忧的使用体验。 首先,从安全性角度来看,Tuxera for Mac采用了先进的技术来保护用户的数据。它支持快速全面的数据保护,通过智能缓存技术确保文件传输…

《手把手教你》系列技巧篇(五十七)-java+ selenium自动化测试-下载文件-下篇(详细教程)

1.简介 前边几篇文章讲解完如何上传文件,既然有上传,那么就可能会有下载文件。因此宏哥就接着讲解和分享一下:自动化测试下载文件。可能有的小伙伴或者童鞋们会觉得这不是很简单吗,还用你介绍和讲解啊,不说就是访问到…

图神经网络实战(6)——使用PyTorch构建图神经网络

图神经网络实战(6)——使用PyTorch构建图神经网络 0. 前言1. 传统机器学习与人工智能2. 人工神经网络基础2.1 人工神经网络组成2.2 神经网络的训练 3. 图神经网络4. 使用香草神经网络执行节点分类4.1 数据集构建4.2 模型构建4.3 模型训练 5. 实现香草图神…

聚观早报 | 比亚迪2023年营收;vivo X Fold3系列发布

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月28日消息 比亚迪2023年营收 vivo X Fold3系列发布 现代汽车拟投入68万亿韩元 华为P70系列最新渲染图 苹果A1…

Art Gallery Vol.2

Art Gallery Vol.2为您的游戏、VR项目和模拟器提供了一个很好的解决方案,图片库。 一个充满雕塑和框架的现代艺术画廊。它包括11件雕塑、14幅画作。适合收藏展览或画作展示。 所有画作都是独立的纹理,非常适合ArchViz、VR或任何类型的AAA游戏。 下载:​​Unity资源商店链接…

[linux] AttributeError: module ‘transformer_engine‘ has no attribute ‘pytorch‘

[BUG] AttributeError: module transformer_engine has no attribute pytorch Issue #696 NVIDIA/Megatron-LM GitHub 其中这个答案并没有解决我的问题&#xff1a; import flash_attn_2_cuda as flash_attn_cuda Traceback (most recent call last): File "<stdi…

国产数据库中统计信息自动更新机制

数据库中统计信息描述的数据库中表和索引的大小数以及数据分布状况&#xff0c;统计信息的准确性对优化器选择执行计划时具有重要的参考意义。本文简要整理了下传统数据库和国产数据库中统计信息的自动更新机制&#xff0c;以加深了解。 1、数据库统计信息介绍 优化器是数据库…