github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/bind_context.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  	"github.com/matrixorigin/matrixone/pkg/catalog"
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    22  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    23  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    24  )
    25  
    26  func NewBindContext(builder *QueryBuilder, parent *BindContext) *BindContext {
    27  	bc := &BindContext{
    28  		groupByAst:     make(map[string]int32),
    29  		aggregateByAst: make(map[string]int32),
    30  		projectByExpr:  make(map[string]int32),
    31  		aliasMap:       make(map[string]int32),
    32  		bindingByTag:   make(map[int32]*Binding),
    33  		bindingByTable: make(map[string]*Binding),
    34  		bindingByCol:   make(map[string]*Binding),
    35  		parent:         parent,
    36  	}
    37  	if parent != nil {
    38  		bc.defaultDatabase = parent.defaultDatabase
    39  	}
    40  
    41  	return bc
    42  }
    43  
    44  func (bc *BindContext) rootTag() int32 {
    45  	if bc.resultTag > 0 {
    46  		return bc.resultTag
    47  	} else {
    48  		return bc.projectTag
    49  	}
    50  }
    51  
    52  func (bc *BindContext) findCTE(name string) *CTERef {
    53  	if cte, ok := bc.cteByName[name]; ok {
    54  		return cte
    55  	}
    56  
    57  	parent := bc.parent
    58  	for parent != nil && name != parent.cteName {
    59  		if cte, ok := parent.cteByName[name]; ok {
    60  			if _, ok := bc.maskedCTEs[name]; !ok {
    61  				return cte
    62  			}
    63  		}
    64  
    65  		bc = parent
    66  		parent = bc.parent
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func (bc *BindContext) mergeContexts(ctx context.Context, left, right *BindContext) error {
    73  	left.parent = bc
    74  	right.parent = bc
    75  	bc.leftChild = left
    76  	bc.rightChild = right
    77  
    78  	for _, binding := range left.bindings {
    79  		bc.bindings = append(bc.bindings, binding)
    80  		bc.bindingByTag[binding.tag] = binding
    81  		bc.bindingByTable[binding.table] = binding
    82  	}
    83  
    84  	for _, binding := range right.bindings {
    85  		if _, ok := bc.bindingByTable[binding.table]; ok {
    86  			return moerr.NewInvalidInput(ctx, "table '%s' specified more than once", binding.table)
    87  		}
    88  
    89  		bc.bindings = append(bc.bindings, binding)
    90  		bc.bindingByTag[binding.tag] = binding
    91  		bc.bindingByTable[binding.table] = binding
    92  	}
    93  
    94  	for col, binding := range left.bindingByCol {
    95  		bc.bindingByCol[col] = binding
    96  	}
    97  
    98  	for col, binding := range right.bindingByCol {
    99  		if _, ok := bc.bindingByCol[col]; ok {
   100  			bc.bindingByCol[col] = nil
   101  		} else {
   102  			bc.bindingByCol[col] = binding
   103  		}
   104  	}
   105  
   106  	bc.bindingTree = &BindingTreeNode{
   107  		left:  left.bindingTree,
   108  		right: right.bindingTree,
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  func (bc *BindContext) addUsingCol(col string, typ plan.Node_JoinFlag, left, right *BindContext) (*plan.Expr, error) {
   115  	leftBinding, ok := left.bindingByCol[col]
   116  	if !ok {
   117  		return nil, moerr.NewInvalidInput(bc.binder.GetContext(), "column '%s' specified in USING clause does not exist in left table", col)
   118  	}
   119  	if leftBinding == nil {
   120  		return nil, moerr.NewInvalidInput(bc.binder.GetContext(), "common column '%s' appears more than once in left table", col)
   121  	}
   122  
   123  	rightBinding, ok := right.bindingByCol[col]
   124  	if !ok {
   125  		return nil, moerr.NewInvalidInput(bc.binder.GetContext(), "column '%s' specified in USING clause does not exist in right table", col)
   126  	}
   127  	if rightBinding == nil {
   128  		return nil, moerr.NewInvalidInput(bc.binder.GetContext(), "common column '%s' appears more than once in right table", col)
   129  	}
   130  
   131  	if typ != plan.Node_RIGHT {
   132  		bc.bindingByCol[col] = leftBinding
   133  		bc.bindingTree.using = append(bc.bindingTree.using, NameTuple{
   134  			table: leftBinding.table,
   135  			col:   col,
   136  		})
   137  	} else {
   138  		bc.bindingByCol[col] = rightBinding
   139  		bc.bindingTree.using = append(bc.bindingTree.using, NameTuple{
   140  			table: rightBinding.table,
   141  			col:   col,
   142  		})
   143  	}
   144  
   145  	leftPos := leftBinding.colIdByName[col]
   146  	rightPos := rightBinding.colIdByName[col]
   147  	expr, err := bindFuncExprImplByPlanExpr(bc.binder.GetContext(), "=", []*plan.Expr{
   148  		{
   149  			Typ: leftBinding.types[leftPos],
   150  			Expr: &plan.Expr_Col{
   151  				Col: &plan.ColRef{
   152  					RelPos: leftBinding.tag,
   153  					ColPos: leftPos,
   154  				},
   155  			},
   156  		},
   157  		{
   158  			Typ: rightBinding.types[rightPos],
   159  			Expr: &plan.Expr_Col{
   160  				Col: &plan.ColRef{
   161  					RelPos: rightBinding.tag,
   162  					ColPos: rightPos,
   163  				},
   164  			},
   165  		},
   166  	})
   167  
   168  	return expr, err
   169  }
   170  
   171  func (bc *BindContext) unfoldStar(ctx context.Context, table string, isSysAccount bool) ([]tree.SelectExpr, []string, error) {
   172  	if len(table) == 0 {
   173  		// unfold *
   174  		var exprs []tree.SelectExpr
   175  		var names []string
   176  
   177  		bc.doUnfoldStar(ctx, bc.bindingTree, make(map[string]any), &exprs, &names, isSysAccount)
   178  
   179  		return exprs, names, nil
   180  	} else {
   181  		// unfold tbl.*
   182  		binding, ok := bc.bindingByTable[table]
   183  		if !ok {
   184  			return nil, nil, moerr.NewInvalidInput(ctx, "missing FROM-clause entry for table '%s'", table)
   185  		}
   186  
   187  		exprs := make([]tree.SelectExpr, 0)
   188  		names := make([]string, 0)
   189  
   190  		for _, col := range binding.cols {
   191  			if catalog.ContainExternalHidenCol(col) {
   192  				continue
   193  			}
   194  			//the non-sys account skips the column account_id for the cluster table
   195  			if !isSysAccount && binding.isClusterTable && util.IsClusterTableAttribute(col) {
   196  				continue
   197  			}
   198  			expr, _ := tree.NewUnresolvedName(ctx, table, col)
   199  			exprs = append(exprs, tree.SelectExpr{Expr: expr})
   200  			names = append(names, col)
   201  		}
   202  
   203  		return exprs, names, nil
   204  	}
   205  }
   206  
   207  func (bc *BindContext) doUnfoldStar(ctx context.Context, root *BindingTreeNode, visitedUsingCols map[string]any, exprs *[]tree.SelectExpr, names *[]string, isSysAccount bool) {
   208  	if root == nil {
   209  		return
   210  	}
   211  	if root.binding != nil {
   212  		for _, col := range root.binding.cols {
   213  			if catalog.ContainExternalHidenCol(col) {
   214  				continue
   215  			}
   216  			//the non-sys account skips the column account_id for the cluster table
   217  			if !isSysAccount && root.binding.isClusterTable && util.IsClusterTableAttribute(col) {
   218  				continue
   219  			}
   220  			if _, ok := visitedUsingCols[col]; !ok {
   221  				expr, _ := tree.NewUnresolvedName(ctx, root.binding.table, col)
   222  				*exprs = append(*exprs, tree.SelectExpr{Expr: expr})
   223  				*names = append(*names, col)
   224  			}
   225  		}
   226  
   227  		return
   228  	}
   229  
   230  	var handledUsingCols []string
   231  
   232  	for _, using := range root.using {
   233  		if catalog.ContainExternalHidenCol(using.col) {
   234  			continue
   235  		}
   236  		//the non-sys account skips the column account_id for the cluster table
   237  		if !isSysAccount && root.binding.isClusterTable && util.IsClusterTableAttribute(using.col) {
   238  			continue
   239  		}
   240  		if _, ok := visitedUsingCols[using.col]; !ok {
   241  			handledUsingCols = append(handledUsingCols, using.col)
   242  			visitedUsingCols[using.col] = nil
   243  
   244  			expr, _ := tree.NewUnresolvedName(ctx, using.table, using.col)
   245  			*exprs = append(*exprs, tree.SelectExpr{Expr: expr})
   246  			*names = append(*names, using.col)
   247  		}
   248  	}
   249  
   250  	bc.doUnfoldStar(ctx, root.left, visitedUsingCols, exprs, names, isSysAccount)
   251  	bc.doUnfoldStar(ctx, root.right, visitedUsingCols, exprs, names, isSysAccount)
   252  
   253  	for _, col := range handledUsingCols {
   254  		delete(visitedUsingCols, col)
   255  	}
   256  }
   257  
   258  func (bc *BindContext) qualifyColumnNames(astExpr tree.Expr, selectList tree.SelectExprs, expandAlias bool) (tree.Expr, error) {
   259  	var err error
   260  
   261  	switch exprImpl := astExpr.(type) {
   262  	case *tree.ParenExpr:
   263  		astExpr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   264  
   265  	case *tree.OrExpr:
   266  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   267  		if err != nil {
   268  			return nil, err
   269  		}
   270  
   271  		exprImpl.Right, err = bc.qualifyColumnNames(exprImpl.Right, selectList, expandAlias)
   272  
   273  	case *tree.NotExpr:
   274  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   275  
   276  	case *tree.AndExpr:
   277  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   278  		if err != nil {
   279  			return nil, err
   280  		}
   281  
   282  		exprImpl.Right, err = bc.qualifyColumnNames(exprImpl.Right, selectList, expandAlias)
   283  
   284  	case *tree.UnaryExpr:
   285  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   286  
   287  	case *tree.BinaryExpr:
   288  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   289  		if err != nil {
   290  			return nil, err
   291  		}
   292  
   293  		exprImpl.Right, err = bc.qualifyColumnNames(exprImpl.Right, selectList, expandAlias)
   294  
   295  	case *tree.ComparisonExpr:
   296  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   297  		if err != nil {
   298  			return nil, err
   299  		}
   300  
   301  		exprImpl.Right, err = bc.qualifyColumnNames(exprImpl.Right, selectList, expandAlias)
   302  
   303  	case *tree.FuncExpr:
   304  		for i := range exprImpl.Exprs {
   305  			exprImpl.Exprs[i], err = bc.qualifyColumnNames(exprImpl.Exprs[i], selectList, expandAlias)
   306  			if err != nil {
   307  				return nil, err
   308  			}
   309  		}
   310  
   311  	case *tree.RangeCond:
   312  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   313  		if err != nil {
   314  			return nil, err
   315  		}
   316  
   317  		exprImpl.From, err = bc.qualifyColumnNames(exprImpl.From, selectList, expandAlias)
   318  		if err != nil {
   319  			return nil, err
   320  		}
   321  
   322  		exprImpl.To, err = bc.qualifyColumnNames(exprImpl.To, selectList, expandAlias)
   323  
   324  	case *tree.UnresolvedName:
   325  		if !exprImpl.Star && exprImpl.NumParts == 1 {
   326  			col := exprImpl.Parts[0]
   327  			if expandAlias {
   328  				if colPos, ok := bc.aliasMap[col]; ok {
   329  					astExpr = selectList[colPos].Expr
   330  					break
   331  				}
   332  			}
   333  
   334  			if binding, ok := bc.bindingByCol[col]; ok {
   335  				if binding != nil {
   336  					exprImpl.NumParts = 2
   337  					exprImpl.Parts[1] = binding.table
   338  				} else {
   339  					return nil, moerr.NewInvalidInput(bc.binder.GetContext(), "ambiguouse column reference to '%s'", col)
   340  				}
   341  			}
   342  		}
   343  
   344  	case *tree.CastExpr:
   345  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   346  
   347  	case *tree.IsNullExpr:
   348  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   349  
   350  	case *tree.IsNotNullExpr:
   351  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   352  
   353  	case *tree.Tuple:
   354  		for i := range exprImpl.Exprs {
   355  			exprImpl.Exprs[i], err = bc.qualifyColumnNames(exprImpl.Exprs[i], selectList, expandAlias)
   356  			if err != nil {
   357  				return nil, err
   358  			}
   359  		}
   360  
   361  	case *tree.CaseExpr:
   362  		exprImpl.Expr, err = bc.qualifyColumnNames(exprImpl.Expr, selectList, expandAlias)
   363  		if err != nil {
   364  			return nil, err
   365  		}
   366  
   367  		for _, when := range exprImpl.Whens {
   368  			when.Cond, err = bc.qualifyColumnNames(when.Cond, selectList, expandAlias)
   369  			if err != nil {
   370  				return nil, err
   371  			}
   372  
   373  			when.Val, err = bc.qualifyColumnNames(when.Val, selectList, expandAlias)
   374  			if err != nil {
   375  				return nil, err
   376  			}
   377  		}
   378  
   379  		exprImpl.Else, err = bc.qualifyColumnNames(exprImpl.Else, selectList, expandAlias)
   380  
   381  	case *tree.XorExpr:
   382  		exprImpl.Left, err = bc.qualifyColumnNames(exprImpl.Left, selectList, expandAlias)
   383  		if err != nil {
   384  			return nil, err
   385  		}
   386  
   387  		exprImpl.Right, err = bc.qualifyColumnNames(exprImpl.Right, selectList, expandAlias)
   388  	}
   389  
   390  	return astExpr, err
   391  }