github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/optimizer/resolver.go (about) 1 // Copyright 2015 PingCAP, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package optimizer 15 16 import ( 17 "fmt" 18 19 "github.com/insionng/yougam/libraries/juju/errors" 20 "github.com/insionng/yougam/libraries/pingcap/tidb/ast" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/infoschema" 24 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 25 "github.com/insionng/yougam/libraries/pingcap/tidb/mysql" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/db" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 28 ) 29 30 // ResolveName resolves table name and column name. 31 // It generates ResultFields for ResultSetNode and resolves ColumnNameExpr to a ResultField. 32 func ResolveName(node ast.Node, info infoschema.InfoSchema, ctx context.Context) error { 33 defaultSchema := db.GetCurrentSchema(ctx) 34 resolver := nameResolver{Info: info, Ctx: ctx, DefaultSchema: model.NewCIStr(defaultSchema)} 35 node.Accept(&resolver) 36 return errors.Trace(resolver.Err) 37 } 38 39 // MockResolveName only serves for test. 40 func MockResolveName(node ast.Node, info infoschema.InfoSchema, defaultSchema string) error { 41 resolver := nameResolver{Info: info, Ctx: nil, DefaultSchema: model.NewCIStr(defaultSchema)} 42 node.Accept(&resolver) 43 return resolver.Err 44 } 45 46 // nameResolver is the visitor to resolve table name and column name. 47 // In general, a reference can only refer to information that are available for it. 48 // So children elements are visited in the order that previous elements make information 49 // available for following elements. 50 // 51 // During visiting, information are collected and stored in resolverContext. 52 // When we enter a subquery, a new resolverContext is pushed to the contextStack, so subquery 53 // information can overwrite outer query information. When we look up for a column reference, 54 // we look up from top to bottom in the contextStack. 55 type nameResolver struct { 56 Info infoschema.InfoSchema 57 Ctx context.Context 58 DefaultSchema model.CIStr 59 Err error 60 useOuterContext bool 61 62 contextStack []*resolverContext 63 } 64 65 // resolverContext stores information in a single level of select statement 66 // that table name and column name can be resolved. 67 type resolverContext struct { 68 /* For Select Statement. */ 69 // table map to lookup and check table name conflict. 70 tableMap map[string]int 71 // table map to lookup and check derived-table(subselect) name conflict. 72 derivedTableMap map[string]int 73 // tableSources collected in from clause. 74 tables []*ast.TableSource 75 // result fields collected in select field list. 76 fieldList []*ast.ResultField 77 // result fields collected in group by clause. 78 groupBy []*ast.ResultField 79 80 // The join node stack is used by on condition to find out 81 // available tables to reference. On condition can only 82 // refer to tables involved in current join. 83 joinNodeStack []*ast.Join 84 85 // When visiting TableRefs, tables in this context are not available 86 // because it is being collected. 87 inTableRefs bool 88 // When visiting on condition only tables in current join node are available. 89 inOnCondition bool 90 // When visiting field list, fieldList in this context are not available. 91 inFieldList bool 92 // When visiting group by, groupBy fields are not available. 93 inGroupBy bool 94 // When visiting having, only fieldList and groupBy fields are available. 95 inHaving bool 96 // When visiting having, checks if the expr is an aggregate function expr. 97 inHavingAgg bool 98 // OrderBy clause has different resolving rule than group by. 99 inOrderBy bool 100 // When visiting column name in ByItem, we should know if the column name is in an expression. 101 inByItemExpression bool 102 // If subquery use outer context. 103 useOuterContext bool 104 // When visiting multi-table delete stmt table list. 105 inDeleteTableList bool 106 // When visiting create/drop table statement. 107 inCreateOrDropTable bool 108 // When visiting show statement. 109 inShow bool 110 } 111 112 // currentContext gets the current resolverContext. 113 func (nr *nameResolver) currentContext() *resolverContext { 114 stackLen := len(nr.contextStack) 115 if stackLen == 0 { 116 return nil 117 } 118 return nr.contextStack[stackLen-1] 119 } 120 121 // pushContext is called when we enter a statement. 122 func (nr *nameResolver) pushContext() { 123 nr.contextStack = append(nr.contextStack, &resolverContext{ 124 tableMap: map[string]int{}, 125 derivedTableMap: map[string]int{}, 126 }) 127 } 128 129 // popContext is called when we leave a statement. 130 func (nr *nameResolver) popContext() { 131 nr.contextStack = nr.contextStack[:len(nr.contextStack)-1] 132 } 133 134 // pushJoin is called when we enter a join node. 135 func (nr *nameResolver) pushJoin(j *ast.Join) { 136 ctx := nr.currentContext() 137 ctx.joinNodeStack = append(ctx.joinNodeStack, j) 138 } 139 140 // popJoin is called when we leave a join node. 141 func (nr *nameResolver) popJoin() { 142 ctx := nr.currentContext() 143 ctx.joinNodeStack = ctx.joinNodeStack[:len(ctx.joinNodeStack)-1] 144 } 145 146 // Enter implements ast.Visitor interface. 147 func (nr *nameResolver) Enter(inNode ast.Node) (outNode ast.Node, skipChildren bool) { 148 switch v := inNode.(type) { 149 case *ast.AdminStmt: 150 nr.pushContext() 151 case *ast.AggregateFuncExpr: 152 ctx := nr.currentContext() 153 if ctx.inHaving { 154 ctx.inHavingAgg = true 155 } 156 case *ast.AlterTableStmt: 157 nr.pushContext() 158 case *ast.ByItem: 159 if _, ok := v.Expr.(*ast.ColumnNameExpr); !ok { 160 // If ByItem is not a single column name expression, 161 // the resolving rule is different from order by clause. 162 nr.currentContext().inByItemExpression = true 163 } 164 if nr.currentContext().inGroupBy { 165 // make sure item is not aggregate function 166 if ast.HasAggFlag(v.Expr) { 167 nr.Err = ErrInvalidGroupFuncUse 168 return inNode, true 169 } 170 } 171 case *ast.CreateIndexStmt: 172 nr.pushContext() 173 case *ast.CreateTableStmt: 174 nr.pushContext() 175 nr.currentContext().inCreateOrDropTable = true 176 case *ast.DeleteStmt: 177 nr.pushContext() 178 case *ast.DeleteTableList: 179 nr.currentContext().inDeleteTableList = true 180 case *ast.DoStmt: 181 nr.pushContext() 182 case *ast.DropTableStmt: 183 nr.pushContext() 184 nr.currentContext().inCreateOrDropTable = true 185 case *ast.DropIndexStmt: 186 nr.pushContext() 187 case *ast.FieldList: 188 nr.currentContext().inFieldList = true 189 case *ast.GroupByClause: 190 nr.currentContext().inGroupBy = true 191 case *ast.HavingClause: 192 nr.currentContext().inHaving = true 193 case *ast.InsertStmt: 194 nr.pushContext() 195 case *ast.Join: 196 nr.pushJoin(v) 197 case *ast.OnCondition: 198 nr.currentContext().inOnCondition = true 199 case *ast.OrderByClause: 200 nr.currentContext().inOrderBy = true 201 case *ast.SelectStmt: 202 nr.pushContext() 203 case *ast.SetStmt: 204 for _, assign := range v.Variables { 205 if cn, ok := assign.Value.(*ast.ColumnNameExpr); ok && cn.Name.Table.L == "" { 206 // Convert column name expression to string value expression. 207 assign.Value = ast.NewValueExpr(cn.Name.Name.O) 208 } 209 } 210 nr.pushContext() 211 case *ast.ShowStmt: 212 nr.pushContext() 213 nr.currentContext().inShow = true 214 nr.fillShowFields(v) 215 case *ast.TableRefsClause: 216 nr.currentContext().inTableRefs = true 217 case *ast.TruncateTableStmt: 218 nr.pushContext() 219 case *ast.UnionStmt: 220 nr.pushContext() 221 case *ast.UpdateStmt: 222 nr.pushContext() 223 } 224 return inNode, false 225 } 226 227 // Leave implements ast.Visitor interface. 228 func (nr *nameResolver) Leave(inNode ast.Node) (node ast.Node, ok bool) { 229 switch v := inNode.(type) { 230 case *ast.AdminStmt: 231 nr.popContext() 232 case *ast.AggregateFuncExpr: 233 ctx := nr.currentContext() 234 if ctx.inHaving { 235 ctx.inHavingAgg = false 236 } 237 case *ast.AlterTableStmt: 238 nr.popContext() 239 case *ast.TableName: 240 nr.handleTableName(v) 241 case *ast.ColumnNameExpr: 242 nr.handleColumnName(v) 243 case *ast.CreateIndexStmt: 244 nr.popContext() 245 case *ast.CreateTableStmt: 246 nr.popContext() 247 case *ast.DeleteTableList: 248 nr.currentContext().inDeleteTableList = false 249 case *ast.DoStmt: 250 nr.popContext() 251 case *ast.DropIndexStmt: 252 nr.popContext() 253 case *ast.DropTableStmt: 254 nr.popContext() 255 case *ast.TableSource: 256 nr.handleTableSource(v) 257 case *ast.OnCondition: 258 nr.currentContext().inOnCondition = false 259 case *ast.Join: 260 nr.handleJoin(v) 261 nr.popJoin() 262 case *ast.TableRefsClause: 263 nr.currentContext().inTableRefs = false 264 case *ast.FieldList: 265 nr.handleFieldList(v) 266 nr.currentContext().inFieldList = false 267 case *ast.GroupByClause: 268 ctx := nr.currentContext() 269 ctx.inGroupBy = false 270 for _, item := range v.Items { 271 switch x := item.Expr.(type) { 272 case *ast.ColumnNameExpr: 273 ctx.groupBy = append(ctx.groupBy, x.Refer) 274 } 275 } 276 case *ast.HavingClause: 277 nr.currentContext().inHaving = false 278 case *ast.OrderByClause: 279 nr.currentContext().inOrderBy = false 280 case *ast.ByItem: 281 nr.currentContext().inByItemExpression = false 282 case *ast.PositionExpr: 283 nr.handlePosition(v) 284 case *ast.SelectStmt: 285 ctx := nr.currentContext() 286 v.SetResultFields(ctx.fieldList) 287 if ctx.useOuterContext { 288 nr.useOuterContext = true 289 } 290 nr.popContext() 291 case *ast.SetStmt: 292 nr.popContext() 293 case *ast.ShowStmt: 294 nr.popContext() 295 case *ast.SubqueryExpr: 296 if nr.useOuterContext { 297 // TODO: check this 298 // If there is a deep nest of subquery, there may be something wrong. 299 v.Correlated = true 300 nr.useOuterContext = false 301 } 302 case *ast.TruncateTableStmt: 303 nr.popContext() 304 case *ast.UnionStmt: 305 ctx := nr.currentContext() 306 v.SetResultFields(ctx.fieldList) 307 if ctx.useOuterContext { 308 nr.useOuterContext = true 309 } 310 nr.popContext() 311 case *ast.UnionSelectList: 312 nr.handleUnionSelectList(v) 313 case *ast.InsertStmt: 314 nr.popContext() 315 case *ast.DeleteStmt: 316 nr.popContext() 317 case *ast.UpdateStmt: 318 nr.popContext() 319 } 320 return inNode, nr.Err == nil 321 } 322 323 // handleTableName looks up and sets the schema information and result fields for table name. 324 func (nr *nameResolver) handleTableName(tn *ast.TableName) { 325 if tn.Schema.L == "" { 326 tn.Schema = nr.DefaultSchema 327 } 328 ctx := nr.currentContext() 329 if ctx.inCreateOrDropTable { 330 // The table may not exist in create table or drop table statement. 331 // Skip resolving the table to avoid error. 332 return 333 } 334 if ctx.inDeleteTableList { 335 idx, ok := ctx.tableMap[nr.tableUniqueName(tn.Schema, tn.Name)] 336 if !ok { 337 nr.Err = errors.Errorf("Unknown table %s", tn.Name.O) 338 return 339 } 340 ts := ctx.tables[idx] 341 tableName := ts.Source.(*ast.TableName) 342 tn.DBInfo = tableName.DBInfo 343 tn.TableInfo = tableName.TableInfo 344 tn.SetResultFields(tableName.GetResultFields()) 345 return 346 } 347 table, err := nr.Info.TableByName(tn.Schema, tn.Name) 348 if err != nil { 349 nr.Err = errors.Trace(err) 350 return 351 } 352 tn.TableInfo = table.Meta() 353 dbInfo, _ := nr.Info.SchemaByName(tn.Schema) 354 tn.DBInfo = dbInfo 355 356 rfs := make([]*ast.ResultField, 0, len(tn.TableInfo.Columns)) 357 for _, v := range tn.TableInfo.Columns { 358 if v.State != model.StatePublic { 359 continue 360 } 361 expr := &ast.ValueExpr{} 362 expr.SetType(&v.FieldType) 363 rf := &ast.ResultField{ 364 Column: v, 365 Table: tn.TableInfo, 366 DBName: tn.Schema, 367 Expr: expr, 368 TableName: tn, 369 } 370 rfs = append(rfs, rf) 371 } 372 tn.SetResultFields(rfs) 373 return 374 } 375 376 // handleTableSources checks name duplication 377 // and puts the table source in current resolverContext. 378 // Note: 379 // "select * from t as a join (select 1) as a;" is not duplicate. 380 // "select * from t as a join t as a;" is duplicate. 381 // "select * from (select 1) as a join (select 1) as a;" is duplicate. 382 func (nr *nameResolver) handleTableSource(ts *ast.TableSource) { 383 for _, v := range ts.GetResultFields() { 384 v.TableAsName = ts.AsName 385 } 386 ctx := nr.currentContext() 387 switch ts.Source.(type) { 388 case *ast.TableName: 389 var name string 390 if ts.AsName.L != "" { 391 name = ts.AsName.L 392 } else { 393 tableName := ts.Source.(*ast.TableName) 394 name = nr.tableUniqueName(tableName.Schema, tableName.Name) 395 } 396 if _, ok := ctx.tableMap[name]; ok { 397 nr.Err = errors.Errorf("duplicated table/alias name %s", name) 398 return 399 } 400 ctx.tableMap[name] = len(ctx.tables) 401 case *ast.SelectStmt: 402 name := ts.AsName.L 403 if _, ok := ctx.derivedTableMap[name]; ok { 404 nr.Err = errors.Errorf("duplicated table/alias name %s", name) 405 return 406 } 407 ctx.derivedTableMap[name] = len(ctx.tables) 408 } 409 dupNames := make(map[string]struct{}, len(ts.GetResultFields())) 410 for _, f := range ts.GetResultFields() { 411 // duplicate column name in one table is not allowed. 412 // "select * from (select 1, 1) as a;" is duplicate. 413 name := f.ColumnAsName.L 414 if name == "" { 415 name = f.Column.Name.L 416 } 417 if _, ok := dupNames[name]; ok { 418 nr.Err = errors.Errorf("Duplicate column name '%s'", name) 419 return 420 } 421 dupNames[name] = struct{}{} 422 } 423 ctx.tables = append(ctx.tables, ts) 424 return 425 } 426 427 // handleJoin sets result fields for join. 428 func (nr *nameResolver) handleJoin(j *ast.Join) { 429 if j.Right == nil { 430 j.SetResultFields(j.Left.GetResultFields()) 431 return 432 } 433 leftLen := len(j.Left.GetResultFields()) 434 rightLen := len(j.Right.GetResultFields()) 435 rfs := make([]*ast.ResultField, leftLen+rightLen) 436 copy(rfs, j.Left.GetResultFields()) 437 copy(rfs[leftLen:], j.Right.GetResultFields()) 438 j.SetResultFields(rfs) 439 } 440 441 // handleColumnName looks up and sets ResultField for 442 // the column name. 443 func (nr *nameResolver) handleColumnName(cn *ast.ColumnNameExpr) { 444 ctx := nr.currentContext() 445 if ctx.inOnCondition { 446 // In on condition, only tables within current join is available. 447 nr.resolveColumnNameInOnCondition(cn) 448 return 449 } 450 451 // Try to resolve the column name form top to bottom in the context stack. 452 for i := len(nr.contextStack) - 1; i >= 0; i-- { 453 if nr.resolveColumnNameInContext(nr.contextStack[i], cn) { 454 // Column is already resolved or encountered an error. 455 if i < len(nr.contextStack)-1 { 456 // If in subselect, the query use outer query. 457 nr.currentContext().useOuterContext = true 458 } 459 return 460 } 461 } 462 nr.Err = errors.Errorf("unknown column %s", cn.Name.Name.L) 463 } 464 465 // resolveColumnNameInContext looks up and sets ResultField for a column with the ctx. 466 func (nr *nameResolver) resolveColumnNameInContext(ctx *resolverContext, cn *ast.ColumnNameExpr) bool { 467 if ctx.inTableRefs { 468 // In TableRefsClause, column reference only in join on condition which is handled before. 469 return false 470 } 471 if ctx.inFieldList { 472 // only resolve column using tables. 473 return nr.resolveColumnInTableSources(cn, ctx.tables) 474 } 475 if ctx.inGroupBy { 476 // From tables first, then field list. 477 // If ctx.InByItemExpression is true, the item is not an identifier. 478 // Otherwise it is an identifier. 479 if ctx.inByItemExpression { 480 // From table first, then field list. 481 if nr.resolveColumnInTableSources(cn, ctx.tables) { 482 return true 483 } 484 found := nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) 485 if nr.Err == nil && found { 486 // Check if resolved refer is an aggregate function expr. 487 if _, ok := cn.Refer.Expr.(*ast.AggregateFuncExpr); ok { 488 nr.Err = ErrIllegalReference.Gen("Reference '%s' not supported (reference to group function)", cn.Name.Name.O) 489 } 490 } 491 return found 492 } 493 // Resolve from table first, then from select list. 494 found := nr.resolveColumnInTableSources(cn, ctx.tables) 495 if nr.Err != nil { 496 return found 497 } 498 // We should copy the refer here. 499 // Because if the ByItem is an identifier, we should check if it 500 // is ambiguous even it is already resolved from table source. 501 // If the ByItem is not an identifier, we do not need the second check. 502 r := cn.Refer 503 if nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) { 504 if nr.Err != nil { 505 return true 506 } 507 if r != nil { 508 // It is not ambiguous and already resolved from table source. 509 // We should restore its Refer. 510 cn.Refer = r 511 } 512 if _, ok := cn.Refer.Expr.(*ast.AggregateFuncExpr); ok { 513 nr.Err = ErrIllegalReference.Gen("Reference '%s' not supported (reference to group function)", cn.Name.Name.O) 514 } 515 return true 516 } 517 return found 518 } 519 if ctx.inHaving { 520 // First group by, then field list. 521 if nr.resolveColumnInResultFields(ctx, cn, ctx.groupBy) { 522 return true 523 } 524 if ctx.inHavingAgg { 525 // If cn is in an aggregate function in having clause, check tablesource first. 526 if nr.resolveColumnInTableSources(cn, ctx.tables) { 527 return true 528 } 529 } 530 return nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) 531 } 532 if ctx.inOrderBy { 533 if nr.resolveColumnInResultFields(ctx, cn, ctx.groupBy) { 534 return true 535 } 536 if ctx.inByItemExpression { 537 // From table first, then field list. 538 if nr.resolveColumnInTableSources(cn, ctx.tables) { 539 return true 540 } 541 return nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) 542 } 543 // Field list first, then from table. 544 if nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) { 545 return true 546 } 547 return nr.resolveColumnInTableSources(cn, ctx.tables) 548 } 549 if ctx.inShow { 550 return nr.resolveColumnInResultFields(ctx, cn, ctx.fieldList) 551 } 552 // In where clause. 553 return nr.resolveColumnInTableSources(cn, ctx.tables) 554 } 555 556 // resolveColumnNameInOnCondition resolves the column name in current join. 557 func (nr *nameResolver) resolveColumnNameInOnCondition(cn *ast.ColumnNameExpr) { 558 ctx := nr.currentContext() 559 join := ctx.joinNodeStack[len(ctx.joinNodeStack)-1] 560 tableSources := appendTableSources(nil, join) 561 if !nr.resolveColumnInTableSources(cn, tableSources) { 562 nr.Err = errors.Errorf("unkown column name %s", cn.Name.Name.O) 563 } 564 } 565 566 func (nr *nameResolver) resolveColumnInTableSources(cn *ast.ColumnNameExpr, tableSources []*ast.TableSource) (done bool) { 567 var matchedResultField *ast.ResultField 568 tableNameL := cn.Name.Table.L 569 columnNameL := cn.Name.Name.L 570 if tableNameL != "" { 571 var matchedTable ast.ResultSetNode 572 for _, ts := range tableSources { 573 if tableNameL == ts.AsName.L { 574 // different table name. 575 matchedTable = ts 576 break 577 } else if ts.AsName.L != "" { 578 // Table as name shadows table real name. 579 continue 580 } 581 if tn, ok := ts.Source.(*ast.TableName); ok { 582 if cn.Name.Schema.L != "" && cn.Name.Schema.L != tn.Schema.L { 583 continue 584 } 585 if tableNameL == tn.Name.L { 586 matchedTable = ts 587 } 588 } 589 } 590 if matchedTable != nil { 591 resultFields := matchedTable.GetResultFields() 592 for _, rf := range resultFields { 593 if rf.ColumnAsName.L == columnNameL || rf.Column.Name.L == columnNameL { 594 // resolve column. 595 matchedResultField = rf 596 break 597 } 598 } 599 } 600 } else { 601 for _, ts := range tableSources { 602 rfs := ts.GetResultFields() 603 for _, rf := range rfs { 604 matchAsName := rf.ColumnAsName.L != "" && rf.ColumnAsName.L == columnNameL 605 matchColumnName := rf.ColumnAsName.L == "" && rf.Column.Name.L == columnNameL 606 if matchAsName || matchColumnName { 607 if matchedResultField != nil { 608 nr.Err = errors.Errorf("column %s is ambiguous.", cn.Name.Name.O) 609 return true 610 } 611 matchedResultField = rf 612 } 613 } 614 } 615 } 616 if matchedResultField != nil { 617 // Bind column. 618 cn.Refer = matchedResultField 619 matchedResultField.Referenced = true 620 return true 621 } 622 return false 623 } 624 625 func (nr *nameResolver) resolveColumnInResultFields(ctx *resolverContext, cn *ast.ColumnNameExpr, rfs []*ast.ResultField) bool { 626 var matched *ast.ResultField 627 for _, rf := range rfs { 628 if cn.Name.Table.L != "" { 629 // Check table name 630 if rf.TableAsName.L != "" { 631 if cn.Name.Table.L != rf.TableAsName.L { 632 continue 633 } 634 } else if cn.Name.Table.L != rf.Table.Name.L { 635 continue 636 } 637 } 638 matchAsName := cn.Name.Name.L == rf.ColumnAsName.L 639 var matchColumnName bool 640 if ctx.inHaving { 641 matchColumnName = cn.Name.Name.L == rf.Column.Name.L 642 } else { 643 matchColumnName = rf.ColumnAsName.L == "" && cn.Name.Name.L == rf.Column.Name.L 644 } 645 if matchAsName || matchColumnName { 646 if rf.Column.Name.L == "" { 647 // This is not a real table column, resolve it directly. 648 cn.Refer = rf 649 rf.Referenced = true 650 return true 651 } 652 if matched == nil { 653 matched = rf 654 } else { 655 sameColumn := matched.TableName == rf.TableName && matched.Column.Name.L == rf.Column.Name.L 656 if !sameColumn { 657 nr.Err = errors.Errorf("column %s is ambiguous.", cn.Name.Name.O) 658 return true 659 } 660 } 661 } 662 } 663 if matched != nil { 664 // If in GroupBy, we clone the ResultField 665 if ctx.inGroupBy || ctx.inHaving || ctx.inOrderBy { 666 nf := *matched 667 expr := matched.Expr 668 if cexpr, ok := expr.(*ast.ColumnNameExpr); ok { 669 expr = cexpr.Refer.Expr 670 } 671 nf.Expr = expr 672 matched = &nf 673 } 674 // Bind column. 675 cn.Refer = matched 676 matched.Referenced = true 677 return true 678 } 679 return false 680 } 681 682 // handleFieldList expands wild card field and sets fieldList in current context. 683 func (nr *nameResolver) handleFieldList(fieldList *ast.FieldList) { 684 var resultFields []*ast.ResultField 685 for _, v := range fieldList.Fields { 686 resultFields = append(resultFields, nr.createResultFields(v)...) 687 } 688 nr.currentContext().fieldList = resultFields 689 } 690 691 func getInnerFromParentheses(expr ast.ExprNode) ast.ExprNode { 692 if pexpr, ok := expr.(*ast.ParenthesesExpr); ok { 693 return getInnerFromParentheses(pexpr.Expr) 694 } 695 return expr 696 } 697 698 // createResultFields creates result field list for a single select field. 699 func (nr *nameResolver) createResultFields(field *ast.SelectField) (rfs []*ast.ResultField) { 700 ctx := nr.currentContext() 701 if field.WildCard != nil { 702 if len(ctx.tables) == 0 { 703 nr.Err = errors.New("No table used.") 704 return 705 } 706 tableRfs := []*ast.ResultField{} 707 if field.WildCard.Table.L == "" { 708 for _, v := range ctx.tables { 709 tableRfs = append(tableRfs, v.GetResultFields()...) 710 } 711 } else { 712 name := nr.tableUniqueName(field.WildCard.Schema, field.WildCard.Table) 713 tableIdx, ok1 := ctx.tableMap[name] 714 derivedTableIdx, ok2 := ctx.derivedTableMap[name] 715 if !ok1 && !ok2 { 716 nr.Err = errors.Errorf("unknown table %s.", field.WildCard.Table.O) 717 } 718 if ok1 { 719 tableRfs = ctx.tables[tableIdx].GetResultFields() 720 } 721 if ok2 { 722 tableRfs = append(tableRfs, ctx.tables[derivedTableIdx].GetResultFields()...) 723 } 724 725 } 726 for _, trf := range tableRfs { 727 trf.Referenced = true 728 // Convert it to ColumnNameExpr 729 cn := &ast.ColumnName{ 730 Schema: trf.DBName, 731 Table: trf.Table.Name, 732 Name: trf.ColumnAsName, 733 } 734 cnExpr := &ast.ColumnNameExpr{ 735 Name: cn, 736 Refer: trf, 737 } 738 ast.SetFlag(cnExpr) 739 cnExpr.SetType(trf.Expr.GetType()) 740 rf := *trf 741 rf.Expr = cnExpr 742 rfs = append(rfs, &rf) 743 } 744 return 745 } 746 // The column is visited before so it must has been resolved already. 747 rf := &ast.ResultField{ColumnAsName: field.AsName} 748 innerExpr := getInnerFromParentheses(field.Expr) 749 switch v := innerExpr.(type) { 750 case *ast.ColumnNameExpr: 751 rf.Column = v.Refer.Column 752 rf.Table = v.Refer.Table 753 rf.DBName = v.Refer.DBName 754 rf.TableName = v.Refer.TableName 755 rf.Expr = v 756 default: 757 rf.Column = &model.ColumnInfo{} // Empty column info. 758 rf.Table = &model.TableInfo{} // Empty table info. 759 rf.Expr = v 760 } 761 if field.AsName.L == "" { 762 switch x := innerExpr.(type) { 763 case *ast.ColumnNameExpr: 764 rf.ColumnAsName = model.NewCIStr(x.Name.Name.O) 765 case *ast.ValueExpr: 766 if innerExpr.Text() != "" { 767 rf.ColumnAsName = model.NewCIStr(innerExpr.Text()) 768 } else { 769 rf.ColumnAsName = model.NewCIStr(field.Text()) 770 } 771 default: 772 rf.ColumnAsName = model.NewCIStr(field.Text()) 773 } 774 } 775 rfs = append(rfs, rf) 776 return 777 } 778 779 func appendTableSources(in []*ast.TableSource, resultSetNode ast.ResultSetNode) (out []*ast.TableSource) { 780 switch v := resultSetNode.(type) { 781 case *ast.TableSource: 782 out = append(in, v) 783 case *ast.Join: 784 out = appendTableSources(in, v.Left) 785 if v.Right != nil { 786 out = appendTableSources(out, v.Right) 787 } 788 } 789 return 790 } 791 792 func (nr *nameResolver) tableUniqueName(schema, table model.CIStr) string { 793 if schema.L != "" && schema.L != nr.DefaultSchema.L { 794 return schema.L + "." + table.L 795 } 796 return table.L 797 } 798 799 func (nr *nameResolver) handlePosition(pos *ast.PositionExpr) { 800 ctx := nr.currentContext() 801 if pos.N < 1 || pos.N > len(ctx.fieldList) { 802 nr.Err = errors.Errorf("Unknown column '%d'", pos.N) 803 return 804 } 805 matched := ctx.fieldList[pos.N-1] 806 nf := *matched 807 expr := matched.Expr 808 if cexpr, ok := expr.(*ast.ColumnNameExpr); ok { 809 expr = cexpr.Refer.Expr 810 } 811 nf.Expr = expr 812 pos.Refer = &nf 813 pos.Refer.Referenced = true 814 if nr.currentContext().inGroupBy { 815 // make sure item is not aggregate function 816 if ast.HasAggFlag(pos.Refer.Expr) { 817 nr.Err = errors.New("group by cannot contain aggregate function") 818 } 819 } 820 } 821 822 func (nr *nameResolver) handleUnionSelectList(u *ast.UnionSelectList) { 823 firstSelFields := u.Selects[0].GetResultFields() 824 unionFields := make([]*ast.ResultField, len(firstSelFields)) 825 // Copy first result fields, because we may change the result field type. 826 for i, v := range firstSelFields { 827 rf := *v 828 col := *v.Column 829 rf.Column = &col 830 if rf.Column.Flen == 0 { 831 rf.Column.Flen = types.UnspecifiedLength 832 } 833 rf.Expr = &ast.ValueExpr{} 834 unionFields[i] = &rf 835 } 836 nr.currentContext().fieldList = unionFields 837 } 838 839 func (nr *nameResolver) fillShowFields(s *ast.ShowStmt) { 840 if s.DBName == "" { 841 if s.Table != nil && s.Table.Schema.L != "" { 842 s.DBName = s.Table.Schema.O 843 } else { 844 s.DBName = nr.DefaultSchema.O 845 } 846 } else if s.Table != nil && s.Table.Schema.L == "" { 847 s.Table.Schema = model.NewCIStr(s.DBName) 848 } 849 var fields []*ast.ResultField 850 var ( 851 names []string 852 ftypes []byte 853 ) 854 switch s.Tp { 855 case ast.ShowEngines: 856 names = []string{"Engine", "Support", "Comment", "Transactions", "XA", "Savepoints"} 857 case ast.ShowDatabases: 858 names = []string{"Database"} 859 case ast.ShowTables: 860 names = []string{fmt.Sprintf("Tables_in_%s", s.DBName)} 861 if s.Full { 862 names = append(names, "Table_type") 863 } 864 case ast.ShowTableStatus: 865 names = []string{"Name", "Engine", "Version", "Row_format", "Rows", "Avg_row_length", 866 "Data_length", "Max_data_length", "Index_length", "Data_free", "Auto_increment", 867 "Create_time", "Update_time", "Check_time", "Collation", "Checksum", 868 "Create_options", "Comment"} 869 ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeLonglong, 870 mysql.TypeLonglong, mysql.TypeLonglong, mysql.TypeLonglong, mysql.TypeLonglong, mysql.TypeLonglong, 871 mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar, mysql.TypeVarchar, 872 mysql.TypeVarchar, mysql.TypeVarchar} 873 case ast.ShowColumns: 874 names = column.ColDescFieldNames(s.Full) 875 case ast.ShowWarnings: 876 names = []string{"Level", "Code", "Message"} 877 ftypes = []byte{mysql.TypeVarchar, mysql.TypeLong, mysql.TypeVarchar} 878 case ast.ShowCharset: 879 names = []string{"Charset", "Description", "Default collation", "Maxlen"} 880 ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong} 881 case ast.ShowVariables: 882 names = []string{"Variable_name", "Value"} 883 case ast.ShowStatus: 884 names = []string{"Variable_name", "Value"} 885 case ast.ShowCollation: 886 names = []string{"Collation", "Charset", "Id", "Default", "Compiled", "Sortlen"} 887 ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, 888 mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong} 889 case ast.ShowCreateTable: 890 names = []string{"Table", "Create Table"} 891 case ast.ShowGrants: 892 names = []string{fmt.Sprintf("Grants for %s", s.User)} 893 case ast.ShowTriggers: 894 names = []string{"Trigger", "Event", "Table", "Statement", "Timing", "Created", 895 "sql_mode", "Definer", "character_set_client", "collation_connection", "Database Collation"} 896 ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, 897 mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar} 898 case ast.ShowProcedureStatus: 899 names = []string{} 900 ftypes = []byte{} 901 case ast.ShowIndex: 902 names = []string{"Table", "Non_unique", "Key_name", "Seq_in_index", 903 "Column_name", "Collation", "Cardinality", "Sub_part", "Packed", 904 "Null", "Index_type", "Comment", "Index_comment"} 905 ftypes = []byte{mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeLonglong, 906 mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeLonglong, 907 mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar} 908 } 909 for i, name := range names { 910 f := &ast.ResultField{ 911 ColumnAsName: model.NewCIStr(name), 912 Column: &model.ColumnInfo{}, // Empty column info. 913 Table: &model.TableInfo{}, // Empty table info. 914 } 915 if ftypes == nil || ftypes[i] == 0 { 916 // use varchar as the default return column type 917 f.Column.Tp = mysql.TypeVarchar 918 } else { 919 f.Column.Tp = ftypes[i] 920 } 921 f.Column.Charset, f.Column.Collate = types.DefaultCharsetForType(f.Column.Tp) 922 f.Expr = &ast.ValueExpr{} 923 f.Expr.SetType(&f.Column.FieldType) 924 fields = append(fields, f) 925 } 926 927 if s.Pattern != nil && s.Pattern.Expr == nil { 928 rf := fields[0] 929 s.Pattern.Expr = &ast.ColumnNameExpr{ 930 Name: &ast.ColumnName{Name: rf.ColumnAsName}, 931 } 932 ast.SetFlag(s.Pattern) 933 } 934 s.SetResultFields(fields) 935 nr.currentContext().fieldList = fields 936 }