💻 深耕数据库内核架构设计与开发十余年,曾主导多款高性能分布式数据库内核研发,攻克高并发、低延迟等核心技术难题。现倾力打造《从零手写数据库》系列教程,首次系统性公开数据库内核源码级实现细节!
一、概述
在查询SQL中有一个重要的组成部分,就是表达式,它在select子句,from子句,where子句中都会出现,在不同的位置代表的含义也不相同。
通常表达式有以下几种类型:
标量表达式,返回单个值的表达式,通常用于操作单行数据中的字段或常量。 条件表达式,根据条件逻辑返回不同的值或执行分支操作。 逻辑表达式,组合布尔条件,通常用AND、OR、NOT等连接多个表达式,用于 WHERE、HAVING 或 CHECK 约束。 聚合表达式,对多行数据进行汇总计算,返回单个汇总值。 窗口函数表达式,在数据窗口(一组相关行)内进行计算,保留原始行的同时返回聚合结果。 表表达式,也就是子查询,返回一个虚拟表的表达式,通常用于复杂查询的模块化。 类型转换表达式,显式或隐式转换数据类型。
在前面的基础之上,本节来实现对表达式的处理,主要实现前三种类型的处理。
二、基本表达式运算
参与表达式运算的基础数据类型的数值,不同类型的数值支持不同的运算符,比如整型数值,可以支持算术运算,比较运算;而字符类型的数值,支持比较运算,不支持算术运算。
表达式经过解析之后,是一棵二叉树,每个操作对应具体的两个数值,当数据值的类型支持相应操作时才能进行运算,如果数据类型不支持相应操作时,会产生错误。
当两个操作数类型不相同时,就不能进行直接运算,一般会将右操作数的类型转换为左操作数相同的类型,如果右操作符的数据类型支持类型转换运算时,则可以自动隐式的转换,否则必须由SQL中指定转换。
最基本的表达式运算就是两个数据值的运算,根据数据类型,分别实现它们支持的运算操作。
三、数据类型的运算符集
每种数据类型都有一组支持的运算符函数,为了每种数据类型都可以统一调用,实现运算集的基本框架。
3.1 运算符函数
对于一元和二元操作,即有一个操作数或两个操作数的运算符,定义通用的操作运算函数。
typedef ValuesData* (*Operator2)(ValuesData* leftvalue, ValuesData* rightvalue);
3.2 运算符集
每种数据类型都支持一组操作运算,由统一的结构来表示。
typedef struct DataTypeProcs
{
int version;
DataType dType;
Operator2 opf2[EXPR_OP_NUM];
}DataTypeProcs;
成员说明:
dType, 数据类型,当前数据库支持的基本数据类型; opf2, 二元操作函数数组,数据大小为当前数据库支持的运算类型最大值,每个数据成员为对应的操作函数;操作的类型在node.h中已经定义。
3.3 表达式运算
当一个运算节点需要计算表达式值时,调用基础的二元表达式计算函数即可。
ValuesData* ComputeExpr(Expr_Op opType, ValuesData *lres, ValuesData *rres)
{
ValuesData *result = NULL;
if(lres == NULL)
returnNULL;
if(dTypesProc[lres->dataType] == NULL)
{
/* not support */
returnNULL;
}
else
{
if((rres != NULL) && (rres->dataType != lres->dataType))
{
printf("right operand may be ocur type conversation.\n");
returnNULL;
}
result = dTypesProc[lres->dataType]->opf2[opType](lres, rres);
}
return result;
}
函数流程如下:
函数参数传入操作符类型,左右操作数,左操作数不能为空,当然一元操作时,右操作数为空; 当左右操作数的数据类型不一致时,右操作数可能会发生类型转换; 调用左操作数对应的运算函数进行表达式计算;如果操作数不支持类型转换时,就会产生错误。
其中dTypesProc是一个运算符集合的结构体的数组,数据大小为数据类型的个数,每种数据类型将它支持的运算函数集合结构加到数组中,通过数据类型进行索引,再按操作符类型索引就可以找到对应的运算函数。
DataTypeProcs* dTypesProc[DT_END] =
{
&integerDataTypeProcEntry,
&FloatDataTypeProcEntry,
&CharDataTypeProcEntry,
&BoolDataTypeProcEntry,
&VarcharDataTypeProcEntry,
&TextDataTypeProcEntry
};
目前没有隐式类型转换实现,当数据类型不一致时无法运算。
四、总结
新增表达式模块,对应的代码位于exam_49目录的expr.h/expr.c文件当中。
文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




