暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

【手写数据库核心揭秘系列】第89讲 select子句中的表达式计算,仅select的SQL语法支持

开源无限 2025-04-28
181

💻 深耕数据库内核架构设计与开发十余年,曾主导多款高性能分布式数据库内核研发,攻克高并发、低延迟等核心技术难题。现倾力打造《从零手写数据库》系列教程,首次系统性公开数据库内核源码级实现细节!

🚀 从存储引擎、查询优化到分布式事务,手把手拆解核心模块;从语法解析树构建到执行计划生成,逐行代码还原设计精髓
🌟 无论你是数据库开发者、系统架构师,还是对底层技术充满好奇的极客,这里都有你想要的“硬核干货”!点击关注,与行业老兵共同探索数据库技术的星辰大海!

一、概述 


当表达式出现在select子句时,作为目标列一种类型,表达式的结果需要在投影操作执行时计算得出,最终拼接在查询结果中。

二、查询结果处理 


将查询结果组装时,原来目标列只有常量和属性列的类型,增加表达式节点类型处理分支。

Node* FormTargetResult(Node *targetList, Node *resultList)

            case T_Expr:
                ((Expr*)te->val)->srcData 
= resultList;
                resValue = ExprEvaluation(te->val);

                offset += FormColumnData(te->attr, resValue, tempBuf + offset, PAGE_MAX_SIZE - offset);
            break;

将结果集记录到表达式结构中,调用表达式计算函数计算表达式的值,并将它拼接到查询结果当中。

三、仅select子句支持 


有一种SQL形式,它只有select子句和表达式,表达式可以是常量表达式或者其它运算表达式,比如常用于检测数据库是否正常的“select 1; ”。

这类型的SQL语句,不能迭代循环查询,只需要执行一次即可。

在查询执行计划的顶层投影节点中增加是否执行一次的标记。

typedef struct ProjectNode
{

    int           isOnlyOnce;
}ProjectNode;

在投影执行函数中,当投影节点的子节点为空时,说明只有select子句,只执行一次,当下次迭代进入时返回空,即结束迭代执行。

Node* ExecProject(Node *planNode)

    if(prjPlanNode->isOnlyOnce)
    
{
        return NULL;
    }

    if(prjPlanNode->subNode != NULL)
    {
   
    }
    else
    {
        /* only select */
        prjPlanNode->isOnlyOnce = 1;
    }

另外,在生成执行计划时,当没有where子句时,选择操作节点也是可选节点,顶层投影节点的下层节点为其它存在的节点。

    if(selectNode != NULL)
    {
        selectNode->subNode = subNode;
    }
    else 
    {
        prjNode->subNode = subNode;
    }

四、结果表头显示 


在SQL的查询结果显示时,有一种特殊的情况,如果目标列是表达式或者常量时,如果没有给它别名时,结果列的名称就需要内部生成,有些数据库直接显示为表达式的原字符串,在这里定义为固定名称。

#define DEFAULT_COLUMN_HEAD "-column-"

当目标列名称为表达示或常量时,调用下面函数生成一个属性信息结构,其中名称为固定字符串,而属性的数据类型依据常量的类型,或者表达示中子节点常量或属性列的类型。

AttrInfo* EstimateAttr(TargetElement *te)

在显示查询结果时,会根据这个属性信息来解析目标列的值。

五、目标列表达式计算 


当select子句中目标列为表达式时,在查询结果组装时,需要计算表达式的值。在select子句中的表达式一般非逻辑表达式,计算结果为具体的数据值。

Node* FormTargetResult(Node *targetList, Node *resultList)
            case T_Expr:
                ((Expr*)te->val)->srcData 
= resultList;
                resValue = ExprEvaluation(te->val);

                offset += FormColumnData(te->attr, resValue, tempBuf + offset, PAGE_MAX_SIZE - offset);
            break;

在组装处理时,增加表达式分支处理,将表达式计算的结果值作为当前目标列的值组装到结果中。

六、总结 


本节内容实现代码在exam_50目录下。


🌟 点赞收藏,分享给身边的技术伙伴,关注我们,持续获取数据库内核开发的硬核干货!一起从源码级实现到分布式架构,解锁数据库技术的每一个核心细节!🚀
【往期精彩推荐】

【手写数据库核心揭秘系列】第88讲 表达式结果的计算实现

【手写数据库核心揭秘系列】第87讲 逻辑表达式,运算符处理函数集合

【手写数据库核心揭秘系列】第86讲 比较运算符的实现,基本数据类型的比较操作算子集合



文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论