openGauss学习——解析树结构补充

引言

SQL parser解读(12)—— analyze.cpp解析(上)SQL rewriter解读(3)—— rewriteHandler.cpp解读(三) 两篇博客中,我们简单介绍了查询解析过程中的重要结构体Query和RangeTblEntry。在本篇博客中,我们继续对结构体的部分字段以及解析树结构作补充说明。

RangeTblEntry

RangeTblEntry,即RTE结点,简单地说,是查询树节点中的表实体对象。RTE可以用来表示各种查询语句中包含的关系,其包含了很多我们在查询重写过程中会使用到的信息。其相关知识在 SQL rewriter解读(3)—— rewriteHandler.cpp解读(三) 中已经简单介绍,此处不再赘述。

Query

结构体Query用于保存语义解析所得的查询树细节,一条SQL语句的每个子句的语义分析结果会保存在Query的对应字段中。Query的定义在文件/src/include/parser/parse_node.h中。

typedef struct Query {
    NodeTag type;
    CmdType commandType; 
    QuerySource querySource; 
    uint64 queryId; 
    ……
    bool hasAggs;        
    bool hasWindowFuncs; 
    bool hasSubLinks;     
    bool hasDistinctOn;   
    bool hasRecursive;    
    bool hasModifyingCTE; 
    bool hasForUpdate;   
    bool hasRowSecurity;  
    bool hasSynonyms;    
    ……
    List* targetList; 
    List* starStart; 
    List* starEnd; 
    …… 
    Oid* fixed_paramTypes; 
    int fixed_numParams;
} Query;

这里简单补充下Query的几个比较重要的字段:

  • rtable:存储FROM子句生成的范围表(RTE)集合。rtable的数据类型为List *,其实际是一个列表指针,指向一个存储了许多RTE结点的列表,这些RTE结点中包含了很多查询重写和优化过程中会使用到的信息。

  • targetlist:targetlist用于存储查询语句中的目标属性语义分析结果。它包含了查询语句中所有被选取的属性,用于指定查询的输出结果。通过targetlist,我们可以获取查询结果中需要显示的属性以及它们的别名等信息。targetlist实际上也是一个List* 类型的指针,其指向存放了一组TargetEntry结点的列表。

  • jointree:指向查询包含的连接树的顶层结点,由FROM-WHERE clause转化而来。事实上,Query的jointree字段永远指向一个FromExpr类型的结构体,因为在查询语句中,连接操作只能够出现在FROM子句中,那么连接操作语法树的顶层结点一定为FROM表达式结点。

接下来介绍结构体TargetEntry和FromExpr。

TargetEntry

结构体 TargetEntry 用于表示查询中的目标属性。在openGauss中,查询语句通常由多个目标属性组成,每个目标属性都包含了属性名、表达式以及其他相关信息,而TargetEntry用于表示查询中的目标属性,帮助标识和处理目标属性在查询结果中的位置、名称以及其他相关信息。它的定义在文件/src/include/nodes/primnodes.h中。

typedef struct TargetEntry {
    Expr xpr;
    Expr* expr;            /* expression to evaluate */
    AttrNumber resno;      /* attribute number (see notes above) */
    char* resname;         /* name of the column (could be NULL) */
    Index ressortgroupref; /* nonzero if referenced by a sort/group
                            * clause */
    Oid resorigtbl;        /* OID of column's source table */
    AttrNumber resorigcol; /* column's number in source table */
    bool resjunk;          /* set to true to eliminate the attribute from
                            * final target list */
} TargetEntry;

下面介绍下TargetEntry的几个字段:

  • resno: 表示目标属性在查询结果中的位置编号。

  • resname: 表示目标属性的名称。

  • ressortgroupref: 表示目标属性所属的分组。

  • resorigtbl: 表示目标属性所属的原始表。

  • resorigcol: 表示目标属性所属的原始列。

TargetEntry结构体的主要作用之一是在查询执行过程中,帮助标识和处理目标属性。它可以通过指定resno来确定目标属性在查询结果中的位置,通过resname来获取目标属性的名称。同时,它可以通过ressortgroupref、resorigtbl和resorigcol等成员变量来帮助进行分组、关联和连接操作。

FromExpr & JoinExpr

FromExpr结构体是连接操作语法树的顶层结点,其定义也在文件/src/include/nodes/primnodes.h中。

typedef struct FromExpr {
    NodeTag type;
    List* fromlist; /* List of join subtrees */
    Node* quals;    /* qualifiers on join, if any */
} FromExpr;

此处简单介绍其各个字段:

  • FromExpr的字段 type 用来标识结点类型,其值为T_FromExpr。

  • 成员 fromlist 是一个List * 类型指针,其指向连接树的子树。具体地说,其通常指向一组JoinExpr类型的结点,这是因为通常在连接操作的语法树中FROM操作是JOIN操作的父结点。

  • 字段 quals 是用于存储连接的条件表达式树的。它是一个指向Node类型的指针,用于表示连接操作的条件。这个字段可以用于指定连接操作的过滤条件,以确定连接的结果集。

而JoinExpr是连接树中表示连接操作的语法结点,其定义也在/src/include/nodes/primnodes.h中。

typedef struct JoinExpr {
    NodeTag type;
    JoinType jointype; /* type of join */
    bool isNatural;    /* Natural join? Will need to shape table */
    Node* larg;        /* left subtree */
    Node* rarg;        /* right subtree */
    List* usingClause; /* USING clause, if any (list of String) */
    Node* quals;       /* qualifiers on join, if any */
    Alias* alias;      /* user-written alias clause, if any */
    int rtindex;       /* RT index assigned for join, or 0 */
} JoinExpr;

简单介绍几个比较重要的字段:

  • jointype:表示连接类型,包括左连接、右连接、内连接等等,可参考 SQL optimizer解读(3)—— 子链接提升

  • larg & rarg:这是两个Node * 类型的指针,其指向参与连接操作的左右两个参数的RTE引用。说的具体些,larg和rarg各自指向一个RTE引用结点,即其指向的RTE结点的类型type字段并不为T_RangeTblEntry,而是T_RangeTblRef;这表示其指向的RTE结点并不为实体表,而是通过某些字段与一个实体关系表结点RTE相关联。总之,JoinExpr的larg和rarg字段可以帮助我们找到参与连接操作的两个关系表。

  • rtindex:RTE结点也拥有这个字段,其表示range table中对应的某个实体RTE结点的索引值,上面所述的T_RangeTblRef类型的RTE结点也是通过这个字段来实现与range table中某个实体RTE的一对一绑定。事实上,range table中对于连接操作JOIN也有一个实体RTE结点,因此JoinExpr也具有这一字段,用来与这个RTE结点相关联。

  • quals:存储连接操作的条件表达式树。这个字段可以用于指定连接操作的过滤条件,以确定连接的结果集。

举个例子,比如下面这个FROM-WHERE 语句:

SELECT … FROM table1 LEFT JOIN table2; 

其对应连接部分的语法树,即连接树表示如下:

而其结构体之间的关联关系表示如下。

接下来我们把前面介绍的内容串起来,举个简单的例子方便理解。例如如下两个十分简单的实体表table1、table2:

基于这两个表的查询语句 SELECT table1.a as c1, table1.b as c2, table3.d as c3 FROM table1,table2 WHERE table1.b == table2.c;所对应的各个结构体之间的关联关系,以及FROM语句生成的RangeTblEntry结点、TargetEntry结点以及作用于FROM语句的连接操作条件树就可以总结绘制如下图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
决策树算法是一种广泛应用于分类和回归的机器学习算法,它基于树形结构对样本进行分类或预测。决策树算法的主要思想是通过一系列的判断来对样本进行分类或预测。在决策树中,每个节点表示一个属性或特征,每个分支代表该属性或特征的一个取值,而每个叶子节点代表一个分类或预测结果。 决策树算法的训练过程主要包括以下步骤: 1. 特征选择:根据某种指标(如信息增益或基尼系数)选择最优的特征作为当前节点的分裂属性。 2. 决策树生成:根据选择的特征将数据集分成若干个子集,并递归地生成决策树。 3. 剪枝:通过剪枝操作来提高决策树的泛化性能。 决策树算法的优点包括易于理解和解释、计算复杂度较低、对缺失值不敏感等。但是,决策树算法也存在一些缺点,如容易出现过拟合、对离散数据敏感等。 下面是一个决策树算法的案例:假设我们要根据一个人的年龄、性别、教育程度和职业预测其收入水平(高于或低于50K)。首先,我们需要将这些特征进行编码,将其转换为数值型数据。然后,我们可以使用决策树算法对这些数据进行训练,并生成一个决策树模型。最后,我们可以使用该模型对新的数据进行分类或预测。例如,根据一个人的年龄、性别、教育程度和职业,我们可以使用决策树模型预测该人的收入水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值