暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

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

原创 闫宗帅 2024-02-04
796

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

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

1、搜索表达式

语法如下:

CASE WHEN condition THEN result

     [WHEN ...]

     [ELSE result]

END

表达式计算过程:


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

2、简单表达式

语法如下:

CASE expression

    WHEN value THEN result

    [WHEN ...]

    [ELSE result]

END

表达式计算过程:


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

3、搜索表达式实现机制

3.1 结构体


3.2 搜索表达式的实现机制


首先生成表达式计算步骤: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 简单表达式的实现机制


和搜索表达式不同,需要对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

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论