func (b *executorBuilder) buildIndexScan(v *plan.PhysicalIndexScan) Executor { startTS := b.getStartTS() if b.err != nil { return nil } table, _ := b.is.TableByID(v.Table.ID) client := b.ctx.GetClient() memDB := infoschema.IsMemoryDB(v.DBName.L) supportDesc := client.SupportRequestType(kv.ReqTypeIndex, kv.ReqSubTypeDesc) if !memDB && client.SupportRequestType(kv.ReqTypeIndex, 0) { st := &XSelectIndexExec{ tableInfo: v.Table, ctx: b.ctx, supportDesc: supportDesc, asName: v.TableAsName, table: table, indexPlan: v, singleReadMode: !v.DoubleRead, startTS: startTS, where: v.TableConditionPBExpr, aggregate: v.Aggregated, aggFuncs: v.AggFuncsPB, aggFields: v.AggFields, byItems: v.GbyItemsPB, } st.scanConcurrency, b.err = getScanConcurrency(b.ctx) return st } b.err = errors.New("not implement yet") return nil }
func (b *executorBuilder) buildTableScan(v *plan.PhysicalTableScan) Executor { startTS := b.getStartTS() if b.err != nil { return nil } table, _ := b.is.TableByID(v.Table.ID) client := b.ctx.GetClient() memDB := infoschema.IsMemoryDB(v.DBName.L) supportDesc := client.SupportRequestType(kv.ReqTypeSelect, kv.ReqSubTypeDesc) if !memDB && client.SupportRequestType(kv.ReqTypeSelect, 0) { st := &XSelectTableExec{ tableInfo: v.Table, ctx: b.ctx, startTS: startTS, supportDesc: supportDesc, asName: v.TableAsName, table: table, schema: v.GetSchema(), Columns: v.Columns, ranges: v.Ranges, desc: v.Desc, limitCount: v.LimitCount, keepOrder: v.KeepOrder, where: v.TableConditionPBExpr, aggregate: v.Aggregated, aggFuncs: v.AggFuncsPB, aggFields: v.AggFields, byItems: v.GbyItemsPB, orderByList: v.SortItemsPB, } st.scanConcurrency, b.err = getScanConcurrency(b.ctx) return st } ts := &TableScanExec{ t: table, asName: v.TableAsName, ctx: b.ctx, columns: v.Columns, schema: v.GetSchema(), seekHandle: math.MinInt64, ranges: v.Ranges, isInfoSchema: strings.EqualFold(v.DBName.L, infoschema.Name), } if v.Desc { return &ReverseExec{Src: ts} } return ts }
func (p *DataSource) convert2IndexScan(prop *requiredProperty, index *model.IndexInfo) (*physicalPlanInfo, error) { client := p.ctx.GetClient() is := &PhysicalIndexScan{ Index: index, Table: p.Table, Columns: p.Columns, TableAsName: p.TableAsName, OutOfOrder: true, DBName: p.DBName, physicalTableSource: physicalTableSource{client: client}, } is.tp = Idx is.allocator = p.allocator is.initIDAndContext(p.ctx) is.SetSchema(p.schema) txn, err := p.ctx.GetTxn(false) if err != nil { return nil, errors.Trace(err) } if txn != nil { is.readOnly = txn.IsReadOnly() } else { is.readOnly = true } var resultPlan PhysicalPlan resultPlan = is statsTbl := p.statisticTable rowCount := uint64(statsTbl.Count) sc := p.ctx.GetSessionVars().StmtCtx if sel, ok := p.GetParentByIndex(0).(*Selection); ok { newSel := *sel conds := make([]expression.Expression, 0, len(sel.Conditions)) for _, cond := range sel.Conditions { conds = append(conds, cond.Clone()) } is.AccessCondition, newSel.Conditions = detachIndexScanConditions(conds, is) memDB := infoschema.IsMemoryDB(p.DBName.L) isDistReq := !memDB && client != nil && client.SupportRequestType(kv.ReqTypeIndex, 0) if isDistReq { idxConds, tblConds := detachIndexFilterConditions(newSel.Conditions, is.Index.Columns, is.Table) is.IndexConditionPBExpr, is.indexFilterConditions, idxConds = expressionsToPB(sc, idxConds, client) is.TableConditionPBExpr, is.tableFilterConditions, tblConds = expressionsToPB(sc, tblConds, client) newSel.Conditions = append(idxConds, tblConds...) } err := buildIndexRange(p.ctx.GetSessionVars().StmtCtx, is) if err != nil { if !terror.ErrorEqual(err, types.ErrTruncated) { return nil, errors.Trace(err) } log.Warn("truncate error in buildIndexRange") } rowCount, err = getRowCountByIndexRanges(sc, statsTbl, is.Ranges, is.Index) if err != nil { return nil, errors.Trace(err) } if len(newSel.Conditions) > 0 { newSel.SetChildren(is) newSel.onTable = true resultPlan = &newSel } } else { rb := rangeBuilder{sc: p.ctx.GetSessionVars().StmtCtx} is.Ranges = rb.buildIndexRanges(fullRange, types.NewFieldType(mysql.TypeNull)) } is.DoubleRead = !isCoveringIndex(is.Columns, is.Index.Columns, is.Table.PKIsHandle) return resultPlan.matchProperty(prop, &physicalPlanInfo{count: rowCount}), nil }
func (p *DataSource) convert2TableScan(prop *requiredProperty) (*physicalPlanInfo, error) { client := p.ctx.GetClient() ts := &PhysicalTableScan{ Table: p.Table, Columns: p.Columns, TableAsName: p.TableAsName, DBName: p.DBName, physicalTableSource: physicalTableSource{client: client}, } ts.tp = Tbl ts.allocator = p.allocator ts.SetSchema(p.GetSchema()) ts.initIDAndContext(p.ctx) txn, err := p.ctx.GetTxn(false) if err != nil { return nil, errors.Trace(err) } if txn != nil { ts.readOnly = txn.IsReadOnly() } else { ts.readOnly = true } var resultPlan PhysicalPlan resultPlan = ts table := p.Table sc := p.ctx.GetSessionVars().StmtCtx if sel, ok := p.GetParentByIndex(0).(*Selection); ok { newSel := *sel conds := make([]expression.Expression, 0, len(sel.Conditions)) for _, cond := range sel.Conditions { conds = append(conds, cond.Clone()) } ts.AccessCondition, newSel.Conditions = detachTableScanConditions(conds, table) memDB := infoschema.IsMemoryDB(p.DBName.L) isDistReq := !memDB && client != nil && client.SupportRequestType(kv.ReqTypeSelect, 0) if isDistReq { ts.TableConditionPBExpr, ts.tableFilterConditions, newSel.Conditions = expressionsToPB(sc, newSel.Conditions, client) } err := buildTableRange(ts) if err != nil { return nil, errors.Trace(err) } if len(newSel.Conditions) > 0 { newSel.SetChildren(ts) newSel.onTable = true resultPlan = &newSel } } else { ts.Ranges = []TableRange{{math.MinInt64, math.MaxInt64}} } statsTbl := p.statisticTable rowCount := uint64(statsTbl.Count) if table.PKIsHandle { for i, colInfo := range ts.Columns { if mysql.HasPriKeyFlag(colInfo.Flag) { ts.pkCol = p.GetSchema()[i] break } } var offset int for _, colInfo := range table.Columns { if mysql.HasPriKeyFlag(colInfo.Flag) { offset = colInfo.Offset break } } rowCount, err = getRowCountByTableRange(sc, statsTbl, ts.Ranges, offset) if err != nil { return nil, errors.Trace(err) } } if ts.TableConditionPBExpr != nil { rowCount = uint64(float64(rowCount) * selectionFactor) } return resultPlan.matchProperty(prop, &physicalPlanInfo{count: rowCount}), nil }