当前位置: 首页 > article >正文

PgSQL技术内幕 - case when表达式实现机制

PgSQL技术内幕 - case when表达式实现机制

CASE表达式如同 C语言中的if/else语句一样,为SQL添加了条件逻辑处理能力,可以根据不同条件返回不同结果。PgSQL支持两种语法:简单表达式和搜索表达式。

1、搜索表达式

语法如下:

CASE WHEN condition THEN result
     [WHEN ...]
     [ELSE result]
END

表达式计算过程:

1fa4cc6e303f417fb57ae6e61647e5f3.png

按照顺序依次计算WHEN子句的条件表达式:condition1,condition2...,当遇到结果为真的分支就返回相应的THEN结果;若不为真,则继续下一个WHEN条件计算;若所有WHEN都不为真,则返回ELSE默认值;当没有指定ELSE时,就返回NULL。

2、简单表达式

语法如下:

CASE expression
    WHEN value THEN result
    [WHEN ...]
    [ELSE result]
END

表达式计算过程:

7402926e89b3e2fbc9a83fc98307eb19.png

首先计算表达式testexpr的值,然后依次与WHEN中值:value1,value2...进行比较,遇到匹配的就返回THEN对应的结果;如果没有匹配则继续下一个WHEN值比较;若所有WHEN都不匹配则返回ELSE的默认值;如果没有指定ELSE则返回NULL。

3、搜索表达式实现机制

3.1 结构体

18e6c28e9e3eb7ff06493a1a2431c5c2.png

3.2 搜索表达式的实现机制

b7f818831d0913612bf46d616dc0f992.png

首先生成表达式计算步骤:ExecInitExprRec函数的T_CaseExpr分支。大致分为2大部分:

1)所有when的表达式caseExpr->args。首先通过ExecInitExprRec初始化when->expr的表达式计算步骤;然后添加EEOP_JUMP_IF_NOT_TRUE步骤,当when->expr表达式步骤计算为false时需要跳到下一个when,后面的state->steps[whenstep].d.jump.jumpdone = state->steps即为跳转位置;接着ExecInitExprRec初始化THEN的表达式(when->result)计算步骤;最后通过EEOP_JUMP跳到case的结束位置,它的结束位置需要计算完ELSE表达式后进行调整。

2)所有when表达式计算步骤生成后,需要对ELSE表达式进行初始化,即调用ExecInitExprRec对caseExpr->defresult生成计算步骤;最后调整EEOP_JUMP的跳转位置

3.3 简单表达式的实现机制

643907aa65f67e85a897bd6c6be51ba1.png

和搜索表达式不同,需要对CASE的表达式生成计算步骤,即caseExpr->arg的步骤;当该表达式结果类型为变长类型时,需要添加EEOP_MAKE_READONLY步骤进行结果值拷贝。

当没有ELSE时怎么办?

transformCaseExpr
  ...
  defresult = (Node *) c->defresult;
  if (defresult == NULL)
  {
    A_Const    *n = makeNode(A_Const);


    n->val.type = T_Null;
    n->location = -1;
    defresult = (Node *) n;
  }
  newc->defresult = (Expr *) transformExprRecurse(pstate, defresult);
  ...

也就是会添加一个const节点表示NULL,caseExpr->defresult总是有值。

参考

https://www.postgresql.org/docs/12/functions-conditional.html


http://www.kler.cn/a/232504.html

相关文章:

  • Wireshark中的length栏位
  • Vulnhub靶场案例渗透[8]- HackableII
  • 【教程】Ubuntu设置alacritty为默认终端
  • Vue计算属性computed
  • MyBatis——增删查改(XML 方式)
  • 在JPA和EJB中用乐观锁解决并发问题
  • 【Linux系统学习】3.Linux用户和权限
  • C++2024寒假J312实战班2.6
  • C语言冒泡排序介绍
  • 面试复盘——10
  • C++三剑客之std::any(一) : 使用
  • 【MySQL进阶之路】BufferPool底层设计(下)
  • 【GAMES101】Lecture 19 相机
  • java——学习并推荐java8
  • 猫头虎分享已解决Bug :内存泄漏(Memory Leak)
  • Kubernetes实战(二十七)-HPA实战
  • Web Services 服务 是不是过时了?创建 Web Services 服务实例
  • 【Linux】SystemV IPC
  • CTFshow web(命令执行 41-44)
  • WPF 中 Loaded 和 Closing 窗口事件
  • K210如何下载程序
  • LDAR管理系统解决方案
  • 90.Go语言中实现可选参数的几种方法:可变长参数、使用Map、结构体和函数选项模式
  • macbookpro和macbookair的区别?cleanmymac 怎么清理mac空间
  • sqlite3数据库操作接口详细整理,以及常用的数据库语句
  • vscode debug无法直接查看eigen变量的问题(解决方法)