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

2024-03-28 10:28

本文主要是介绍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;
BEGINid := 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编写函数/存储过程时,还通过缓存编译结果,使得函数调用变得更加高效。

这篇关于Vastbase编程利器:PL/pgSQL原理简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855353

相关文章

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

数据库原理与安全复习笔记(未完待续)

1 概念 产生与发展:人工管理阶段 → \to → 文件系统阶段 → \to → 数据库系统阶段。 数据库系统特点:数据的管理者(DBMS);数据结构化;数据共享性高,冗余度低,易于扩充;数据独立性高。DBMS 对数据的控制功能:数据的安全性保护;数据的完整性检查;并发控制;数据库恢复。 数据库技术研究领域:数据库管理系统软件的研发;数据库设计;数据库理论。数据模型要素 数据结构:描述数据库

计算机组成原理——RECORD

第一章 概论 1.固件  将部分操作系统固化——即把软件永恒存于只读存储器中。 2.多级层次结构的计算机系统 3.冯*诺依曼计算机的特点 4.现代计算机的组成:CPU、I/O设备、主存储器(MM) 5.细化的计算机组成框图 6.指令操作的三个阶段:取指、分析、执行 第二章 计算机的发展 1.第一台由电子管组成的电子数字积分和计算机(ENIAC) 第三章 系统总线

GaussDB关键技术原理:高性能(二)

GaussDB关键技术原理:高性能(一)从数据库性能优化系统概述对GaussDB的高性能技术进行了解读,本篇将从查询处理综述方面继续分享GaussDB的高性能技术的精彩内容。 2 查询处理综述 内容概要:本章节介绍查询端到端处理的执行流程,首先让读者对查询在数据库内部如何执行有一个初步的认识,充分理解查询处理各阶段主要瓶颈点以及对应的解决方案,本章以GaussDB为例讲解查询执行的几个主要阶段

IPython小白教程:提升你的Python交互式编程技巧,通俗易懂!

IPython是一个增强的Python交互式shell,它提供了丰富的功能和便捷的交互方式,使得Python开发和数据分析工作更加高效。本文将详细介绍IPython的基本概念、使用方法、主要作用以及注意事项。 一、IPython简介 1. IPython的起源 IPython由Fernando Pérez于2001年创建,旨在提供一个更高效的Python交互式编程环境。 2. IPyt

【计算机组成原理】部分题目汇总

计算机组成原理 部分题目汇总 一. 简答题 RISC和CICS 简要说明,比较异同 RISC(精简指令集)注重简单快速的指令执行,使用少量通用寄存器,固定长度指令,优化硬件性能,依赖软件(如编译器)来提升效率。 CISC(复杂指令集)包含多样复杂的指令,能一条指令完成多步操作,采用变长指令,减少指令数但可能增加执行时间,倾向于硬件直接支持复杂功能减轻软件负担。 两者均追求高性能,但RISC