github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/query_builder.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"fmt"
    21  	"go/constant"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    26  
    27  	"github.com/matrixorigin/matrixone/pkg/catalog"
    28  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    29  	"github.com/matrixorigin/matrixone/pkg/container/types"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    31  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    32  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    33  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    34  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    35  )
    36  
    37  func NewQueryBuilder(queryType plan.Query_StatementType, ctx CompilerContext) *QueryBuilder {
    38  	var mysqlCompatible bool
    39  
    40  	mode, err := ctx.ResolveVariable("sql_mode", true, false)
    41  	if err == nil {
    42  		if modeStr, ok := mode.(string); ok {
    43  			if !strings.Contains(modeStr, "ONLY_FULL_GROUP_BY") {
    44  				mysqlCompatible = true
    45  			}
    46  		}
    47  	}
    48  
    49  	return &QueryBuilder{
    50  		qry: &Query{
    51  			StmtType: queryType,
    52  		},
    53  		compCtx:         ctx,
    54  		ctxByNode:       []*BindContext{},
    55  		nameByColRef:    make(map[[2]int32]string),
    56  		nextTag:         0,
    57  		mysqlCompatible: mysqlCompatible,
    58  	}
    59  }
    60  
    61  func (builder *QueryBuilder) remapExpr(expr *Expr, colMap map[[2]int32][2]int32) error {
    62  	switch ne := expr.Expr.(type) {
    63  	case *plan.Expr_Col:
    64  		mapId := [2]int32{ne.Col.RelPos, ne.Col.ColPos}
    65  		if ids, ok := colMap[mapId]; ok {
    66  			ne.Col.RelPos = ids[0]
    67  			ne.Col.ColPos = ids[1]
    68  			ne.Col.Name = builder.nameByColRef[mapId]
    69  		} else {
    70  			return moerr.NewParseError(builder.GetContext(), "can't find column %v in context's map %v", mapId, colMap)
    71  		}
    72  
    73  	case *plan.Expr_F:
    74  		for _, arg := range ne.F.GetArgs() {
    75  			err := builder.remapExpr(arg, colMap)
    76  			if err != nil {
    77  				return err
    78  			}
    79  		}
    80  	}
    81  	return nil
    82  }
    83  
    84  type ColRefRemapping struct {
    85  	globalToLocal map[[2]int32][2]int32
    86  	localToGlobal [][2]int32
    87  }
    88  
    89  func (m *ColRefRemapping) addColRef(colRef [2]int32) {
    90  	m.globalToLocal[colRef] = [2]int32{0, int32(len(m.localToGlobal))}
    91  	m.localToGlobal = append(m.localToGlobal, colRef)
    92  }
    93  
    94  func (builder *QueryBuilder) remapAllColRefs(nodeID int32, colRefCnt map[[2]int32]int) (*ColRefRemapping, error) {
    95  	node := builder.qry.Nodes[nodeID]
    96  
    97  	remapping := &ColRefRemapping{
    98  		globalToLocal: make(map[[2]int32][2]int32),
    99  	}
   100  
   101  	switch node.NodeType {
   102  	case plan.Node_TABLE_SCAN, plan.Node_MATERIAL_SCAN, plan.Node_EXTERNAL_SCAN, plan.Node_FUNCTION_SCAN:
   103  		for _, expr := range node.FilterList {
   104  			increaseRefCnt(expr, colRefCnt)
   105  		}
   106  
   107  		internalRemapping := &ColRefRemapping{
   108  			globalToLocal: make(map[[2]int32][2]int32),
   109  		}
   110  
   111  		tag := node.BindingTags[0]
   112  		newTableDef := &plan.TableDef{
   113  			Name:          node.TableDef.Name,
   114  			Defs:          node.TableDef.Defs,
   115  			Name2ColIndex: node.TableDef.Name2ColIndex,
   116  			Createsql:     node.TableDef.Createsql,
   117  			TblFunc:       node.TableDef.TblFunc,
   118  			TableType:     node.TableDef.TableType,
   119  			CompositePkey: node.TableDef.CompositePkey,
   120  			OriginCols:    node.TableDef.OriginCols,
   121  		}
   122  
   123  		for i, col := range node.TableDef.Cols {
   124  			globalRef := [2]int32{tag, int32(i)}
   125  			if colRefCnt[globalRef] == 0 {
   126  				continue
   127  			}
   128  
   129  			internalRemapping.addColRef(globalRef)
   130  
   131  			newTableDef.Cols = append(newTableDef.Cols, col)
   132  		}
   133  
   134  		if len(newTableDef.Cols) == 0 {
   135  			internalRemapping.addColRef([2]int32{tag, 0})
   136  			newTableDef.Cols = append(newTableDef.Cols, node.TableDef.Cols[0])
   137  		}
   138  
   139  		node.TableDef = newTableDef
   140  
   141  		for _, expr := range node.FilterList {
   142  			decreaseRefCnt(expr, colRefCnt)
   143  			err := builder.remapExpr(expr, internalRemapping.globalToLocal)
   144  			if err != nil {
   145  				return nil, err
   146  			}
   147  		}
   148  
   149  		for i, col := range node.TableDef.Cols {
   150  			if colRefCnt[internalRemapping.localToGlobal[i]] == 0 {
   151  				continue
   152  			}
   153  
   154  			remapping.addColRef(internalRemapping.localToGlobal[i])
   155  
   156  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   157  				Typ: col.Typ,
   158  				Expr: &plan.Expr_Col{
   159  					Col: &plan.ColRef{
   160  						RelPos: 0,
   161  						ColPos: int32(i),
   162  						Name:   builder.nameByColRef[internalRemapping.localToGlobal[i]],
   163  					},
   164  				},
   165  			})
   166  		}
   167  
   168  		if len(node.ProjectList) == 0 {
   169  			if len(node.TableDef.Cols) == 0 {
   170  				globalRef := [2]int32{tag, 0}
   171  				remapping.addColRef(globalRef)
   172  
   173  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   174  					Typ: node.TableDef.Cols[0].Typ,
   175  					Expr: &plan.Expr_Col{
   176  						Col: &plan.ColRef{
   177  							RelPos: 0,
   178  							ColPos: 0,
   179  							Name:   builder.nameByColRef[globalRef],
   180  						},
   181  					},
   182  				})
   183  			} else {
   184  				remapping.addColRef(internalRemapping.localToGlobal[0])
   185  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   186  					Typ: node.TableDef.Cols[0].Typ,
   187  					Expr: &plan.Expr_Col{
   188  						Col: &plan.ColRef{
   189  							RelPos: 0,
   190  							ColPos: 0,
   191  							Name:   builder.nameByColRef[internalRemapping.localToGlobal[0]],
   192  						},
   193  					},
   194  				})
   195  			}
   196  		}
   197  
   198  		if node.NodeType == plan.Node_FUNCTION_SCAN {
   199  			childId := node.Children[0]
   200  			childNode := builder.qry.Nodes[childId]
   201  			if childNode.NodeType != plan.Node_PROJECT {
   202  				break
   203  			}
   204  			_, err := builder.remapAllColRefs(childId, colRefCnt)
   205  			if err != nil {
   206  				return nil, err
   207  			}
   208  		}
   209  
   210  	case plan.Node_INTERSECT, plan.Node_INTERSECT_ALL,
   211  		plan.Node_UNION, plan.Node_UNION_ALL,
   212  		plan.Node_MINUS, plan.Node_MINUS_ALL:
   213  
   214  		thisTag := node.BindingTags[0]
   215  		leftID := node.Children[0]
   216  		rightID := node.Children[1]
   217  		for i, expr := range node.ProjectList {
   218  			increaseRefCnt(expr, colRefCnt)
   219  			globalRef := [2]int32{thisTag, int32(i)}
   220  			remapping.addColRef(globalRef)
   221  		}
   222  
   223  		rightNode := builder.qry.Nodes[rightID]
   224  		if rightNode.NodeType == plan.Node_PROJECT {
   225  			projectTag := rightNode.BindingTags[0]
   226  			for i := range rightNode.ProjectList {
   227  				increaseRefCnt(&plan.Expr{
   228  					Expr: &plan.Expr_Col{
   229  						Col: &plan.ColRef{
   230  							RelPos: projectTag,
   231  							ColPos: int32(i),
   232  						},
   233  					}}, colRefCnt)
   234  			}
   235  		}
   236  
   237  		internalMap := make(map[[2]int32][2]int32)
   238  
   239  		leftRemapping, err := builder.remapAllColRefs(leftID, colRefCnt)
   240  		if err != nil {
   241  			return nil, err
   242  		}
   243  		for k, v := range leftRemapping.globalToLocal {
   244  			internalMap[k] = v
   245  		}
   246  
   247  		_, err = builder.remapAllColRefs(rightID, colRefCnt)
   248  		if err != nil {
   249  			return nil, err
   250  		}
   251  
   252  		for _, expr := range node.ProjectList {
   253  			decreaseRefCnt(expr, colRefCnt)
   254  			err := builder.remapExpr(expr, internalMap)
   255  			if err != nil {
   256  				return nil, err
   257  			}
   258  		}
   259  
   260  	case plan.Node_JOIN:
   261  		for _, expr := range node.OnList {
   262  			increaseRefCnt(expr, colRefCnt)
   263  		}
   264  
   265  		internalMap := make(map[[2]int32][2]int32)
   266  
   267  		leftID := node.Children[0]
   268  		leftRemapping, err := builder.remapAllColRefs(leftID, colRefCnt)
   269  		if err != nil {
   270  			return nil, err
   271  		}
   272  
   273  		for k, v := range leftRemapping.globalToLocal {
   274  			internalMap[k] = v
   275  		}
   276  
   277  		rightID := node.Children[1]
   278  		rightRemapping, err := builder.remapAllColRefs(rightID, colRefCnt)
   279  		if err != nil {
   280  			return nil, err
   281  		}
   282  
   283  		for k, v := range rightRemapping.globalToLocal {
   284  			internalMap[k] = [2]int32{1, v[1]}
   285  		}
   286  
   287  		for _, expr := range node.OnList {
   288  			decreaseRefCnt(expr, colRefCnt)
   289  			err := builder.remapExpr(expr, internalMap)
   290  			if err != nil {
   291  				return nil, err
   292  			}
   293  		}
   294  
   295  		childProjList := builder.qry.Nodes[leftID].ProjectList
   296  		for i, globalRef := range leftRemapping.localToGlobal {
   297  			if colRefCnt[globalRef] == 0 {
   298  				continue
   299  			}
   300  
   301  			remapping.addColRef(globalRef)
   302  
   303  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   304  				Typ: childProjList[i].Typ,
   305  				Expr: &plan.Expr_Col{
   306  					Col: &plan.ColRef{
   307  						RelPos: 0,
   308  						ColPos: int32(i),
   309  						Name:   builder.nameByColRef[globalRef],
   310  					},
   311  				},
   312  			})
   313  		}
   314  
   315  		if node.JoinType == plan.Node_MARK {
   316  			globalRef := [2]int32{node.BindingTags[0], 0}
   317  			remapping.addColRef(globalRef)
   318  
   319  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   320  				Typ: &plan.Type{
   321  					Id:          int32(types.T_bool),
   322  					NotNullable: false,
   323  					Size:        1,
   324  				},
   325  				Expr: &plan.Expr_Col{
   326  					Col: &plan.ColRef{
   327  						RelPos: -1,
   328  						ColPos: 0,
   329  						Name:   builder.nameByColRef[globalRef],
   330  					},
   331  				},
   332  			})
   333  		} else if node.JoinType != plan.Node_SEMI && node.JoinType != plan.Node_ANTI {
   334  			childProjList = builder.qry.Nodes[rightID].ProjectList
   335  			for i, globalRef := range rightRemapping.localToGlobal {
   336  				if colRefCnt[globalRef] == 0 {
   337  					continue
   338  				}
   339  
   340  				remapping.addColRef(globalRef)
   341  
   342  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   343  					Typ: childProjList[i].Typ,
   344  					Expr: &plan.Expr_Col{
   345  						Col: &plan.ColRef{
   346  							RelPos: 1,
   347  							ColPos: int32(i),
   348  							Name:   builder.nameByColRef[globalRef],
   349  						},
   350  					},
   351  				})
   352  			}
   353  		}
   354  
   355  		if len(node.ProjectList) == 0 && len(leftRemapping.localToGlobal) > 0 {
   356  			globalRef := leftRemapping.localToGlobal[0]
   357  			remapping.addColRef(globalRef)
   358  
   359  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   360  				Typ: builder.qry.Nodes[leftID].ProjectList[0].Typ,
   361  				Expr: &plan.Expr_Col{
   362  					Col: &plan.ColRef{
   363  						RelPos: 0,
   364  						ColPos: 0,
   365  						Name:   builder.nameByColRef[globalRef],
   366  					},
   367  				},
   368  			})
   369  		}
   370  
   371  	case plan.Node_AGG:
   372  		for _, expr := range node.GroupBy {
   373  			increaseRefCnt(expr, colRefCnt)
   374  		}
   375  
   376  		for _, expr := range node.AggList {
   377  			increaseRefCnt(expr, colRefCnt)
   378  		}
   379  
   380  		childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt)
   381  		if err != nil {
   382  			return nil, err
   383  		}
   384  
   385  		groupTag := node.BindingTags[0]
   386  		aggregateTag := node.BindingTags[1]
   387  
   388  		for idx, expr := range node.GroupBy {
   389  			decreaseRefCnt(expr, colRefCnt)
   390  			err := builder.remapExpr(expr, childRemapping.globalToLocal)
   391  			if err != nil {
   392  				return nil, err
   393  			}
   394  
   395  			globalRef := [2]int32{groupTag, int32(idx)}
   396  			if colRefCnt[globalRef] == 0 {
   397  				continue
   398  			}
   399  
   400  			remapping.addColRef(globalRef)
   401  
   402  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   403  				Typ: expr.Typ,
   404  				Expr: &plan.Expr_Col{
   405  					Col: &ColRef{
   406  						RelPos: -1,
   407  						ColPos: int32(idx),
   408  						Name:   builder.nameByColRef[globalRef],
   409  					},
   410  				},
   411  			})
   412  		}
   413  
   414  		groupSize := int32(len(node.GroupBy))
   415  		for idx, expr := range node.AggList {
   416  			decreaseRefCnt(expr, colRefCnt)
   417  			err := builder.remapExpr(expr, childRemapping.globalToLocal)
   418  			if err != nil {
   419  				return nil, err
   420  			}
   421  
   422  			globalRef := [2]int32{aggregateTag, int32(idx)}
   423  			if colRefCnt[globalRef] == 0 {
   424  				continue
   425  			}
   426  
   427  			remapping.addColRef(globalRef)
   428  
   429  			node.ProjectList = append(node.ProjectList, &Expr{
   430  				Typ: expr.Typ,
   431  				Expr: &plan.Expr_Col{
   432  					Col: &ColRef{
   433  						RelPos: -2,
   434  						ColPos: int32(idx) + groupSize,
   435  						Name:   builder.nameByColRef[globalRef],
   436  					},
   437  				},
   438  			})
   439  		}
   440  
   441  		if len(node.ProjectList) == 0 {
   442  			if groupSize > 0 {
   443  				globalRef := [2]int32{groupTag, 0}
   444  				remapping.addColRef(globalRef)
   445  
   446  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   447  					Typ: node.GroupBy[0].Typ,
   448  					Expr: &plan.Expr_Col{
   449  						Col: &plan.ColRef{
   450  							RelPos: -1,
   451  							ColPos: 0,
   452  							Name:   builder.nameByColRef[globalRef],
   453  						},
   454  					},
   455  				})
   456  			} else {
   457  				globalRef := [2]int32{aggregateTag, 0}
   458  				remapping.addColRef(globalRef)
   459  
   460  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   461  					Typ: node.AggList[0].Typ,
   462  					Expr: &plan.Expr_Col{
   463  						Col: &plan.ColRef{
   464  							RelPos: -2,
   465  							ColPos: 0,
   466  							Name:   builder.nameByColRef[globalRef],
   467  						},
   468  					},
   469  				})
   470  			}
   471  		}
   472  
   473  	case plan.Node_SORT:
   474  		for _, orderBy := range node.OrderBy {
   475  			increaseRefCnt(orderBy.Expr, colRefCnt)
   476  		}
   477  
   478  		childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt)
   479  		if err != nil {
   480  			return nil, err
   481  		}
   482  
   483  		for _, orderBy := range node.OrderBy {
   484  			decreaseRefCnt(orderBy.Expr, colRefCnt)
   485  			err := builder.remapExpr(orderBy.Expr, childRemapping.globalToLocal)
   486  			if err != nil {
   487  				return nil, err
   488  			}
   489  		}
   490  
   491  		childProjList := builder.qry.Nodes[node.Children[0]].ProjectList
   492  		for i, globalRef := range childRemapping.localToGlobal {
   493  			if colRefCnt[globalRef] == 0 {
   494  				continue
   495  			}
   496  
   497  			remapping.addColRef(globalRef)
   498  
   499  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   500  				Typ: childProjList[i].Typ,
   501  				Expr: &plan.Expr_Col{
   502  					Col: &plan.ColRef{
   503  						RelPos: 0,
   504  						ColPos: int32(i),
   505  						Name:   builder.nameByColRef[globalRef],
   506  					},
   507  				},
   508  			})
   509  		}
   510  
   511  		if len(node.ProjectList) == 0 && len(childRemapping.localToGlobal) > 0 {
   512  			globalRef := childRemapping.localToGlobal[0]
   513  			remapping.addColRef(globalRef)
   514  
   515  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   516  				Typ: childProjList[0].Typ,
   517  				Expr: &plan.Expr_Col{
   518  					Col: &plan.ColRef{
   519  						RelPos: 0,
   520  						ColPos: 0,
   521  						Name:   builder.nameByColRef[globalRef],
   522  					},
   523  				},
   524  			})
   525  		}
   526  
   527  	case plan.Node_FILTER:
   528  		for _, expr := range node.FilterList {
   529  			increaseRefCnt(expr, colRefCnt)
   530  		}
   531  
   532  		childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt)
   533  		if err != nil {
   534  			return nil, err
   535  		}
   536  
   537  		for _, expr := range node.FilterList {
   538  			decreaseRefCnt(expr, colRefCnt)
   539  			err := builder.remapExpr(expr, childRemapping.globalToLocal)
   540  			if err != nil {
   541  				return nil, err
   542  			}
   543  		}
   544  
   545  		childProjList := builder.qry.Nodes[node.Children[0]].ProjectList
   546  		for i, globalRef := range childRemapping.localToGlobal {
   547  			if colRefCnt[globalRef] == 0 {
   548  				continue
   549  			}
   550  
   551  			remapping.addColRef(globalRef)
   552  
   553  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   554  				Typ: childProjList[i].Typ,
   555  				Expr: &plan.Expr_Col{
   556  					Col: &plan.ColRef{
   557  						RelPos: 0,
   558  						ColPos: int32(i),
   559  						Name:   builder.nameByColRef[globalRef],
   560  					},
   561  				},
   562  			})
   563  		}
   564  
   565  		if len(node.ProjectList) == 0 {
   566  			if len(childRemapping.localToGlobal) > 0 {
   567  				remapping.addColRef(childRemapping.localToGlobal[0])
   568  			}
   569  
   570  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   571  				Typ: childProjList[0].Typ,
   572  				Expr: &plan.Expr_Col{
   573  					Col: &plan.ColRef{
   574  						RelPos: 0,
   575  						ColPos: 0,
   576  					},
   577  				},
   578  			})
   579  		}
   580  
   581  	case plan.Node_PROJECT, plan.Node_MATERIAL:
   582  		projectTag := node.BindingTags[0]
   583  
   584  		var neededProj []int32
   585  
   586  		for i, expr := range node.ProjectList {
   587  			globalRef := [2]int32{projectTag, int32(i)}
   588  			if colRefCnt[globalRef] == 0 {
   589  				continue
   590  			}
   591  
   592  			neededProj = append(neededProj, int32(i))
   593  			increaseRefCnt(expr, colRefCnt)
   594  		}
   595  
   596  		if len(neededProj) == 0 {
   597  			increaseRefCnt(node.ProjectList[0], colRefCnt)
   598  			neededProj = append(neededProj, 0)
   599  		}
   600  
   601  		childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt)
   602  		if err != nil {
   603  			return nil, err
   604  		}
   605  
   606  		var newProjList []*plan.Expr
   607  		for _, needed := range neededProj {
   608  			expr := node.ProjectList[needed]
   609  			decreaseRefCnt(expr, colRefCnt)
   610  			err := builder.remapExpr(expr, childRemapping.globalToLocal)
   611  			if err != nil {
   612  				return nil, err
   613  			}
   614  
   615  			globalRef := [2]int32{projectTag, needed}
   616  			remapping.addColRef(globalRef)
   617  
   618  			newProjList = append(newProjList, expr)
   619  		}
   620  
   621  		node.ProjectList = newProjList
   622  
   623  	case plan.Node_DISTINCT:
   624  		childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt)
   625  		if err != nil {
   626  			return nil, err
   627  		}
   628  
   629  		// Rewrite DISTINCT to AGG
   630  		node.NodeType = plan.Node_AGG
   631  		preNode := builder.qry.Nodes[node.Children[0]]
   632  		node.GroupBy = make([]*Expr, len(preNode.ProjectList))
   633  		node.ProjectList = make([]*Expr, len(preNode.ProjectList))
   634  
   635  		for i, prjExpr := range preNode.ProjectList {
   636  			node.GroupBy[i] = &plan.Expr{
   637  				Typ: prjExpr.Typ,
   638  				Expr: &plan.Expr_Col{
   639  					Col: &plan.ColRef{
   640  						RelPos: 0,
   641  						ColPos: int32(i),
   642  					},
   643  				},
   644  			}
   645  
   646  			node.ProjectList[i] = &plan.Expr{
   647  				Typ: prjExpr.Typ,
   648  				Expr: &plan.Expr_Col{
   649  					Col: &plan.ColRef{
   650  						RelPos: -1,
   651  						ColPos: int32(i),
   652  					},
   653  				},
   654  			}
   655  		}
   656  
   657  		remapping = childRemapping
   658  
   659  	case plan.Node_VALUE_SCAN:
   660  		// VALUE_SCAN always have one column now
   661  		if node.TableDef == nil { // like select 1,2
   662  			node.ProjectList = append(node.ProjectList, &plan.Expr{
   663  				Typ:  &plan.Type{Id: int32(types.T_int64)},
   664  				Expr: &plan.Expr_C{C: &plan.Const{Value: &plan.Const_I64Val{I64Val: 0}}},
   665  			})
   666  		} else {
   667  			internalRemapping := &ColRefRemapping{
   668  				globalToLocal: make(map[[2]int32][2]int32),
   669  			}
   670  
   671  			tag := node.BindingTags[0]
   672  			for i := range node.TableDef.Cols {
   673  				globalRef := [2]int32{tag, int32(i)}
   674  				if colRefCnt[globalRef] == 0 {
   675  					continue
   676  				}
   677  				internalRemapping.addColRef(globalRef)
   678  			}
   679  
   680  			for i, col := range node.TableDef.Cols {
   681  				if colRefCnt[internalRemapping.localToGlobal[i]] == 0 {
   682  					continue
   683  				}
   684  
   685  				remapping.addColRef(internalRemapping.localToGlobal[i])
   686  
   687  				node.ProjectList = append(node.ProjectList, &plan.Expr{
   688  					Typ: col.Typ,
   689  					Expr: &plan.Expr_Col{
   690  						Col: &plan.ColRef{
   691  							RelPos: 0,
   692  							ColPos: int32(i),
   693  							Name:   col.Name,
   694  						},
   695  					},
   696  				})
   697  			}
   698  		}
   699  
   700  	default:
   701  		return nil, moerr.NewInternalError(builder.GetContext(), "unsupport node type")
   702  	}
   703  
   704  	node.BindingTags = nil
   705  
   706  	return remapping, nil
   707  }
   708  
   709  func (builder *QueryBuilder) createQuery() (*Query, error) {
   710  	for i, rootId := range builder.qry.Steps {
   711  		rootId, _ = builder.pushdownFilters(rootId, nil)
   712  		ReCalcNodeStats(rootId, builder, true)
   713  		rootId = builder.determineJoinOrder(rootId)
   714  		rootId = builder.pushdownSemiAntiJoins(rootId)
   715  		builder.qry.Steps[i] = rootId
   716  
   717  		colRefCnt := make(map[[2]int32]int)
   718  		rootNode := builder.qry.Nodes[rootId]
   719  		resultTag := rootNode.BindingTags[0]
   720  		for i := range rootNode.ProjectList {
   721  			colRefCnt[[2]int32{resultTag, int32(i)}] = 1
   722  		}
   723  
   724  		_, err := builder.remapAllColRefs(rootId, colRefCnt)
   725  		if err != nil {
   726  			return nil, err
   727  		}
   728  	}
   729  	return builder.qry, nil
   730  }
   731  
   732  func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree.OrderBy, astLimit *tree.Limit, ctx *BindContext, isRoot bool) (int32, error) {
   733  	var selectStmts []tree.Statement
   734  	var unionTypes []plan.Node_NodeType
   735  
   736  	// get Union selectStmts
   737  	err := getUnionSelects(builder.GetContext(), stmt, &selectStmts, &unionTypes)
   738  	if err != nil {
   739  		return 0, err
   740  	}
   741  
   742  	if len(selectStmts) == 1 {
   743  		switch sltStmt := selectStmts[0].(type) {
   744  		case *tree.Select:
   745  			if sltClause, ok := sltStmt.Select.(*tree.SelectClause); ok {
   746  				sltClause.Distinct = true
   747  				return builder.buildSelect(sltStmt, ctx, isRoot)
   748  			} else {
   749  				// rewrite sltStmt to select distinct * from (sltStmt) a
   750  				tmpSltStmt := &tree.Select{
   751  					Select: &tree.SelectClause{
   752  						Distinct: true,
   753  
   754  						Exprs: []tree.SelectExpr{
   755  							{Expr: tree.StarExpr()},
   756  						},
   757  						From: &tree.From{
   758  							Tables: tree.TableExprs{
   759  								&tree.AliasedTableExpr{
   760  									Expr: &tree.ParenTableExpr{
   761  										Expr: sltStmt,
   762  									},
   763  									As: tree.AliasClause{
   764  										Alias: "a",
   765  									},
   766  								},
   767  							},
   768  						},
   769  					},
   770  					Limit:   astLimit,
   771  					OrderBy: astOrderBy,
   772  				}
   773  				return builder.buildSelect(tmpSltStmt, ctx, isRoot)
   774  			}
   775  
   776  		case *tree.SelectClause:
   777  			if !sltStmt.Distinct {
   778  				sltStmt.Distinct = true
   779  			}
   780  			return builder.buildSelect(&tree.Select{Select: sltStmt, Limit: astLimit, OrderBy: astOrderBy}, ctx, isRoot)
   781  		}
   782  	}
   783  
   784  	// build selects
   785  	var projectTypList [][]types.Type
   786  	selectStmtLength := len(selectStmts)
   787  	nodes := make([]int32, selectStmtLength)
   788  	subCtxList := make([]*BindContext, selectStmtLength)
   789  	var projectLength int
   790  	var nodeID int32
   791  	for idx, sltStmt := range selectStmts {
   792  		subCtx := NewBindContext(builder, ctx)
   793  		if slt, ok := sltStmt.(*tree.Select); ok {
   794  			nodeID, err = builder.buildSelect(slt, subCtx, isRoot)
   795  		} else {
   796  			nodeID, err = builder.buildSelect(&tree.Select{Select: sltStmt}, subCtx, isRoot)
   797  		}
   798  		if err != nil {
   799  			return 0, err
   800  		}
   801  
   802  		if idx == 0 {
   803  			projectLength = len(builder.qry.Nodes[nodeID].ProjectList)
   804  			projectTypList = make([][]types.Type, projectLength)
   805  			for i := 0; i < projectLength; i++ {
   806  				projectTypList[i] = make([]types.Type, selectStmtLength)
   807  			}
   808  		} else {
   809  			if projectLength != len(builder.qry.Nodes[nodeID].ProjectList) {
   810  				return 0, moerr.NewParseError(builder.GetContext(), "SELECT statements have different number of columns")
   811  			}
   812  		}
   813  
   814  		for i, expr := range subCtx.results {
   815  			projectTypList[i][idx] = makeTypeByPlan2Expr(expr)
   816  		}
   817  		subCtxList[idx] = subCtx
   818  		nodes[idx] = nodeID
   819  	}
   820  
   821  	// reset all select's return Projection(type cast up)
   822  	// we use coalesce function's type check&type cast rule
   823  	for columnIdx, argsType := range projectTypList {
   824  		// we don't cast null as any type in function
   825  		// but we will cast null as some target type in union/intersect/minus
   826  		var tmpArgsType []types.Type
   827  		for _, typ := range argsType {
   828  			if typ.Oid != types.T_any {
   829  				tmpArgsType = append(tmpArgsType, typ)
   830  			}
   831  		}
   832  
   833  		if len(tmpArgsType) > 0 {
   834  			_, _, argsCastType, err := function.GetFunctionByName(builder.GetContext(), "coalesce", tmpArgsType)
   835  			if err != nil {
   836  				return 0, moerr.NewParseError(builder.GetContext(), "the %d column cann't cast to a same type", columnIdx)
   837  			}
   838  
   839  			if len(argsCastType) > 0 && int(argsCastType[0].Oid) == int(types.T_datetime) {
   840  				for i := 0; i < len(argsCastType); i++ {
   841  					argsCastType[i].Precision = 0
   842  				}
   843  			}
   844  			var targetType *plan.Type
   845  			var targetArgType types.Type
   846  			if len(argsCastType) == 0 {
   847  				targetArgType = tmpArgsType[0]
   848  			} else {
   849  				targetArgType = argsCastType[0]
   850  			}
   851  			// if string union string, different length may cause error. use text type as the output
   852  			if targetArgType.Oid == types.T_varchar || targetArgType.Oid == types.T_char {
   853  				targetArgType = types.T_text.ToType()
   854  			}
   855  			targetType = makePlan2Type(&targetArgType)
   856  
   857  			for idx, tmpID := range nodes {
   858  				if !argsType[idx].Eq(targetArgType) {
   859  					node := builder.qry.Nodes[tmpID]
   860  					if argsType[idx].Oid == types.T_any {
   861  						node.ProjectList[columnIdx].Typ = targetType
   862  					} else {
   863  						node.ProjectList[columnIdx], err = appendCastBeforeExpr(builder.GetContext(), node.ProjectList[columnIdx], targetType)
   864  						if err != nil {
   865  							return 0, err
   866  						}
   867  					}
   868  				}
   869  			}
   870  		}
   871  	}
   872  
   873  	firstSelectProjectNode := builder.qry.Nodes[nodes[0]]
   874  	// set ctx's headings  projects  results
   875  	ctx.headings = append(ctx.headings, subCtxList[0].headings...)
   876  
   877  	getProjectList := func(tag int32, thisTag int32) []*plan.Expr {
   878  		projectList := make([]*plan.Expr, len(firstSelectProjectNode.ProjectList))
   879  		for i, expr := range firstSelectProjectNode.ProjectList {
   880  			projectList[i] = &plan.Expr{
   881  				Typ: expr.Typ,
   882  				Expr: &plan.Expr_Col{
   883  					Col: &plan.ColRef{
   884  						RelPos: tag,
   885  						ColPos: int32(i),
   886  					},
   887  				},
   888  			}
   889  			builder.nameByColRef[[2]int32{thisTag, int32(i)}] = ctx.headings[i]
   890  		}
   891  		return projectList
   892  	}
   893  
   894  	// build intersect node first.  because intersect has higher precedence then UNION and MINUS
   895  	var newNodes []int32
   896  	var newUnionType []plan.Node_NodeType
   897  	var lastTag int32
   898  	newNodes = append(newNodes, nodes[0])
   899  	for i := 1; i < len(nodes); i++ {
   900  		utIdx := i - 1
   901  		lastNewNodeIdx := len(newNodes) - 1
   902  		if unionTypes[utIdx] == plan.Node_INTERSECT || unionTypes[utIdx] == plan.Node_INTERSECT_ALL {
   903  			lastTag = builder.genNewTag()
   904  			leftNodeTag := builder.qry.Nodes[newNodes[lastNewNodeIdx]].BindingTags[0]
   905  			newNodeID := builder.appendNode(&plan.Node{
   906  				NodeType:    unionTypes[utIdx],
   907  				Children:    []int32{newNodes[lastNewNodeIdx], nodes[i]},
   908  				BindingTags: []int32{lastTag},
   909  				ProjectList: getProjectList(leftNodeTag, lastTag),
   910  			}, ctx)
   911  			newNodes[lastNewNodeIdx] = newNodeID
   912  		} else {
   913  			newNodes = append(newNodes, nodes[i])
   914  			newUnionType = append(newUnionType, unionTypes[utIdx])
   915  		}
   916  	}
   917  
   918  	// build UNION/MINUS node one by one
   919  	lastNodeId := newNodes[0]
   920  	for i := 1; i < len(newNodes); i++ {
   921  		utIdx := i - 1
   922  		lastTag = builder.genNewTag()
   923  		leftNodeTag := builder.qry.Nodes[lastNodeId].BindingTags[0]
   924  
   925  		lastNodeId = builder.appendNode(&plan.Node{
   926  			NodeType:    newUnionType[utIdx],
   927  			Children:    []int32{lastNodeId, newNodes[i]},
   928  			BindingTags: []int32{lastTag},
   929  			ProjectList: getProjectList(leftNodeTag, lastTag),
   930  		}, ctx)
   931  	}
   932  
   933  	// set ctx base on selects[0] and it's ctx
   934  	ctx.groupTag = builder.genNewTag()
   935  	ctx.aggregateTag = builder.genNewTag()
   936  	ctx.projectTag = builder.genNewTag()
   937  	for i, v := range ctx.headings {
   938  		ctx.aliasMap[v] = int32(i)
   939  		builder.nameByColRef[[2]int32{ctx.projectTag, int32(i)}] = v
   940  	}
   941  	for i, expr := range firstSelectProjectNode.ProjectList {
   942  		ctx.projects = append(ctx.projects, &plan.Expr{
   943  			Typ: expr.Typ,
   944  			Expr: &plan.Expr_Col{
   945  				Col: &plan.ColRef{
   946  					RelPos: lastTag,
   947  					ColPos: int32(i),
   948  				},
   949  			},
   950  		})
   951  	}
   952  	havingBinder := NewHavingBinder(builder, ctx)
   953  	projectionBinder := NewProjectionBinder(builder, ctx, havingBinder)
   954  
   955  	// append a project node
   956  	lastNodeId = builder.appendNode(&plan.Node{
   957  		NodeType:    plan.Node_PROJECT,
   958  		ProjectList: ctx.projects,
   959  		Children:    []int32{lastNodeId},
   960  		BindingTags: []int32{ctx.projectTag},
   961  	}, ctx)
   962  
   963  	// append orderBy
   964  	if astOrderBy != nil {
   965  		orderBinder := NewOrderBinder(projectionBinder, nil)
   966  		orderBys := make([]*plan.OrderBySpec, 0, len(astOrderBy))
   967  
   968  		for _, order := range astOrderBy {
   969  			expr, err := orderBinder.BindExpr(order.Expr)
   970  			if err != nil {
   971  				return 0, err
   972  			}
   973  
   974  			orderBy := &plan.OrderBySpec{
   975  				Expr: expr,
   976  				Flag: plan.OrderBySpec_INTERNAL,
   977  			}
   978  
   979  			switch order.Direction {
   980  			case tree.Ascending:
   981  				orderBy.Flag |= plan.OrderBySpec_ASC
   982  			case tree.Descending:
   983  				orderBy.Flag |= plan.OrderBySpec_DESC
   984  			}
   985  
   986  			switch order.NullsPosition {
   987  			case tree.NullsFirst:
   988  				orderBy.Flag |= plan.OrderBySpec_NULLS_FIRST
   989  			case tree.NullsLast:
   990  				orderBy.Flag |= plan.OrderBySpec_NULLS_LAST
   991  			}
   992  
   993  			orderBys = append(orderBys, orderBy)
   994  		}
   995  
   996  		lastNodeId = builder.appendNode(&plan.Node{
   997  			NodeType: plan.Node_SORT,
   998  			Children: []int32{lastNodeId},
   999  			OrderBy:  orderBys,
  1000  		}, ctx)
  1001  	}
  1002  
  1003  	// append limit
  1004  	if astLimit != nil {
  1005  		node := builder.qry.Nodes[lastNodeId]
  1006  
  1007  		limitBinder := NewLimitBinder(builder, ctx)
  1008  		if astLimit.Offset != nil {
  1009  			node.Offset, err = limitBinder.BindExpr(astLimit.Offset, 0, true)
  1010  			if err != nil {
  1011  				return 0, err
  1012  			}
  1013  		}
  1014  		if astLimit.Count != nil {
  1015  			node.Limit, err = limitBinder.BindExpr(astLimit.Count, 0, true)
  1016  			if err != nil {
  1017  				return 0, err
  1018  			}
  1019  
  1020  			if cExpr, ok := node.Limit.Expr.(*plan.Expr_C); ok {
  1021  				if c, ok := cExpr.C.Value.(*plan.Const_I64Val); ok {
  1022  					ctx.hasSingleRow = c.I64Val == 1
  1023  				}
  1024  			}
  1025  		}
  1026  	}
  1027  
  1028  	// append result PROJECT node
  1029  	if builder.qry.Nodes[lastNodeId].NodeType != plan.Node_PROJECT {
  1030  		for i := 0; i < len(ctx.projects); i++ {
  1031  			ctx.results = append(ctx.results, &plan.Expr{
  1032  				Typ: ctx.projects[i].Typ,
  1033  				Expr: &plan.Expr_Col{
  1034  					Col: &plan.ColRef{
  1035  						RelPos: ctx.projectTag,
  1036  						ColPos: int32(i),
  1037  					},
  1038  				},
  1039  			})
  1040  		}
  1041  		ctx.resultTag = builder.genNewTag()
  1042  
  1043  		lastNodeId = builder.appendNode(&plan.Node{
  1044  			NodeType:    plan.Node_PROJECT,
  1045  			ProjectList: ctx.results,
  1046  			Children:    []int32{lastNodeId},
  1047  			BindingTags: []int32{ctx.resultTag},
  1048  		}, ctx)
  1049  	} else {
  1050  		ctx.results = ctx.projects
  1051  	}
  1052  
  1053  	// set heading
  1054  	if isRoot {
  1055  		builder.qry.Headings = append(builder.qry.Headings, ctx.headings...)
  1056  	}
  1057  
  1058  	return lastNodeId, nil
  1059  }
  1060  
  1061  func (builder *QueryBuilder) buildSelect(stmt *tree.Select, ctx *BindContext, isRoot bool) (int32, error) {
  1062  	// preprocess CTEs
  1063  	if stmt.With != nil {
  1064  		ctx.cteByName = make(map[string]*CTERef)
  1065  		maskedNames := make([]string, len(stmt.With.CTEs))
  1066  
  1067  		for i := range stmt.With.CTEs {
  1068  			idx := len(stmt.With.CTEs) - i - 1
  1069  			cte := stmt.With.CTEs[idx]
  1070  
  1071  			name := string(cte.Name.Alias)
  1072  			if _, ok := ctx.cteByName[name]; ok {
  1073  				return 0, moerr.NewSyntaxError(builder.GetContext(), "WITH query name %q specified more than once", name)
  1074  			}
  1075  
  1076  			var maskedCTEs map[string]any
  1077  			if len(maskedNames) > 0 {
  1078  				maskedCTEs = make(map[string]any)
  1079  				for _, mask := range maskedNames {
  1080  					maskedCTEs[mask] = nil
  1081  				}
  1082  			}
  1083  
  1084  			maskedNames = append(maskedNames, name)
  1085  
  1086  			ctx.cteByName[name] = &CTERef{
  1087  				ast:        cte,
  1088  				maskedCTEs: maskedCTEs,
  1089  			}
  1090  		}
  1091  
  1092  		// Try to do binding for CTE at declaration
  1093  		for _, cte := range stmt.With.CTEs {
  1094  			subCtx := NewBindContext(builder, ctx)
  1095  			subCtx.maskedCTEs = ctx.cteByName[string(cte.Name.Alias)].maskedCTEs
  1096  
  1097  			var err error
  1098  			switch stmt := cte.Stmt.(type) {
  1099  			case *tree.Select:
  1100  				_, err = builder.buildSelect(stmt, subCtx, false)
  1101  
  1102  			case *tree.ParenSelect:
  1103  				_, err = builder.buildSelect(stmt.Select, subCtx, false)
  1104  
  1105  			default:
  1106  				err = moerr.NewParseError(builder.GetContext(), "unexpected statement: '%v'", tree.String(stmt, dialect.MYSQL))
  1107  			}
  1108  
  1109  			if err != nil {
  1110  				return 0, err
  1111  			}
  1112  		}
  1113  	}
  1114  
  1115  	var clause *tree.SelectClause
  1116  	var valuesClause *tree.ValuesClause
  1117  	var nodeID int32
  1118  	var err error
  1119  	astOrderBy := stmt.OrderBy
  1120  	astLimit := stmt.Limit
  1121  
  1122  	// strip parentheses
  1123  	// ((select a from t1)) order by b  [ is equal ] select a from t1 order by b
  1124  	// (((select a from t1)) order by b) [ is equal ] select a from t1 order by b
  1125  	//
  1126  	// (select a from t1 union/union all select aa from t2) order by a
  1127  	//       => we will strip parentheses, but order by only can use 'a' column from the union's output projectlist
  1128  	for {
  1129  		if selectClause, ok := stmt.Select.(*tree.ParenSelect); ok {
  1130  			if selectClause.Select.OrderBy != nil {
  1131  				if astOrderBy != nil {
  1132  					return 0, moerr.NewSyntaxError(builder.GetContext(), "multiple ORDER BY clauses not allowed")
  1133  				}
  1134  				astOrderBy = selectClause.Select.OrderBy
  1135  			}
  1136  			if selectClause.Select.Limit != nil {
  1137  				if astLimit != nil {
  1138  					return 0, moerr.NewSyntaxError(builder.GetContext(), "multiple LIMIT clauses not allowed")
  1139  				}
  1140  				astLimit = selectClause.Select.Limit
  1141  			}
  1142  			stmt = selectClause.Select
  1143  		} else {
  1144  			break
  1145  		}
  1146  	}
  1147  
  1148  	switch selectClause := stmt.Select.(type) {
  1149  	case *tree.SelectClause:
  1150  		clause = selectClause
  1151  	case *tree.UnionClause:
  1152  		return builder.buildUnion(selectClause, astOrderBy, astLimit, ctx, isRoot)
  1153  	case *tree.ValuesClause:
  1154  		valuesClause = selectClause
  1155  	default:
  1156  		return 0, moerr.NewNYI(builder.GetContext(), "statement '%s'", tree.String(stmt, dialect.MYSQL))
  1157  	}
  1158  
  1159  	var projectionBinder *ProjectionBinder
  1160  	var havingList []*plan.Expr
  1161  	var selectList tree.SelectExprs
  1162  	var resultLen int
  1163  	var havingBinder *HavingBinder
  1164  
  1165  	if clause == nil {
  1166  		rowCount := len(valuesClause.Rows)
  1167  		if len(valuesClause.Rows) == 0 {
  1168  			return 0, moerr.NewInternalError(builder.GetContext(), "values statement have not rows")
  1169  		}
  1170  		colCount := len(valuesClause.Rows[0])
  1171  		for j := 1; j < rowCount; j++ {
  1172  			if len(valuesClause.Rows[j]) != colCount {
  1173  				return 0, moerr.NewInternalError(builder.GetContext(), fmt.Sprintf("have different column count in row '%v'", j))
  1174  			}
  1175  		}
  1176  
  1177  		ctx.hasSingleRow = rowCount == 1
  1178  		rowSetData := &plan.RowsetData{
  1179  			Cols: make([]*plan.ColData, colCount),
  1180  		}
  1181  		tableDef := &plan.TableDef{
  1182  			TblId: 0,
  1183  			Name:  "",
  1184  			Cols:  make([]*plan.ColDef, colCount),
  1185  		}
  1186  		ctx.binder = NewWhereBinder(builder, ctx)
  1187  		for i := 0; i < colCount; i++ {
  1188  			rows := make([]*plan.Expr, rowCount)
  1189  			var colTyp *plan.Type
  1190  			var tmpArgsType []types.Type
  1191  			for j := 0; j < rowCount; j++ {
  1192  				planExpr, err := ctx.binder.BindExpr(valuesClause.Rows[j][i], 0, true)
  1193  				if err != nil {
  1194  					return 0, err
  1195  				}
  1196  				if planExpr.Typ.Id != int32(types.T_any) {
  1197  					tmpArgsType = append(tmpArgsType, makeTypeByPlan2Expr(planExpr))
  1198  				}
  1199  				rows[j] = planExpr
  1200  			}
  1201  
  1202  			if len(tmpArgsType) > 0 {
  1203  				_, _, argsCastType, err := function.GetFunctionByName(builder.GetContext(), "coalesce", tmpArgsType)
  1204  				if err != nil {
  1205  					return 0, err
  1206  				}
  1207  				if len(argsCastType) > 0 {
  1208  					colTyp = makePlan2Type(&argsCastType[0])
  1209  					for j := 0; j < rowCount; j++ {
  1210  						if rows[j].Typ.Id != int32(types.T_any) && rows[j].Typ.Id != colTyp.Id {
  1211  							rows[j], err = appendCastBeforeExpr(builder.GetContext(), rows[j], colTyp)
  1212  							if err != nil {
  1213  								return 0, err
  1214  							}
  1215  						}
  1216  					}
  1217  				}
  1218  			}
  1219  			if colTyp == nil {
  1220  				colTyp = rows[0].Typ
  1221  			}
  1222  
  1223  			colName := fmt.Sprintf("column_%d", i) // like MySQL
  1224  			selectList = append(selectList, tree.SelectExpr{
  1225  				Expr: &tree.UnresolvedName{
  1226  					NumParts: 1,
  1227  					Star:     false,
  1228  					Parts:    [4]string{colName, "", "", ""},
  1229  				},
  1230  				As: tree.UnrestrictedIdentifier(colName),
  1231  			})
  1232  			ctx.headings = append(ctx.headings, colName)
  1233  			tableDef.Cols[i] = &plan.ColDef{
  1234  				ColId: 0,
  1235  				Name:  colName,
  1236  				Typ:   colTyp,
  1237  			}
  1238  			rowSetData.Cols[i] = &plan.ColData{
  1239  				Data: rows,
  1240  			}
  1241  		}
  1242  		nodeID = builder.appendNode(&plan.Node{
  1243  			NodeType:    plan.Node_VALUE_SCAN,
  1244  			RowsetData:  rowSetData,
  1245  			TableDef:    tableDef,
  1246  			BindingTags: []int32{builder.genNewTag()},
  1247  		}, ctx)
  1248  
  1249  		err = builder.addBinding(nodeID, tree.AliasClause{
  1250  			Alias: "_ValueScan",
  1251  		}, ctx)
  1252  		if err != nil {
  1253  			return 0, err
  1254  		}
  1255  	} else {
  1256  		// build FROM clause
  1257  		nodeID, err = builder.buildFrom(clause.From.Tables, ctx)
  1258  		if err != nil {
  1259  			return 0, err
  1260  		}
  1261  
  1262  		ctx.binder = NewWhereBinder(builder, ctx)
  1263  		// unfold stars and generate headings
  1264  		for _, selectExpr := range clause.Exprs {
  1265  			switch expr := selectExpr.Expr.(type) {
  1266  			case tree.UnqualifiedStar:
  1267  				cols, names, err := ctx.unfoldStar(builder.GetContext(), "", builder.compCtx.GetAccountId() == catalog.System_Account)
  1268  				if err != nil {
  1269  					return 0, err
  1270  				}
  1271  				selectList = append(selectList, cols...)
  1272  				ctx.headings = append(ctx.headings, names...)
  1273  
  1274  			case *tree.UnresolvedName:
  1275  				if expr.Star {
  1276  					cols, names, err := ctx.unfoldStar(builder.GetContext(), expr.Parts[0], builder.compCtx.GetAccountId() == catalog.System_Account)
  1277  					if err != nil {
  1278  						return 0, err
  1279  					}
  1280  					selectList = append(selectList, cols...)
  1281  					ctx.headings = append(ctx.headings, names...)
  1282  				} else {
  1283  					if len(selectExpr.As) > 0 {
  1284  						ctx.headings = append(ctx.headings, string(selectExpr.As))
  1285  					} else {
  1286  						ctx.headings = append(ctx.headings, expr.Parts[0])
  1287  					}
  1288  
  1289  					newExpr, err := ctx.qualifyColumnNames(expr, nil, false)
  1290  					if err != nil {
  1291  						return 0, err
  1292  					}
  1293  
  1294  					selectList = append(selectList, tree.SelectExpr{
  1295  						Expr: newExpr,
  1296  						As:   selectExpr.As,
  1297  					})
  1298  				}
  1299  			case *tree.NumVal:
  1300  				if expr.ValType == tree.P_null {
  1301  					expr.ValType = tree.P_nulltext
  1302  				}
  1303  
  1304  				if len(selectExpr.As) > 0 {
  1305  					ctx.headings = append(ctx.headings, string(selectExpr.As))
  1306  				} else {
  1307  					ctx.headings = append(ctx.headings, tree.String(expr, dialect.MYSQL))
  1308  				}
  1309  				newExpr, err := ctx.qualifyColumnNames(expr, nil, false)
  1310  				if err != nil {
  1311  					return 0, err
  1312  				}
  1313  				selectList = append(selectList, tree.SelectExpr{
  1314  					Expr: newExpr,
  1315  					As:   selectExpr.As,
  1316  				})
  1317  			default:
  1318  				if len(selectExpr.As) > 0 {
  1319  					ctx.headings = append(ctx.headings, string(selectExpr.As))
  1320  				} else {
  1321  					for {
  1322  						if parenExpr, ok := expr.(*tree.ParenExpr); ok {
  1323  							expr = parenExpr.Expr
  1324  						} else {
  1325  							break
  1326  						}
  1327  					}
  1328  					ctx.headings = append(ctx.headings, tree.String(expr, dialect.MYSQL))
  1329  				}
  1330  
  1331  				newExpr, err := ctx.qualifyColumnNames(expr, nil, false)
  1332  				if err != nil {
  1333  					return 0, err
  1334  				}
  1335  
  1336  				selectList = append(selectList, tree.SelectExpr{
  1337  					Expr: newExpr,
  1338  					As:   selectExpr.As,
  1339  				})
  1340  			}
  1341  		}
  1342  
  1343  		if len(selectList) == 0 {
  1344  			return 0, moerr.NewParseError(builder.GetContext(), "No tables used")
  1345  		}
  1346  
  1347  		// rewrite right join to left join
  1348  		builder.rewriteRightJoinToLeftJoin(nodeID)
  1349  
  1350  		if clause.Where != nil {
  1351  			whereList, err := splitAndBindCondition(clause.Where.Expr, ctx)
  1352  			if err != nil {
  1353  				return 0, err
  1354  			}
  1355  
  1356  			var newFilterList []*plan.Expr
  1357  			var expr *plan.Expr
  1358  
  1359  			for _, cond := range whereList {
  1360  				nodeID, expr, err = builder.flattenSubqueries(nodeID, cond, ctx)
  1361  				if err != nil {
  1362  					return 0, err
  1363  				}
  1364  
  1365  				newFilterList = append(newFilterList, expr)
  1366  			}
  1367  
  1368  			nodeID = builder.appendNode(&plan.Node{
  1369  				NodeType:   plan.Node_FILTER,
  1370  				Children:   []int32{nodeID},
  1371  				FilterList: newFilterList,
  1372  			}, ctx)
  1373  		}
  1374  
  1375  		ctx.groupTag = builder.genNewTag()
  1376  		ctx.aggregateTag = builder.genNewTag()
  1377  		ctx.projectTag = builder.genNewTag()
  1378  
  1379  		// bind GROUP BY clause
  1380  		if clause.GroupBy != nil {
  1381  			groupBinder := NewGroupBinder(builder, ctx)
  1382  			for _, group := range clause.GroupBy {
  1383  				group, err = ctx.qualifyColumnNames(group, nil, false)
  1384  				if err != nil {
  1385  					return 0, err
  1386  				}
  1387  
  1388  				_, err = groupBinder.BindExpr(group, 0, true)
  1389  				if err != nil {
  1390  					return 0, err
  1391  				}
  1392  			}
  1393  		}
  1394  
  1395  		// bind HAVING clause
  1396  		havingBinder = NewHavingBinder(builder, ctx)
  1397  		if clause.Having != nil {
  1398  			ctx.binder = havingBinder
  1399  			havingList, err = splitAndBindCondition(clause.Having.Expr, ctx)
  1400  			if err != nil {
  1401  				return 0, err
  1402  			}
  1403  		}
  1404  
  1405  		ctx.isDistinct = clause.Distinct
  1406  	}
  1407  
  1408  	// bind SELECT clause (Projection List)
  1409  	projectionBinder = NewProjectionBinder(builder, ctx, havingBinder)
  1410  	ctx.binder = projectionBinder
  1411  	for i, selectExpr := range selectList {
  1412  		astExpr, err := ctx.qualifyColumnNames(selectExpr.Expr, nil, false)
  1413  		if err != nil {
  1414  			return 0, err
  1415  		}
  1416  
  1417  		expr, err := projectionBinder.BindExpr(astExpr, 0, true)
  1418  		if err != nil {
  1419  			return 0, err
  1420  		}
  1421  
  1422  		builder.nameByColRef[[2]int32{ctx.projectTag, int32(i)}] = tree.String(astExpr, dialect.MYSQL)
  1423  
  1424  		alias := string(selectExpr.As)
  1425  		if len(alias) > 0 {
  1426  			ctx.aliasMap[alias] = int32(len(ctx.projects))
  1427  		}
  1428  		ctx.projects = append(ctx.projects, expr)
  1429  	}
  1430  
  1431  	resultLen = len(ctx.projects)
  1432  	for i, proj := range ctx.projects {
  1433  		exprStr := proj.String()
  1434  		if _, ok := ctx.projectByExpr[exprStr]; !ok {
  1435  			ctx.projectByExpr[exprStr] = int32(i)
  1436  		}
  1437  	}
  1438  
  1439  	// bind ORDER BY clause
  1440  	var orderBys []*plan.OrderBySpec
  1441  	if astOrderBy != nil {
  1442  		orderBinder := NewOrderBinder(projectionBinder, selectList)
  1443  		orderBys = make([]*plan.OrderBySpec, 0, len(astOrderBy))
  1444  
  1445  		for _, order := range astOrderBy {
  1446  			expr, err := orderBinder.BindExpr(order.Expr)
  1447  			if err != nil {
  1448  				return 0, err
  1449  			}
  1450  
  1451  			orderBy := &plan.OrderBySpec{
  1452  				Expr: expr,
  1453  				Flag: plan.OrderBySpec_INTERNAL,
  1454  			}
  1455  
  1456  			switch order.Direction {
  1457  			case tree.Ascending:
  1458  				orderBy.Flag |= plan.OrderBySpec_ASC
  1459  			case tree.Descending:
  1460  				orderBy.Flag |= plan.OrderBySpec_DESC
  1461  			}
  1462  
  1463  			switch order.NullsPosition {
  1464  			case tree.NullsFirst:
  1465  				orderBy.Flag |= plan.OrderBySpec_NULLS_FIRST
  1466  			case tree.NullsLast:
  1467  				orderBy.Flag |= plan.OrderBySpec_NULLS_LAST
  1468  			}
  1469  
  1470  			orderBys = append(orderBys, orderBy)
  1471  		}
  1472  	}
  1473  
  1474  	// bind limit/offset clause
  1475  	var limitExpr *Expr
  1476  	var offsetExpr *Expr
  1477  	if astLimit != nil {
  1478  		limitBinder := NewLimitBinder(builder, ctx)
  1479  		if astLimit.Offset != nil {
  1480  			offsetExpr, err = limitBinder.BindExpr(astLimit.Offset, 0, true)
  1481  			if err != nil {
  1482  				return 0, err
  1483  			}
  1484  		}
  1485  		if astLimit.Count != nil {
  1486  			limitExpr, err = limitBinder.BindExpr(astLimit.Count, 0, true)
  1487  			if err != nil {
  1488  				return 0, err
  1489  			}
  1490  
  1491  			if cExpr, ok := limitExpr.Expr.(*plan.Expr_C); ok {
  1492  				if c, ok := cExpr.C.Value.(*plan.Const_I64Val); ok {
  1493  					ctx.hasSingleRow = c.I64Val == 1
  1494  				}
  1495  			}
  1496  		}
  1497  	}
  1498  
  1499  	if (len(ctx.groups) > 0 || len(ctx.aggregates) > 0) && len(projectionBinder.boundCols) > 0 {
  1500  		if !builder.mysqlCompatible {
  1501  			return 0, moerr.NewSyntaxError(builder.GetContext(), "column %q must appear in the GROUP BY clause or be used in an aggregate function", projectionBinder.boundCols[0])
  1502  		}
  1503  
  1504  		// For MySQL compatibility, wrap bare ColRefs in any_value()
  1505  		for i, proj := range ctx.projects {
  1506  			ctx.projects[i] = builder.wrapBareColRefsInAnyValue(proj, ctx)
  1507  		}
  1508  	}
  1509  
  1510  	// FIXME: delete this when SINGLE join is ready
  1511  	if len(ctx.groups) == 0 && len(ctx.aggregates) > 0 {
  1512  		ctx.hasSingleRow = true
  1513  	}
  1514  
  1515  	// append AGG node
  1516  	if len(ctx.groups) > 0 || len(ctx.aggregates) > 0 {
  1517  		nodeID = builder.appendNode(&plan.Node{
  1518  			NodeType:    plan.Node_AGG,
  1519  			Children:    []int32{nodeID},
  1520  			GroupBy:     ctx.groups,
  1521  			AggList:     ctx.aggregates,
  1522  			BindingTags: []int32{ctx.groupTag, ctx.aggregateTag},
  1523  		}, ctx)
  1524  
  1525  		if len(havingList) > 0 {
  1526  			var newFilterList []*plan.Expr
  1527  			var expr *plan.Expr
  1528  
  1529  			for _, cond := range havingList {
  1530  				nodeID, expr, err = builder.flattenSubqueries(nodeID, cond, ctx)
  1531  				if err != nil {
  1532  					return 0, err
  1533  				}
  1534  
  1535  				newFilterList = append(newFilterList, expr)
  1536  			}
  1537  
  1538  			nodeID = builder.appendNode(&plan.Node{
  1539  				NodeType:   plan.Node_FILTER,
  1540  				Children:   []int32{nodeID},
  1541  				FilterList: newFilterList,
  1542  			}, ctx)
  1543  		}
  1544  
  1545  		for name, id := range ctx.groupByAst {
  1546  			builder.nameByColRef[[2]int32{ctx.groupTag, id}] = name
  1547  		}
  1548  
  1549  		for name, id := range ctx.aggregateByAst {
  1550  			builder.nameByColRef[[2]int32{ctx.aggregateTag, id}] = name
  1551  		}
  1552  	}
  1553  
  1554  	// append PROJECT node
  1555  	for i, proj := range ctx.projects {
  1556  		nodeID, proj, err = builder.flattenSubqueries(nodeID, proj, ctx)
  1557  		if err != nil {
  1558  			return 0, err
  1559  		}
  1560  
  1561  		ctx.projects[i] = proj
  1562  	}
  1563  
  1564  	nodeID = builder.appendNode(&plan.Node{
  1565  		NodeType:    plan.Node_PROJECT,
  1566  		ProjectList: ctx.projects,
  1567  		Children:    []int32{nodeID},
  1568  		BindingTags: []int32{ctx.projectTag},
  1569  	}, ctx)
  1570  
  1571  	// append DISTINCT node
  1572  	if ctx.isDistinct {
  1573  		nodeID = builder.appendNode(&plan.Node{
  1574  			NodeType: plan.Node_DISTINCT,
  1575  			Children: []int32{nodeID},
  1576  		}, ctx)
  1577  	}
  1578  
  1579  	// append SORT node (include limit, offset)
  1580  	if len(orderBys) > 0 {
  1581  		nodeID = builder.appendNode(&plan.Node{
  1582  			NodeType: plan.Node_SORT,
  1583  			Children: []int32{nodeID},
  1584  			OrderBy:  orderBys,
  1585  		}, ctx)
  1586  	}
  1587  
  1588  	if limitExpr != nil || offsetExpr != nil {
  1589  		node := builder.qry.Nodes[nodeID]
  1590  
  1591  		node.Limit = limitExpr
  1592  		node.Offset = offsetExpr
  1593  	}
  1594  
  1595  	// append result PROJECT node
  1596  	if builder.qry.Nodes[nodeID].NodeType != plan.Node_PROJECT {
  1597  		for i := 0; i < resultLen; i++ {
  1598  			ctx.results = append(ctx.results, &plan.Expr{
  1599  				Typ: ctx.projects[i].Typ,
  1600  				Expr: &plan.Expr_Col{
  1601  					Col: &plan.ColRef{
  1602  						RelPos: ctx.projectTag,
  1603  						ColPos: int32(i),
  1604  					},
  1605  				},
  1606  			})
  1607  		}
  1608  
  1609  		ctx.resultTag = builder.genNewTag()
  1610  
  1611  		nodeID = builder.appendNode(&plan.Node{
  1612  			NodeType:    plan.Node_PROJECT,
  1613  			ProjectList: ctx.results,
  1614  			Children:    []int32{nodeID},
  1615  			BindingTags: []int32{ctx.resultTag},
  1616  		}, ctx)
  1617  	} else {
  1618  		ctx.results = ctx.projects
  1619  	}
  1620  
  1621  	if isRoot {
  1622  		builder.qry.Headings = append(builder.qry.Headings, ctx.headings...)
  1623  	}
  1624  
  1625  	return nodeID, nil
  1626  }
  1627  
  1628  func (builder *QueryBuilder) appendNode(node *plan.Node, ctx *BindContext) int32 {
  1629  	nodeID := int32(len(builder.qry.Nodes))
  1630  	node.NodeId = nodeID
  1631  	builder.qry.Nodes = append(builder.qry.Nodes, node)
  1632  	builder.ctxByNode = append(builder.ctxByNode, ctx)
  1633  	ReCalcNodeStats(nodeID, builder, false)
  1634  	return nodeID
  1635  }
  1636  
  1637  func (builder *QueryBuilder) rewriteRightJoinToLeftJoin(nodeID int32) {
  1638  	node := builder.qry.Nodes[nodeID]
  1639  	if node.NodeType == plan.Node_JOIN {
  1640  		builder.rewriteRightJoinToLeftJoin(node.Children[0])
  1641  		builder.rewriteRightJoinToLeftJoin(node.Children[1])
  1642  
  1643  		if node.JoinType == plan.Node_RIGHT {
  1644  			node.JoinType = plan.Node_LEFT
  1645  			node.Children = []int32{node.Children[1], node.Children[0]}
  1646  		}
  1647  	} else if len(node.Children) > 0 {
  1648  		builder.rewriteRightJoinToLeftJoin(node.Children[0])
  1649  	}
  1650  }
  1651  
  1652  func (builder *QueryBuilder) buildFrom(stmt tree.TableExprs, ctx *BindContext) (int32, error) {
  1653  	if len(stmt) == 1 {
  1654  		return builder.buildTable(stmt[0], ctx)
  1655  	}
  1656  	return 0, moerr.NewInternalError(ctx.binder.GetContext(), "stmt's length should be zero")
  1657  	// for now, stmt'length always be zero. if someday that change in parser, you should uncomment these codes
  1658  	// leftCtx := NewBindContext(builder, ctx)
  1659  	// leftChildID, err := builder.buildTable(stmt[0], leftCtx)
  1660  	// if err != nil {
  1661  	// 	return 0, err
  1662  	// }
  1663  
  1664  	// for i := 1; i < len(stmt); i++ {
  1665  	// 	rightCtx := NewBindContext(builder, ctx)
  1666  	// 	rightChildID, err := builder.buildTable(stmt[i], rightCtx)
  1667  	// 	if err != nil {
  1668  	// 		return 0, err
  1669  	// 	}
  1670  
  1671  	// 	leftChildID = builder.appendNode(&plan.Node{
  1672  	// 		NodeType: plan.Node_JOIN,
  1673  	// 		Children: []int32{leftChildID, rightChildID},
  1674  	// 		JoinType: plan.Node_INNER,
  1675  	// 	}, nil)
  1676  
  1677  	// 	if i == len(stmt)-1 {
  1678  	// 		builder.ctxByNode[leftChildID] = ctx
  1679  	// 		err = ctx.mergeContexts(leftCtx, rightCtx)
  1680  	// 		if err != nil {
  1681  	// 			return 0, err
  1682  	// 		}
  1683  	// 	} else {
  1684  	// 		newCtx := NewBindContext(builder, ctx)
  1685  	// 		builder.ctxByNode[leftChildID] = newCtx
  1686  	// 		err = newCtx.mergeContexts(leftCtx, rightCtx)
  1687  	// 		if err != nil {
  1688  	// 			return 0, err
  1689  	// 		}
  1690  	// 		leftCtx = newCtx
  1691  	// 	}
  1692  	// }
  1693  
  1694  	// return leftChildID, err
  1695  }
  1696  
  1697  func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext) (nodeID int32, err error) {
  1698  	switch tbl := stmt.(type) {
  1699  	case *tree.Select:
  1700  		subCtx := NewBindContext(builder, ctx)
  1701  		nodeID, err = builder.buildSelect(tbl, subCtx, false)
  1702  		if subCtx.isCorrelated {
  1703  			return 0, moerr.NewNYI(builder.GetContext(), "correlated subquery in FROM clause")
  1704  		}
  1705  
  1706  		if subCtx.hasSingleRow {
  1707  			ctx.hasSingleRow = true
  1708  		}
  1709  
  1710  	case *tree.TableName:
  1711  		schema := string(tbl.SchemaName)
  1712  		table := string(tbl.ObjectName)
  1713  		if len(table) == 0 || table == "dual" { //special table name
  1714  			nodeID = builder.appendNode(&plan.Node{
  1715  				NodeType: plan.Node_VALUE_SCAN,
  1716  			}, ctx)
  1717  
  1718  			ctx.hasSingleRow = true
  1719  
  1720  			break
  1721  		}
  1722  
  1723  		if len(schema) == 0 {
  1724  			cteRef := ctx.findCTE(table)
  1725  			if cteRef != nil {
  1726  				subCtx := NewBindContext(builder, ctx)
  1727  				subCtx.maskedCTEs = cteRef.maskedCTEs
  1728  				subCtx.cteName = table
  1729  				//reset defaultDatabase
  1730  				if len(cteRef.defaultDatabase) > 0 {
  1731  					subCtx.defaultDatabase = cteRef.defaultDatabase
  1732  				}
  1733  
  1734  				switch stmt := cteRef.ast.Stmt.(type) {
  1735  				case *tree.Select:
  1736  					nodeID, err = builder.buildSelect(stmt, subCtx, false)
  1737  
  1738  				case *tree.ParenSelect:
  1739  					nodeID, err = builder.buildSelect(stmt.Select, subCtx, false)
  1740  
  1741  				default:
  1742  					err = moerr.NewParseError(builder.GetContext(), "unexpected statement: '%v'", tree.String(stmt, dialect.MYSQL))
  1743  				}
  1744  
  1745  				if err != nil {
  1746  					return
  1747  				}
  1748  
  1749  				if subCtx.hasSingleRow {
  1750  					ctx.hasSingleRow = true
  1751  				}
  1752  
  1753  				cols := cteRef.ast.Name.Cols
  1754  
  1755  				if len(cols) > len(subCtx.headings) {
  1756  					return 0, moerr.NewSyntaxError(builder.GetContext(), "table %q has %d columns available but %d columns specified", table, len(subCtx.headings), len(cols))
  1757  				}
  1758  
  1759  				for i, col := range cols {
  1760  					subCtx.headings[i] = string(col)
  1761  				}
  1762  
  1763  				break
  1764  			}
  1765  			schema = ctx.defaultDatabase
  1766  		}
  1767  
  1768  		obj, tableDef := builder.compCtx.Resolve(schema, table)
  1769  		if tableDef == nil {
  1770  			return 0, moerr.NewParseError(builder.GetContext(), "table %q does not exist", table)
  1771  		}
  1772  
  1773  		tableDef.Name2ColIndex = map[string]int32{}
  1774  		for i := 0; i < len(tableDef.Cols); i++ {
  1775  			tableDef.Name2ColIndex[tableDef.Cols[i].Name] = int32(i)
  1776  		}
  1777  		nodeType := plan.Node_TABLE_SCAN
  1778  		if tableDef.TableType == catalog.SystemExternalRel {
  1779  			nodeType = plan.Node_EXTERNAL_SCAN
  1780  			col := &ColDef{
  1781  				Name: catalog.ExternalFilePath,
  1782  				Typ: &plan.Type{
  1783  					Id:    int32(types.T_varchar),
  1784  					Width: types.MaxVarcharLen,
  1785  					Table: table,
  1786  				},
  1787  			}
  1788  			tableDef.Cols = append(tableDef.Cols, col)
  1789  		} else if tableDef.TableType == catalog.SystemViewRel {
  1790  			if yes, dbOfView, nameOfView := builder.compCtx.GetBuildingAlterView(); yes {
  1791  				currentDB := schema
  1792  				if currentDB == "" {
  1793  					currentDB = builder.compCtx.DefaultDatabase()
  1794  				}
  1795  				if dbOfView == currentDB && nameOfView == table {
  1796  					return 0, moerr.NewInternalError(builder.GetContext(), "there is a recursive reference to the view %s", nameOfView)
  1797  				}
  1798  			}
  1799  			// set view statment to CTE
  1800  			viewDefString := tableDef.ViewSql.View
  1801  
  1802  			if viewDefString != "" {
  1803  				if ctx.cteByName == nil {
  1804  					ctx.cteByName = make(map[string]*CTERef)
  1805  				}
  1806  
  1807  				viewData := ViewData{}
  1808  				err := json.Unmarshal([]byte(viewDefString), &viewData)
  1809  				if err != nil {
  1810  					return 0, err
  1811  				}
  1812  
  1813  				originStmts, err := mysql.Parse(builder.GetContext(), viewData.Stmt)
  1814  				if err != nil {
  1815  					return 0, err
  1816  				}
  1817  				viewStmt, ok := originStmts[0].(*tree.CreateView)
  1818  
  1819  				// No createview stmt, check alterview stmt.
  1820  				if !ok {
  1821  					alterstmt, ok := originStmts[0].(*tree.AlterView)
  1822  					viewStmt = &tree.CreateView{}
  1823  					if !ok {
  1824  						return 0, moerr.NewParseError(builder.GetContext(), "can not get view statement")
  1825  					}
  1826  					viewStmt.Name = alterstmt.Name
  1827  					viewStmt.ColNames = alterstmt.ColNames
  1828  					viewStmt.AsSource = alterstmt.AsSource
  1829  				}
  1830  
  1831  				viewName := viewStmt.Name.ObjectName
  1832  				var maskedCTEs map[string]any
  1833  				if len(ctx.cteByName) > 0 {
  1834  					maskedCTEs = make(map[string]any)
  1835  					for name := range ctx.cteByName {
  1836  						maskedCTEs[name] = nil
  1837  					}
  1838  				}
  1839  
  1840  				ctx.cteByName[string(viewName)] = &CTERef{
  1841  					ast: &tree.CTE{
  1842  						Name: &tree.AliasClause{
  1843  							Alias: viewName,
  1844  							Cols:  viewStmt.ColNames,
  1845  						},
  1846  						Stmt: viewStmt.AsSource,
  1847  					},
  1848  					defaultDatabase: viewData.DefaultDatabase,
  1849  					maskedCTEs:      maskedCTEs,
  1850  				}
  1851  
  1852  				newTableName := tree.NewTableName(viewName, tree.ObjectNamePrefix{
  1853  					CatalogName:     tbl.CatalogName, // TODO unused now, if used in some code, that will be save in view
  1854  					SchemaName:      tree.Identifier(""),
  1855  					ExplicitCatalog: false,
  1856  					ExplicitSchema:  false,
  1857  				})
  1858  				return builder.buildTable(newTableName, ctx)
  1859  			}
  1860  		}
  1861  
  1862  		nodeID = builder.appendNode(&plan.Node{
  1863  			NodeType:    nodeType,
  1864  			Stats:       nil,
  1865  			ObjRef:      obj,
  1866  			TableDef:    tableDef,
  1867  			BindingTags: []int32{builder.genNewTag()},
  1868  		}, ctx)
  1869  
  1870  	case *tree.JoinTableExpr:
  1871  		if tbl.Right == nil {
  1872  			return builder.buildTable(tbl.Left, ctx)
  1873  		}
  1874  		return builder.buildJoinTable(tbl, ctx)
  1875  
  1876  	case *tree.TableFunction:
  1877  		if tbl.Id() == "result_scan" {
  1878  			return builder.buildResultScan(tbl, ctx)
  1879  		}
  1880  		return builder.buildTableFunction(tbl, ctx)
  1881  
  1882  	case *tree.ParenTableExpr:
  1883  		return builder.buildTable(tbl.Expr, ctx)
  1884  
  1885  	case *tree.AliasedTableExpr: //allways AliasedTableExpr first
  1886  		if _, ok := tbl.Expr.(*tree.Select); ok {
  1887  			if tbl.As.Alias == "" {
  1888  				return 0, moerr.NewSyntaxError(builder.GetContext(), "subquery in FROM must have an alias: %T", stmt)
  1889  			}
  1890  		}
  1891  
  1892  		nodeID, err = builder.buildTable(tbl.Expr, ctx)
  1893  		if err != nil {
  1894  			return
  1895  		}
  1896  
  1897  		err = builder.addBinding(nodeID, tbl.As, ctx)
  1898  
  1899  		//tableDef := builder.qry.Nodes[nodeID].GetTableDef()
  1900  		midNode := builder.qry.Nodes[nodeID]
  1901  		//if it is the non-sys account and reads the cluster table,
  1902  		//we add an account_id filter to make sure that the non-sys account
  1903  		//can only read its own data.
  1904  		if midNode.NodeType == plan.Node_TABLE_SCAN && builder.compCtx.GetAccountId() != catalog.System_Account {
  1905  			// add account filter for system table scan
  1906  			dbName := midNode.ObjRef.SchemaName
  1907  			tableName := midNode.TableDef.Name
  1908  			currentAccountId := builder.compCtx.GetAccountId()
  1909  			if dbName == catalog.MO_CATALOG && tableName == catalog.MO_DATABASE {
  1910  				modatabaseFilter := util.BuildMoDataBaseFilter(uint64(currentAccountId))
  1911  				ctx.binder = NewWhereBinder(builder, ctx)
  1912  				accountFilterExprs, err := splitAndBindCondition(modatabaseFilter, ctx)
  1913  				if err != nil {
  1914  					return 0, err
  1915  				}
  1916  				builder.qry.Nodes[nodeID].FilterList = accountFilterExprs
  1917  			} else if dbName == catalog.MO_CATALOG && tableName == catalog.MO_TABLES {
  1918  				motablesFilter := util.BuildMoTablesFilter(uint64(currentAccountId))
  1919  				ctx.binder = NewWhereBinder(builder, ctx)
  1920  				accountFilterExprs, err := splitAndBindCondition(motablesFilter, ctx)
  1921  				if err != nil {
  1922  					return 0, err
  1923  				}
  1924  				builder.qry.Nodes[nodeID].FilterList = accountFilterExprs
  1925  			} else if dbName == catalog.MO_CATALOG && tableName == catalog.MO_COLUMNS {
  1926  				moColumnsFilter := util.BuildMoColumnsFilter(uint64(currentAccountId))
  1927  				ctx.binder = NewWhereBinder(builder, ctx)
  1928  				accountFilterExprs, err := splitAndBindCondition(moColumnsFilter, ctx)
  1929  				if err != nil {
  1930  					return 0, err
  1931  				}
  1932  				builder.qry.Nodes[nodeID].FilterList = accountFilterExprs
  1933  			} else if util.TableIsClusterTable(midNode.GetTableDef().GetTableType()) {
  1934  				ctx.binder = NewWhereBinder(builder, ctx)
  1935  				left := &tree.UnresolvedName{
  1936  					NumParts: 1,
  1937  					Parts:    tree.NameParts{util.GetClusterTableAttributeName()},
  1938  				}
  1939  				currentAccountId := builder.compCtx.GetAccountId()
  1940  				right := tree.NewNumVal(constant.MakeUint64(uint64(currentAccountId)), strconv.Itoa(int(currentAccountId)), false)
  1941  				right.ValType = tree.P_uint64
  1942  				//account_id = the accountId of the non-sys account
  1943  				accountFilter := &tree.ComparisonExpr{
  1944  					Op:    tree.EQUAL,
  1945  					Left:  left,
  1946  					Right: right,
  1947  				}
  1948  				accountFilterExprs, err := splitAndBindCondition(accountFilter, ctx)
  1949  				if err != nil {
  1950  					return 0, err
  1951  				}
  1952  				builder.qry.Nodes[nodeID].FilterList = accountFilterExprs
  1953  			}
  1954  		}
  1955  		return
  1956  	case *tree.StatementSource:
  1957  		return 0, moerr.NewParseError(builder.GetContext(), "unsupport table expr: %T", stmt)
  1958  
  1959  	default:
  1960  		// Values table not support
  1961  		return 0, moerr.NewParseError(builder.GetContext(), "unsupport table expr: %T", stmt)
  1962  	}
  1963  
  1964  	return
  1965  }
  1966  
  1967  func (builder *QueryBuilder) genNewTag() int32 {
  1968  	builder.nextTag++
  1969  	return builder.nextTag
  1970  }
  1971  
  1972  func (builder *QueryBuilder) addBinding(nodeID int32, alias tree.AliasClause, ctx *BindContext) error {
  1973  	node := builder.qry.Nodes[nodeID]
  1974  
  1975  	var cols []string
  1976  	var types []*plan.Type
  1977  	var binding *Binding
  1978  	var table string
  1979  
  1980  	if node.NodeType == plan.Node_TABLE_SCAN || node.NodeType == plan.Node_MATERIAL_SCAN || node.NodeType == plan.Node_EXTERNAL_SCAN || node.NodeType == plan.Node_FUNCTION_SCAN || node.NodeType == plan.Node_VALUE_SCAN {
  1981  		if node.NodeType == plan.Node_VALUE_SCAN && node.TableDef == nil {
  1982  			return nil
  1983  		}
  1984  		if len(alias.Cols) > len(node.TableDef.Cols) {
  1985  			return moerr.NewSyntaxError(builder.GetContext(), "table %q has %d columns available but %d columns specified", alias.Alias, len(node.TableDef.Cols), len(alias.Cols))
  1986  		}
  1987  
  1988  		if alias.Alias != "" {
  1989  			table = string(alias.Alias)
  1990  		} else {
  1991  			if node.NodeType == plan.Node_FUNCTION_SCAN {
  1992  				return moerr.NewSyntaxError(builder.GetContext(), "Every table function must have an alias")
  1993  			}
  1994  
  1995  			table = node.TableDef.Name
  1996  		}
  1997  
  1998  		if _, ok := ctx.bindingByTable[table]; ok {
  1999  			return moerr.NewSyntaxError(builder.GetContext(), "table name %q specified more than once", table)
  2000  		}
  2001  
  2002  		cols = make([]string, len(node.TableDef.Cols))
  2003  		types = make([]*plan.Type, len(node.TableDef.Cols))
  2004  
  2005  		tag := node.BindingTags[0]
  2006  
  2007  		for i, col := range node.TableDef.Cols {
  2008  			if i < len(alias.Cols) {
  2009  				cols[i] = string(alias.Cols[i])
  2010  			} else {
  2011  				cols[i] = col.Name
  2012  			}
  2013  			types[i] = col.Typ
  2014  			name := table + "." + cols[i]
  2015  			builder.nameByColRef[[2]int32{tag, int32(i)}] = name
  2016  		}
  2017  
  2018  		binding = NewBinding(tag, nodeID, table, cols, types, util.TableIsClusterTable(node.TableDef.TableType))
  2019  	} else {
  2020  		// Subquery
  2021  		subCtx := builder.ctxByNode[nodeID]
  2022  		tag := subCtx.rootTag()
  2023  		headings := subCtx.headings
  2024  		projects := subCtx.projects
  2025  
  2026  		if len(alias.Cols) > len(headings) {
  2027  			return moerr.NewSyntaxError(builder.GetContext(), "11111 table %q has %d columns available but %d columns specified", alias.Alias, len(headings), len(alias.Cols))
  2028  		}
  2029  
  2030  		table = subCtx.cteName
  2031  		if len(alias.Alias) > 0 {
  2032  			table = string(alias.Alias)
  2033  		}
  2034  		if len(table) == 0 {
  2035  			table = fmt.Sprintf("mo_table_subquery_alias_%d", tag)
  2036  		}
  2037  		if _, ok := ctx.bindingByTable[table]; ok {
  2038  			return moerr.NewSyntaxError(builder.GetContext(), "table name %q specified more than once", table)
  2039  		}
  2040  
  2041  		cols = make([]string, len(headings))
  2042  		types = make([]*plan.Type, len(headings))
  2043  
  2044  		for i, col := range headings {
  2045  			if i < len(alias.Cols) {
  2046  				cols[i] = string(alias.Cols[i])
  2047  			} else {
  2048  				cols[i] = col
  2049  			}
  2050  			types[i] = projects[i].Typ
  2051  
  2052  			name := table + "." + cols[i]
  2053  			builder.nameByColRef[[2]int32{tag, int32(i)}] = name
  2054  		}
  2055  
  2056  		binding = NewBinding(tag, nodeID, table, cols, types, false)
  2057  	}
  2058  
  2059  	ctx.bindings = append(ctx.bindings, binding)
  2060  	ctx.bindingByTag[binding.tag] = binding
  2061  	ctx.bindingByTable[binding.table] = binding
  2062  
  2063  	for _, col := range binding.cols {
  2064  		if _, ok := ctx.bindingByCol[col]; ok {
  2065  			ctx.bindingByCol[col] = nil
  2066  		} else {
  2067  			ctx.bindingByCol[col] = binding
  2068  		}
  2069  	}
  2070  
  2071  	ctx.bindingTree = &BindingTreeNode{
  2072  		binding: binding,
  2073  	}
  2074  
  2075  	return nil
  2076  }
  2077  
  2078  func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindContext) (int32, error) {
  2079  	var joinType plan.Node_JoinFlag
  2080  
  2081  	switch tbl.JoinType {
  2082  	case tree.JOIN_TYPE_CROSS, tree.JOIN_TYPE_INNER, tree.JOIN_TYPE_NATURAL:
  2083  		joinType = plan.Node_INNER
  2084  	case tree.JOIN_TYPE_LEFT, tree.JOIN_TYPE_NATURAL_LEFT:
  2085  		joinType = plan.Node_LEFT
  2086  	case tree.JOIN_TYPE_RIGHT, tree.JOIN_TYPE_NATURAL_RIGHT:
  2087  		joinType = plan.Node_RIGHT
  2088  	case tree.JOIN_TYPE_FULL:
  2089  		joinType = plan.Node_OUTER
  2090  	}
  2091  
  2092  	leftCtx := NewBindContext(builder, ctx)
  2093  	rightCtx := NewBindContext(builder, ctx)
  2094  
  2095  	leftChildID, err := builder.buildTable(tbl.Left, leftCtx)
  2096  	if err != nil {
  2097  		return 0, err
  2098  	}
  2099  	if _, ok := tbl.Right.(*tree.TableFunction); ok {
  2100  		return 0, moerr.NewSyntaxError(builder.GetContext(), "Every table function must have an alias")
  2101  	}
  2102  	if aliasedTblExpr, ok := tbl.Right.(*tree.AliasedTableExpr); ok {
  2103  		if tblFn, ok2 := aliasedTblExpr.Expr.(*tree.TableFunction); ok2 {
  2104  			err = buildTableFunctionStmt(tblFn, tbl.Left, leftCtx)
  2105  			if err != nil {
  2106  				return 0, err
  2107  			}
  2108  		}
  2109  	}
  2110  
  2111  	rightChildID, err := builder.buildTable(tbl.Right, rightCtx)
  2112  	if err != nil {
  2113  		return 0, err
  2114  	}
  2115  
  2116  	err = ctx.mergeContexts(builder.GetContext(), leftCtx, rightCtx)
  2117  	if err != nil {
  2118  		return 0, err
  2119  	}
  2120  
  2121  	nodeID := builder.appendNode(&plan.Node{
  2122  		NodeType: plan.Node_JOIN,
  2123  		Children: []int32{leftChildID, rightChildID},
  2124  		JoinType: joinType,
  2125  	}, ctx)
  2126  	node := builder.qry.Nodes[nodeID]
  2127  
  2128  	ctx.binder = NewTableBinder(builder, ctx)
  2129  
  2130  	switch cond := tbl.Cond.(type) {
  2131  	case *tree.OnJoinCond:
  2132  		joinConds, err := splitAndBindCondition(cond.Expr, ctx)
  2133  		if err != nil {
  2134  			return 0, err
  2135  		}
  2136  
  2137  		node.OnList = joinConds
  2138  
  2139  	case *tree.UsingJoinCond:
  2140  		for _, col := range cond.Cols {
  2141  			expr, err := ctx.addUsingCol(string(col), joinType, leftCtx, rightCtx)
  2142  			if err != nil {
  2143  				return 0, err
  2144  			}
  2145  
  2146  			node.OnList = append(node.OnList, expr)
  2147  		}
  2148  
  2149  	default:
  2150  		if tbl.JoinType == tree.JOIN_TYPE_NATURAL || tbl.JoinType == tree.JOIN_TYPE_NATURAL_LEFT || tbl.JoinType == tree.JOIN_TYPE_NATURAL_RIGHT {
  2151  			leftCols := make(map[string]any)
  2152  			for _, binding := range leftCtx.bindings {
  2153  				for _, col := range binding.cols {
  2154  					leftCols[col] = nil
  2155  				}
  2156  			}
  2157  
  2158  			var usingCols []string
  2159  			for _, binding := range rightCtx.bindings {
  2160  				for _, col := range binding.cols {
  2161  					if _, ok := leftCols[col]; ok {
  2162  						usingCols = append(usingCols, col)
  2163  					}
  2164  				}
  2165  			}
  2166  
  2167  			for _, col := range usingCols {
  2168  				expr, err := ctx.addUsingCol(col, joinType, leftCtx, rightCtx)
  2169  				if err != nil {
  2170  					return 0, err
  2171  				}
  2172  
  2173  				node.OnList = append(node.OnList, expr)
  2174  			}
  2175  		}
  2176  	}
  2177  
  2178  	return nodeID, nil
  2179  }
  2180  
  2181  func (builder *QueryBuilder) pushdownFilters(nodeID int32, filters []*plan.Expr) (int32, []*plan.Expr) {
  2182  	node := builder.qry.Nodes[nodeID]
  2183  
  2184  	var canPushdown, cantPushdown []*plan.Expr
  2185  
  2186  	switch node.NodeType {
  2187  	case plan.Node_AGG:
  2188  		groupTag := node.BindingTags[0]
  2189  		aggregateTag := node.BindingTags[1]
  2190  
  2191  		for _, filter := range filters {
  2192  			if !containsTag(filter, aggregateTag) {
  2193  				canPushdown = append(canPushdown, replaceColRefs(filter, groupTag, node.GroupBy))
  2194  			} else {
  2195  				cantPushdown = append(cantPushdown, filter)
  2196  			}
  2197  		}
  2198  
  2199  		childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown)
  2200  
  2201  		if len(cantPushdownChild) > 0 {
  2202  			childID = builder.appendNode(&plan.Node{
  2203  				NodeType:   plan.Node_FILTER,
  2204  				Children:   []int32{node.Children[0]},
  2205  				FilterList: cantPushdownChild,
  2206  			}, nil)
  2207  		}
  2208  
  2209  		node.Children[0] = childID
  2210  
  2211  	case plan.Node_FILTER:
  2212  		canPushdown = filters
  2213  		for _, filter := range node.FilterList {
  2214  			canPushdown = append(canPushdown, splitPlanConjunction(applyDistributivity(builder.GetContext(), filter))...)
  2215  		}
  2216  
  2217  		childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown)
  2218  
  2219  		var extraFilters []*plan.Expr
  2220  		for _, filter := range cantPushdownChild {
  2221  			switch exprImpl := filter.Expr.(type) {
  2222  			case *plan.Expr_F:
  2223  				if exprImpl.F.Func.ObjName == "or" {
  2224  					keys := checkDNF(filter)
  2225  					for _, key := range keys {
  2226  						extraFilter := walkThroughDNF(builder.GetContext(), filter, key)
  2227  						if extraFilter != nil {
  2228  							extraFilters = append(extraFilters, DeepCopyExpr(extraFilter))
  2229  						}
  2230  					}
  2231  				}
  2232  			}
  2233  		}
  2234  		builder.pushdownFilters(node.Children[0], extraFilters)
  2235  
  2236  		if len(cantPushdownChild) > 0 {
  2237  			node.Children[0] = childID
  2238  			node.FilterList = cantPushdownChild
  2239  		} else {
  2240  			nodeID = childID
  2241  		}
  2242  
  2243  	case plan.Node_JOIN:
  2244  		leftTags := make(map[int32]*Binding)
  2245  		for _, tag := range builder.enumerateTags(node.Children[0]) {
  2246  			leftTags[tag] = nil
  2247  		}
  2248  
  2249  		rightTags := make(map[int32]*Binding)
  2250  		for _, tag := range builder.enumerateTags(node.Children[1]) {
  2251  			rightTags[tag] = nil
  2252  		}
  2253  
  2254  		var markTag int32
  2255  		if node.JoinType == plan.Node_MARK {
  2256  			markTag = node.BindingTags[0]
  2257  		}
  2258  
  2259  		if node.JoinType == plan.Node_INNER {
  2260  			for _, cond := range node.OnList {
  2261  				filters = append(filters, splitPlanConjunction(applyDistributivity(builder.GetContext(), cond))...)
  2262  			}
  2263  
  2264  			node.OnList = nil
  2265  		}
  2266  
  2267  		var leftPushdown, rightPushdown []*plan.Expr
  2268  		var turnInner bool
  2269  
  2270  		joinSides := make([]int8, len(filters))
  2271  
  2272  		for i, filter := range filters {
  2273  			canTurnInner := true
  2274  
  2275  			joinSides[i] = getJoinSide(filter, leftTags, rightTags, markTag)
  2276  			if f, ok := filter.Expr.(*plan.Expr_F); ok {
  2277  				for _, arg := range f.F.Args {
  2278  					if getJoinSide(arg, leftTags, rightTags, markTag) == JoinSideBoth {
  2279  						canTurnInner = false
  2280  						break
  2281  					}
  2282  				}
  2283  			}
  2284  
  2285  			if canTurnInner && node.JoinType == plan.Node_LEFT && joinSides[i]&JoinSideRight != 0 && rejectsNull(filter, builder.compCtx.GetProcess()) {
  2286  				for _, cond := range node.OnList {
  2287  					filters = append(filters, splitPlanConjunction(applyDistributivity(builder.GetContext(), cond))...)
  2288  				}
  2289  
  2290  				node.JoinType = plan.Node_INNER
  2291  				node.OnList = nil
  2292  				turnInner = true
  2293  
  2294  				break
  2295  			}
  2296  
  2297  			// TODO: FULL OUTER join should be handled here. However we don't have FULL OUTER join now.
  2298  		}
  2299  
  2300  		if turnInner {
  2301  			joinSides = make([]int8, len(filters))
  2302  
  2303  			for i, filter := range filters {
  2304  				joinSides[i] = getJoinSide(filter, leftTags, rightTags, markTag)
  2305  			}
  2306  		} else if node.JoinType == plan.Node_LEFT {
  2307  			var newOnList []*plan.Expr
  2308  			for _, cond := range node.OnList {
  2309  				conj := splitPlanConjunction(applyDistributivity(builder.GetContext(), cond))
  2310  				for _, conjElem := range conj {
  2311  					side := getJoinSide(conjElem, leftTags, rightTags, markTag)
  2312  					if side&JoinSideLeft == 0 {
  2313  						rightPushdown = append(rightPushdown, conjElem)
  2314  					} else {
  2315  						newOnList = append(newOnList, conjElem)
  2316  					}
  2317  				}
  2318  			}
  2319  
  2320  			node.OnList = newOnList
  2321  		}
  2322  
  2323  		for i, filter := range filters {
  2324  			switch joinSides[i] {
  2325  			case JoinSideNone:
  2326  				if c, ok := filter.Expr.(*plan.Expr_C); ok {
  2327  					if c, ok := c.C.Value.(*plan.Const_Bval); ok {
  2328  						if c.Bval {
  2329  							break
  2330  						}
  2331  					}
  2332  				}
  2333  
  2334  				switch node.JoinType {
  2335  				case plan.Node_INNER:
  2336  					leftPushdown = append(leftPushdown, DeepCopyExpr(filter))
  2337  					rightPushdown = append(rightPushdown, filter)
  2338  
  2339  				case plan.Node_LEFT, plan.Node_SEMI, plan.Node_ANTI, plan.Node_SINGLE, plan.Node_MARK:
  2340  					leftPushdown = append(leftPushdown, filter)
  2341  
  2342  				default:
  2343  					cantPushdown = append(cantPushdown, filter)
  2344  				}
  2345  
  2346  			case JoinSideLeft:
  2347  				if node.JoinType != plan.Node_OUTER {
  2348  					leftPushdown = append(leftPushdown, filter)
  2349  				} else {
  2350  					cantPushdown = append(cantPushdown, filter)
  2351  				}
  2352  
  2353  			case JoinSideRight:
  2354  				if node.JoinType == plan.Node_INNER {
  2355  					rightPushdown = append(rightPushdown, filter)
  2356  				} else {
  2357  					cantPushdown = append(cantPushdown, filter)
  2358  				}
  2359  
  2360  			case JoinSideBoth:
  2361  				if node.JoinType == plan.Node_INNER {
  2362  					if f, ok := filter.Expr.(*plan.Expr_F); ok {
  2363  						if f.F.Func.ObjName == "=" {
  2364  							if getJoinSide(f.F.Args[0], leftTags, rightTags, markTag) != JoinSideBoth {
  2365  								if getJoinSide(f.F.Args[1], leftTags, rightTags, markTag) != JoinSideBoth {
  2366  									node.OnList = append(node.OnList, filter)
  2367  									break
  2368  								}
  2369  							}
  2370  						}
  2371  					}
  2372  				}
  2373  
  2374  				cantPushdown = append(cantPushdown, filter)
  2375  
  2376  			case JoinSideMark:
  2377  				if tryMark, ok := filter.Expr.(*plan.Expr_Col); ok {
  2378  					if tryMark.Col.RelPos == node.BindingTags[0] {
  2379  						node.JoinType = plan.Node_SEMI
  2380  						node.BindingTags = nil
  2381  						break
  2382  					}
  2383  				} else if fExpr, ok := filter.Expr.(*plan.Expr_F); ok {
  2384  					if filter.Typ.NotNullable && fExpr.F.Func.ObjName == "not" {
  2385  						arg := fExpr.F.Args[0]
  2386  						if tryMark, ok := arg.Expr.(*plan.Expr_Col); ok {
  2387  							if tryMark.Col.RelPos == node.BindingTags[0] {
  2388  								node.JoinType = plan.Node_ANTI
  2389  								node.BindingTags = nil
  2390  								break
  2391  							}
  2392  						}
  2393  					}
  2394  				}
  2395  
  2396  				cantPushdown = append(cantPushdown, filter)
  2397  
  2398  			default:
  2399  				cantPushdown = append(cantPushdown, filter)
  2400  			}
  2401  		}
  2402  
  2403  		if node.JoinType == plan.Node_INNER {
  2404  			//only inner join can deduce new predicate
  2405  			builder.pushdownFilters(node.Children[0], predsDeduction(rightPushdown, node.OnList))
  2406  			builder.pushdownFilters(node.Children[1], predsDeduction(leftPushdown, node.OnList))
  2407  		}
  2408  
  2409  		childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], leftPushdown)
  2410  
  2411  		if len(cantPushdownChild) > 0 {
  2412  			childID = builder.appendNode(&plan.Node{
  2413  				NodeType:   plan.Node_FILTER,
  2414  				Children:   []int32{node.Children[0]},
  2415  				FilterList: cantPushdownChild,
  2416  			}, nil)
  2417  		}
  2418  
  2419  		node.Children[0] = childID
  2420  
  2421  		childID, cantPushdownChild = builder.pushdownFilters(node.Children[1], rightPushdown)
  2422  
  2423  		if len(cantPushdownChild) > 0 {
  2424  			childID = builder.appendNode(&plan.Node{
  2425  				NodeType:   plan.Node_FILTER,
  2426  				Children:   []int32{node.Children[1]},
  2427  				FilterList: cantPushdownChild,
  2428  			}, nil)
  2429  		}
  2430  
  2431  		node.Children[1] = childID
  2432  
  2433  	case plan.Node_UNION, plan.Node_UNION_ALL, plan.Node_MINUS, plan.Node_MINUS_ALL, plan.Node_INTERSECT, plan.Node_INTERSECT_ALL:
  2434  		leftChild := builder.qry.Nodes[node.Children[0]]
  2435  		rightChild := builder.qry.Nodes[node.Children[1]]
  2436  		var canPushDownRight []*plan.Expr
  2437  
  2438  		for _, filter := range filters {
  2439  			canPushdown = append(canPushdown, replaceColRefsForSet(DeepCopyExpr(filter), leftChild.ProjectList))
  2440  			canPushDownRight = append(canPushDownRight, replaceColRefsForSet(filter, rightChild.ProjectList))
  2441  		}
  2442  
  2443  		childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown)
  2444  		if len(cantPushdownChild) > 0 {
  2445  			childID = builder.appendNode(&plan.Node{
  2446  				NodeType:   plan.Node_FILTER,
  2447  				Children:   []int32{node.Children[0]},
  2448  				FilterList: cantPushdownChild,
  2449  			}, nil)
  2450  		}
  2451  		node.Children[0] = childID
  2452  
  2453  		childID, cantPushdownChild = builder.pushdownFilters(node.Children[1], canPushDownRight)
  2454  		if len(cantPushdownChild) > 0 {
  2455  			childID = builder.appendNode(&plan.Node{
  2456  				NodeType:   plan.Node_FILTER,
  2457  				Children:   []int32{node.Children[1]},
  2458  				FilterList: cantPushdownChild,
  2459  			}, nil)
  2460  		}
  2461  		node.Children[1] = childID
  2462  
  2463  	case plan.Node_PROJECT:
  2464  		child := builder.qry.Nodes[node.Children[0]]
  2465  		if (child.NodeType == plan.Node_VALUE_SCAN || child.NodeType == plan.Node_EXTERNAL_SCAN) && child.RowsetData == nil {
  2466  			cantPushdown = filters
  2467  			break
  2468  		}
  2469  
  2470  		projectTag := node.BindingTags[0]
  2471  
  2472  		for _, filter := range filters {
  2473  			canPushdown = append(canPushdown, replaceColRefs(filter, projectTag, node.ProjectList))
  2474  		}
  2475  
  2476  		childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown)
  2477  
  2478  		if len(cantPushdownChild) > 0 {
  2479  			childID = builder.appendNode(&plan.Node{
  2480  				NodeType:   plan.Node_FILTER,
  2481  				Children:   []int32{node.Children[0]},
  2482  				FilterList: cantPushdownChild,
  2483  			}, nil)
  2484  		}
  2485  
  2486  		node.Children[0] = childID
  2487  
  2488  	case plan.Node_TABLE_SCAN, plan.Node_EXTERNAL_SCAN:
  2489  		node.FilterList = append(node.FilterList, filters...)
  2490  	case plan.Node_FUNCTION_SCAN:
  2491  		node.FilterList = append(node.FilterList, filters...)
  2492  		childId := node.Children[0]
  2493  		childId, err := builder.pushdownFilters(childId, nil)
  2494  		if err != nil {
  2495  			return 0, err
  2496  		}
  2497  		node.Children[0] = childId
  2498  
  2499  	default:
  2500  		if len(node.Children) > 0 {
  2501  			childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], filters)
  2502  
  2503  			if len(cantPushdownChild) > 0 {
  2504  				childID = builder.appendNode(&plan.Node{
  2505  					NodeType:   plan.Node_FILTER,
  2506  					Children:   []int32{node.Children[0]},
  2507  					FilterList: cantPushdownChild,
  2508  				}, nil)
  2509  			}
  2510  
  2511  			node.Children[0] = childID
  2512  		} else {
  2513  			cantPushdown = filters
  2514  		}
  2515  	}
  2516  
  2517  	return nodeID, cantPushdown
  2518  }
  2519  
  2520  func (builder *QueryBuilder) buildTableFunction(tbl *tree.TableFunction, ctx *BindContext) (int32, error) {
  2521  	var (
  2522  		childId int32 = -1
  2523  		err     error
  2524  		nodeId  int32
  2525  	)
  2526  	if tbl.SelectStmt != nil {
  2527  		childId, err = builder.buildSelect(tbl.SelectStmt, ctx, false)
  2528  		if err != nil {
  2529  			return 0, err
  2530  		}
  2531  	}
  2532  	if childId == -1 {
  2533  		scanNode := &plan.Node{
  2534  			NodeType: plan.Node_VALUE_SCAN,
  2535  		}
  2536  		childId = builder.appendNode(scanNode, ctx)
  2537  	}
  2538  	ctx.binder = NewTableBinder(builder, ctx)
  2539  	exprs := make([]*plan.Expr, 0, len(tbl.Func.Exprs))
  2540  	for _, v := range tbl.Func.Exprs {
  2541  		curExpr, err := ctx.binder.BindExpr(v, 0, false)
  2542  		if err != nil {
  2543  			return 0, err
  2544  		}
  2545  		exprs = append(exprs, curExpr)
  2546  	}
  2547  	id := tbl.Id()
  2548  	switch id {
  2549  	case "unnest":
  2550  		nodeId, err = builder.buildUnnest(tbl, ctx, exprs, childId)
  2551  	case "generate_series":
  2552  		nodeId = builder.buildGenerateSeries(tbl, ctx, exprs, childId)
  2553  	case "meta_scan":
  2554  		nodeId, err = builder.buildMetaScan(tbl, ctx, exprs, childId)
  2555  	case "current_account":
  2556  		nodeId, err = builder.buildCurrentAccount(tbl, ctx, exprs, childId)
  2557  	default:
  2558  		err = moerr.NewNotSupported(builder.GetContext(), "table function '%s' not supported", id)
  2559  	}
  2560  	clearBinding(ctx)
  2561  	return nodeId, err
  2562  }
  2563  
  2564  func (builder *QueryBuilder) GetContext() context.Context {
  2565  	if builder == nil {
  2566  		return context.TODO()
  2567  	}
  2568  	return builder.compCtx.GetContext()
  2569  }