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 }