convertSetOprSelectList converts a list of SELECT from the Pingcap parser into a tree. It is called for UNION, INTERSECT or EXCLUDE operation. Given an union with the following nodes: [Select{1}, Select{2}, Select{3}, Select{4}] The function will return: Select{ Larg: Select{ Lar
(n *pcast.SetOprSelectList)
| 1359 | // Op: Union, |
| 1360 | // } |
| 1361 | func (c *cc) convertSetOprSelectList(n *pcast.SetOprSelectList) ast.Node { |
| 1362 | selectStmts := make([]*ast.SelectStmt, len(n.Selects)) |
| 1363 | for i, node := range n.Selects { |
| 1364 | switch node := node.(type) { |
| 1365 | case *pcast.SelectStmt: |
| 1366 | selectStmts[i] = c.convertSelectStmt(node) |
| 1367 | case *pcast.SetOprSelectList: |
| 1368 | // If this is a single-select SetOprSelectList (e.g., from parenthesized SELECT), |
| 1369 | // extract the inner select instead of building a UNION tree |
| 1370 | if len(node.Selects) == 1 { |
| 1371 | if innerSelect, ok := node.Selects[0].(*pcast.SelectStmt); ok { |
| 1372 | selectStmts[i] = c.convertSelectStmt(innerSelect) |
| 1373 | } else { |
| 1374 | selectStmts[i] = c.convertSetOprSelectList(node).(*ast.SelectStmt) |
| 1375 | } |
| 1376 | } else { |
| 1377 | selectStmts[i] = c.convertSetOprSelectList(node).(*ast.SelectStmt) |
| 1378 | } |
| 1379 | default: |
| 1380 | // Handle other node types like ParenthesesExpr wrapping a SELECT |
| 1381 | converted := c.convert(node) |
| 1382 | if ss, ok := converted.(*ast.SelectStmt); ok { |
| 1383 | selectStmts[i] = ss |
| 1384 | } else if pe, ok := converted.(*ast.ParenExpr); ok { |
| 1385 | // Unwrap ParenExpr to get the inner SelectStmt |
| 1386 | if inner, ok := pe.Expr.(*ast.SelectStmt); ok { |
| 1387 | selectStmts[i] = inner |
| 1388 | } |
| 1389 | } |
| 1390 | } |
| 1391 | } |
| 1392 | |
| 1393 | op, all := c.convertSetOprType(n.AfterSetOperator) |
| 1394 | tree := &ast.SelectStmt{ |
| 1395 | TargetList: &ast.List{}, |
| 1396 | FromClause: &ast.List{}, |
| 1397 | WhereClause: nil, |
| 1398 | Op: op, |
| 1399 | All: all, |
| 1400 | WithClause: c.convertWithClause(n.With), |
| 1401 | } |
| 1402 | for _, stmt := range selectStmts { |
| 1403 | // We move Op and All from the child to the parent. |
| 1404 | op, all := stmt.Op, stmt.All |
| 1405 | stmt.Op, stmt.All = ast.None, false |
| 1406 | |
| 1407 | switch { |
| 1408 | case tree.Larg == nil: |
| 1409 | tree.Larg = stmt |
| 1410 | case tree.Rarg == nil: |
| 1411 | tree.Rarg = stmt |
| 1412 | tree.Op = op |
| 1413 | tree.All = all |
| 1414 | default: |
| 1415 | tree = &ast.SelectStmt{ |
| 1416 | TargetList: &ast.List{}, |
| 1417 | FromClause: &ast.List{}, |
| 1418 | WhereClause: nil, |
no test coverage detected