Esempio n. 1
0
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
}
Esempio n. 2
0
// 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
}
Esempio n. 3
0
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())
}
Esempio n. 4
0
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
}
Esempio n. 5
0
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
}
Esempio n. 6
0
// 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
}
Esempio n. 7
0
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
}
Esempio n. 8
0
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
}
Esempio n. 9
0
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
}
Esempio n. 10
0
// 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
}
Esempio n. 11
0
// 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
}