How to support "FULL JOIN" clause

114 Views Asked by At

I'm trying to add "FULL JOIN" support in TiDB parser(https://github.com/pingcap/tidb/tree/master/parser). I tried two different modifications to parser.y. In attempt one: I changed the definition of "JoinTable" as follows:

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}
    }

and in attempt two: I changed the definition of "JoinType" to:

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

and in dml.go:

// 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")
    }
...
}

and in both cases I got "conflicts: 2 shift/reduce" in make.In y.output I found the following lines:

state 1810 // update '(' selectKwd '*' ')'

  1474 TableFactor: '(' SetOprStmt1 ')' . TableAsNameOpt  // assoc %precedence, prec 56
  1478 TableAsNameOpt: .  [$end, ')', ',', ';', '}', cross, except, fetch, forKwd, full, group, having, inner, intersect, into, join, left, limit, lock, natural, on, order, right, set, straightJoin, union, using, where, window, with]

    $end                   reduce using rule 1478 (TableAsNameOpt)
    ')'                    reduce using rule 1478 (TableAsNameOpt)
    ','                    reduce using rule 1478 (TableAsNameOpt)
    ';'                    reduce using rule 1478 (TableAsNameOpt)
    '}'                    reduce using rule 1478 (TableAsNameOpt)
    account                shift, and goto state 387
...
format                 shift, and goto state 236
    full                   shift, and goto state 237
    function               shift, and goto state 331
...
jobs                   shift, and goto state 521
    join                   reduce using rule 1478 (TableAsNameOpt)
    jsonArrayagg           shift, and goto state 603
...
Identifier         goto state 1813
    NotKeywordToken    goto state 180
    TableAsName        goto state 1812
    TableAsNameOpt     goto state 1811
    TiDBKeyword        goto state 181
    UnReservedKeyword  goto state 179

    conflict on full, shift, and goto state 237, reduce using rule 1478 // full: assoc %left, prec 33

Now I understand the problem is with "FULL", the next step could be both "shift, and goto state 237", or "reduce using rule 1478", but I'v got no clue how to solve this. I tried to add a new "%precedence full" to the end of precedence list and reusing "%prec tableRefPriority", but the error remains. Any help would be appreciated!

1

There are 1 best solutions below

0
Wink Yao On

I am one of the maintainers for TiDB. I have tried your second method and it worked on my end. I did not encounter any shift/reduce errors. Additionally, I successfully ran the newly built TiDB and tested parsing a full join statement, which was successful as well. Did you use 'make parser' to build the parser.go file?

By the way, since MySQL does not support Full Join, if you want to implement it in TiDB, could you please create an issue on github.com/pingcap/tidb first? This will allow us to discuss whether this feature would be accepted or not.