You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TiDB Parser中支持FULL JOIN子句?

在TiDB Parser中添加FULL JOIN支持解决移进/归约冲突问题

问题背景

尝试给TiDB Parser添加FULL JOIN支持时,两种修改方案均导致make执行时出现conflicts: 2 shift/reduce错误。查看y.output发现state 1810中FULL关键字存在移进/归约冲突,可移进至state237,也可归约规则1478。尝试添加%precedence full或复用tableRefPriority未解决问题。

两种修改尝试如下:

尝试一:单独添加FULL JOIN规则

JoinTable:
|   TableRef "FULL" "JOIN" TableRef "ON" Expression
    {
        on := &ast.OnCondition{Expr: $6}
        $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $4.(ast.ResultSetNode), Tp: ast.FullJoin, On: on}
    }

尝试二:扩展JoinType枚举

JoinType:
    "LEFT"
    {
        $$ = ast.LeftJoin
    }
|   "RIGHT"
    {
        $$ = ast.RightJoin
    }
|   "FULL"
    {
        $$ = ast.FullJoin
    }

同时在dml.go中添加枚举及更新Restore方法:

// JoinType is join type, including cross/left/right/full.
type JoinType int

const (
    // CrossJoin is cross join type.
    CrossJoin JoinType = iota + 1
    // LeftJoin is left Join type.
    LeftJoin
    // RightJoin is right Join type.
    RightJoin
    // FullJoin is full Join type.
    FullJoin
)

// Restore implements Node interface.
func (n *Join) Restore(ctx *format.RestoreCtx) error {
...
switch n.Tp {
    case LeftJoin:
        ctx.WriteKeyWord(" LEFT")
    case RightJoin:
        ctx.WriteKeyWord(" RIGHT")
    case FullJoin:
        ctx.WriteKeyWord(" FULL")
    }
...
}

冲突原因

  1. 尝试一单独定义FULL JOIN规则,与原有JoinTable规则产生语法歧义,导致分析器无法确定匹配路径。
  2. 尝试二未正确设置FULL关键字的优先级,使其被其他上下文规则(如FULL TEXT索引相关规则)捕获,引发移进/归约冲突。

解决方案

1. 正确声明关键字优先级

在parser.y的优先级声明区域,添加FULL的优先级,确保其作为JOIN类型时的优先级高于其他冲突规则:

%token FULL
// 将FULL的优先级设置为与LEFT、RIGHT一致,且高于可能引发冲突的规则
%precedence LEFT RIGHT FULL
%precedence JOIN

2. 复用JoinType规则统一处理JOIN类型

删除尝试一中单独的FULL JOIN规则,确保所有JOIN类型通过JoinType统一匹配,避免规则重复:

JoinTable:
    TableRef JoinType "JOIN" TableRef "ON" Expression
    {
        on := &ast.OnCondition{Expr: $6}
        $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $4.(ast.ResultSetNode), Tp: $2.(ast.JoinType), On: on}
    }
// 保留原有其他JoinTable规则(如不带ON、使用USING的场景)

3. 区分FULL关键字的上下文

检查parser.y中是否存在其他使用FULL的规则(如FULLTEXT索引),确保上下文区分:

  • 在表定义上下文,FULL需匹配FULLTEXT规则;
  • 在JOIN上下文,FULL需匹配JoinType规则。
    Yacc会根据当前语法状态自动区分上下文,只要优先级设置正确即可避免冲突。

验证步骤

  1. 执行make parser重新生成解析器,确认无移进/归约冲突提示;
  2. 测试FULL JOIN语句,例如:
    SELECT * FROM t1 FULL JOIN t2 ON t1.id = t2.id;
    
    验证解析结果是否正确生成ast.FullJoin类型的节点。

内容的提问来源于stack exchange,提问作者xiaonerner0821

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 18:25:54