Exemple #1
0
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
}
Exemple #2
0
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
}