func (b *planBuilder) buildTableScanPlan(tn *ast.TableName, conditions []ast.ExprNode) Plan { p := &TableScan{ Table: tn.TableInfo, } p.SetFields(tn.GetResultFields()) var pkName model.CIStr if p.Table.PKIsHandle { for _, colInfo := range p.Table.Columns { if mysql.HasPriKeyFlag(colInfo.Flag) { pkName = colInfo.Name } } } for _, con := range conditions { if pkName.L != "" { checker := conditionChecker{tableName: tn.TableInfo.Name, pkName: pkName} if checker.check(con) { p.AccessConditions = append(p.AccessConditions, con) } else { p.FilterConditions = append(p.FilterConditions, con) } } else { p.FilterConditions = append(p.FilterConditions, con) } } return p }
// handleTableName looks up and sets the schema information and result fields for table name. func (nr *nameResolver) handleTableName(tn *ast.TableName) { if tn.Schema.L == "" { tn.Schema = nr.DefaultSchema } table, err := nr.Info.TableByName(tn.Schema, tn.Name) if err != nil { nr.Err = err return } tn.TableInfo = table.Meta() dbInfo, _ := nr.Info.SchemaByName(tn.Schema) tn.DBInfo = dbInfo rfs := make([]*ast.ResultField, len(tn.TableInfo.Columns)) for i, v := range tn.TableInfo.Columns { expr := &ast.ValueExpr{} expr.SetType(&v.FieldType) rfs[i] = &ast.ResultField{ Column: v, Table: tn.TableInfo, DBName: tn.Schema, Expr: expr, TableName: tn, } } tn.SetResultFields(rfs) return }
func (b *executorBuilder) columnNameToPBExpr(client kv.Client, column *ast.ColumnNameExpr, tn *ast.TableName) *tipb.Expr { if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_ColumnRef)) { return nil } // Zero Column ID is not a column from table, can not support for now. if column.Refer.Column.ID == 0 { return nil } switch column.Refer.Expr.GetType().Tp { case mysql.TypeBit, mysql.TypeSet, mysql.TypeEnum, mysql.TypeDecimal, mysql.TypeGeometry, mysql.TypeDate, mysql.TypeNewDate, mysql.TypeDatetime, mysql.TypeTimestamp, mysql.TypeYear: return nil } matched := false for _, f := range tn.GetResultFields() { if f.TableName == column.Refer.TableName && f.Column.ID == column.Refer.Column.ID { matched = true break } } if matched { pbExpr := new(tipb.Expr) pbExpr.Tp = tipb.ExprType_ColumnRef.Enum() pbExpr.Val = codec.EncodeInt(nil, column.Refer.Column.ID) return pbExpr } // If the column ID isn't in fields, it means the column is from an outer table, // its value is available to use. return b.datumToPBExpr(client, *column.Refer.Expr.GetDatum()) }
func (b *planBuilder) buildDataSource(tn *ast.TableName) LogicalPlan { statisticTable := b.getTableStats(tn.TableInfo) if b.err != nil { return nil } p := &DataSource{ table: tn, Table: tn.TableInfo, baseLogicalPlan: newBaseLogicalPlan(Ts, b.allocator), statisticTable: statisticTable, } p.initID() // Equal condition contains a column from previous joined table. rfs := tn.GetResultFields() schema := make([]*expression.Column, 0, len(rfs)) for i, rf := range rfs { p.DBName = &rf.DBName p.Columns = append(p.Columns, rf.Column) schema = append(schema, &expression.Column{ FromID: p.id, ColName: rf.Column.Name, TblName: rf.Table.Name, DBName: rf.DBName, RetType: &rf.Column.FieldType, Position: i}) } p.SetSchema(schema) return p }
func (b *planBuilder) buildIndexScanPlan(index *model.IndexInfo, tn *ast.TableName, conditions []ast.ExprNode) Plan { ip := &IndexScan{Table: tn.TableInfo, Index: index} ip.SetFields(tn.GetResultFields()) condMap := map[ast.ExprNode]bool{} for _, con := range conditions { condMap[con] = true } out: // Build equal access conditions first. // Starts from the first index column, if equal condition is found, add it to access conditions, // proceed to the next index column. until we can't find any equal condition for the column. for ip.AccessEqualCount < len(index.Columns) { for con := range condMap { binop, ok := con.(*ast.BinaryOperationExpr) if !ok || binop.Op != opcode.EQ { continue } if ast.IsPreEvaluable(binop.L) { binop.L, binop.R = binop.R, binop.L } if !ast.IsPreEvaluable(binop.R) { continue } cn, ok2 := binop.L.(*ast.ColumnNameExpr) if !ok2 || cn.Refer.Column.Name.L != index.Columns[ip.AccessEqualCount].Name.L { continue } ip.AccessConditions = append(ip.AccessConditions, con) delete(condMap, con) ip.AccessEqualCount++ continue out } break } for con := range condMap { if ip.AccessEqualCount < len(ip.Index.Columns) { // Try to add non-equal access condition for index column at AccessEqualCount. checker := conditionChecker{tableName: tn.TableInfo.Name, idx: index, columnOffset: ip.AccessEqualCount} if checker.check(con) { ip.AccessConditions = append(ip.AccessConditions, con) } else { ip.FilterConditions = append(ip.FilterConditions, con) } } else { ip.FilterConditions = append(ip.FilterConditions, con) } } return ip }
// handleTableName looks up and sets the schema information and result fields for table name. func (nr *nameResolver) handleTableName(tn *ast.TableName) { if tn.Schema.L == "" { tn.Schema = nr.DefaultSchema } ctx := nr.currentContext() if ctx.inCreateOrDropTable { // The table may not exist in create table or drop table statement. // Skip resolving the table to avoid error. return } if ctx.inDeleteTableList { idx, ok := ctx.tableMap[nr.tableUniqueName(tn.Schema, tn.Name)] if !ok { nr.Err = errors.Errorf("Unknown table %s", tn.Name.O) return } ts := ctx.tables[idx] tableName := ts.Source.(*ast.TableName) tn.DBInfo = tableName.DBInfo tn.TableInfo = tableName.TableInfo tn.SetResultFields(tableName.GetResultFields()) return } table, err := nr.Info.TableByName(tn.Schema, tn.Name) if err != nil { nr.Err = errors.Trace(err) return } tn.TableInfo = table.Meta() dbInfo, _ := nr.Info.SchemaByName(tn.Schema) tn.DBInfo = dbInfo rfs := make([]*ast.ResultField, 0, len(tn.TableInfo.Columns)) sVars := variable.GetSessionVars(nr.Ctx) for _, v := range tn.TableInfo.Columns { if v.State != model.StatePublic { if !sVars.InUpdateStmt || v.State != model.StateWriteReorganization { // TODO: check this continue } } expr := &ast.ValueExpr{} expr.SetType(&v.FieldType) rf := &ast.ResultField{ Column: v, Table: tn.TableInfo, DBName: tn.Schema, Expr: expr, TableName: tn, } rfs = append(rfs, rf) } tn.SetResultFields(rfs) return }
func (b *planBuilder) buildIndexScanPlan(index *model.IndexInfo, tn *ast.TableName, conditions []ast.ExprNode) Plan { ip := &IndexScan{Table: tn.TableInfo, Index: index} ip.SetFields(tn.GetResultFields()) // Only use first column as access condition for cost estimation, // In executor, we can try to use second index column to build index range. checker := conditionChecker{tableName: tn.TableInfo.Name, idx: index, columnOffset: 0} for _, con := range conditions { if checker.check(con) { ip.AccessConditions = append(ip.AccessConditions, con) } else { ip.FilterConditions = append(ip.FilterConditions, con) } } return ip }
func (b *planBuilder) buildNewTableScanPlan(tn *ast.TableName) LogicalPlan { p := &NewTableScan{Table: tn.TableInfo, baseLogicalPlan: newBaseLogicalPlan(Ts, b.allocator)} p.initID() // Equal condition contains a column from previous joined table. rfs := tn.GetResultFields() schema := make([]*expression.Column, 0, len(rfs)) for i, rf := range rfs { p.DBName = &rf.DBName p.Columns = append(p.Columns, rf.Column) schema = append(schema, &expression.Column{ FromID: p.id, ColName: rf.Column.Name, TblName: rf.Table.Name, DBName: rf.DBName, RetType: &rf.Column.FieldType, Position: i}) } p.SetSchema(schema) return p }
func (b *planBuilder) buildNewTableScanPlan(tn *ast.TableName) Plan { p := &NewTableScan{ Table: tn.TableInfo, } p.id = b.allocID(p) // Equal condition contains a column from previous joined table. p.RefAccess = false rfs := tn.GetResultFields() schema := make([]*expression.Column, 0, len(rfs)) for _, rf := range rfs { p.DBName = &rf.DBName p.Columns = append(p.Columns, rf.Column) schema = append(schema, &expression.Column{ FromID: p.id, ColName: rf.Column.Name, TblName: rf.Table.Name, DBName: rf.DBName, RetType: &rf.Column.FieldType}) } p.SetSchema(schema) return p }
// handleTableName looks up and sets the schema information and result fields for table name. func (nr *nameResolver) handleTableName(tn *ast.TableName) { if tn.Schema.L == "" { tn.Schema = nr.DefaultSchema } ctx := nr.currentContext() if ctx.inDeleteTableList { idx, ok := ctx.tableMap[nr.tableUniqueName(tn.Schema, tn.Name)] if !ok { nr.Err = errors.Errorf("Unknown table %s", tn.Name.O) return } ts := ctx.tables[idx] tableName := ts.Source.(*ast.TableName) tn.DBInfo = tableName.DBInfo tn.TableInfo = tableName.TableInfo tn.SetResultFields(tableName.GetResultFields()) return } table, err := nr.Info.TableByName(tn.Schema, tn.Name) if err != nil { nr.Err = errors.Trace(err) return } tn.TableInfo = table.Meta() dbInfo, _ := nr.Info.SchemaByName(tn.Schema) tn.DBInfo = dbInfo rfs := make([]*ast.ResultField, len(tn.TableInfo.Columns)) for i, v := range tn.TableInfo.Columns { expr := &ast.ValueExpr{} expr.SetType(&v.FieldType) rfs[i] = &ast.ResultField{ Column: v, Table: tn.TableInfo, DBName: tn.Schema, Expr: expr, TableName: tn, } } tn.SetResultFields(rfs) return }
// handleTableName looks up and bind the schema information for table name // and set result fields for table name. func (sb *InfoBinder) handleTableName(tn *ast.TableName) { if tn.Schema.L == "" { tn.Schema = sb.DefaultSchema } table, err := sb.Info.TableByName(tn.Schema, tn.Name) if err != nil { sb.Err = err return } tn.TableInfo = table.Meta() dbInfo, _ := sb.Info.SchemaByName(tn.Schema) tn.DBInfo = dbInfo rfs := make([]*ast.ResultField, len(tn.TableInfo.Columns)) for i, v := range tn.TableInfo.Columns { rfs[i] = &ast.ResultField{ Column: v, Table: tn.TableInfo, DBName: tn.Schema, } } tn.SetResultFields(rfs) return }