func (h *rpcHandler) getRowsFromSelectReq(ctx *selectContext) ([]*tipb.Row, error) { // Init ctx.colTps and use it to decode all the rows. columns := ctx.sel.TableInfo.Columns ctx.colTps = make(map[int64]*types.FieldType, len(columns)) for _, col := range columns { if col.GetPkHandle() { continue } ctx.colTps[col.GetColumnId()] = xapi.FieldTypeFromPBColumn(col) } kvRanges, desc := h.extractKVRanges(ctx) var rows []*tipb.Row limit := int64(-1) if ctx.sel.Limit != nil { limit = ctx.sel.GetLimit() } for _, ran := range kvRanges { if limit == 0 { break } ranRows, err := h.getRowsFromRange(ctx, ran, limit, desc) if err != nil { return nil, errors.Trace(err) } rows = append(rows, ranRows...) limit -= int64(len(ranRows)) } if ctx.aggregate { return h.getRowsFromAgg(ctx) } return rows, nil }
func (rs *localRegion) evalWhereForRow(ctx *selectContext, h int64, row map[int64][]byte) (bool, error) { if ctx.sel.Where == nil { return true, nil } for colID, col := range ctx.whereColumns { if col.GetPkHandle() { ctx.eval.Row[colID] = types.NewIntDatum(h) } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return false, errors.Trace(err) } ctx.eval.Row[colID] = datum } } result, err := ctx.eval.Eval(ctx.sel.Where) if err != nil { return false, errors.Trace(err) } if result.IsNull() { return false, nil } boolResult, err := result.ToBool() if err != nil { return false, errors.Trace(err) } return boolResult == 1, nil }
func (rs *localRegion) getRowsFromSelectReq(ctx *selectContext) error { // Init ctx.colTps and use it to decode all the rows. columns := ctx.sel.TableInfo.Columns ctx.colTps = make(map[int64]*types.FieldType, len(columns)) for _, col := range columns { if col.GetPkHandle() { continue } ctx.colTps[col.GetColumnId()] = xapi.FieldTypeFromPBColumn(col) } kvRanges, desc := rs.extractKVRanges(ctx) limit := int64(-1) if ctx.sel.Limit != nil { limit = ctx.sel.GetLimit() } for _, ran := range kvRanges { if limit == 0 { break } count, err := rs.getRowsFromRange(ctx, ran, limit, desc) if err != nil { return errors.Trace(err) } limit -= count } if ctx.aggregate { return rs.getRowsFromAgg(ctx) } return nil }
// Put column values into ctx, the values will be used for expr evaluation. func (rs *localRegion) setColumnValueToCtx(ctx *selectContext, h int64, row map[int64][]byte, cols map[int64]*tipb.ColumnInfo) error { for colID, col := range cols { if col.GetPkHandle() { ctx.eval.Row[colID] = types.NewIntDatum(h) } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return errors.Trace(err) } ctx.eval.Row[colID] = datum } } return nil }
// Put column values into ctx, the values will be used for expr evaluation. func (h *rpcHandler) setColumnValueToCtx(ctx *selectContext, handle int64, row map[int64][]byte, cols map[int64]*tipb.ColumnInfo) error { for colID, col := range cols { if col.GetPkHandle() { if mysql.HasUnsignedFlag(uint(col.GetFlag())) { ctx.eval.Row[colID] = types.NewUintDatum(uint64(handle)) } else { ctx.eval.Row[colID] = types.NewIntDatum(handle) } } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return errors.Trace(err) } ctx.eval.Row[colID] = datum } } return nil }
func (h *rpcHandler) getRowByHandle(ctx *selectContext, handle int64) (*tipb.Row, error) { tid := ctx.sel.TableInfo.GetTableId() columns := ctx.sel.TableInfo.Columns row := new(tipb.Row) var d types.Datum d.SetInt64(handle) var err error row.Handle, err = codec.EncodeValue(nil, d) if err != nil { return nil, errors.Trace(err) } rowData := make([][]byte, len(columns)) colTps := make(map[int64]*types.FieldType, len(columns)) for i, col := range columns { var colVal []byte if col.GetPkHandle() { if mysql.HasUnsignedFlag(uint(*col.Flag)) { // PK column is Unsigned var ud types.Datum ud.SetUint64(uint64(handle)) var err1 error colVal, err1 = codec.EncodeValue(nil, ud) if err1 != nil { return nil, errors.Trace(err1) } } else { colVal = row.Handle } rowData[i] = colVal } else { colTps[col.GetColumnId()] = xapi.FieldTypeFromPBColumn(col) } } key := tablecodec.EncodeRowKeyWithHandle(tid, handle) value, err := h.mvccStore.Get(key, ctx.sel.GetStartTs()) if err != nil { return nil, errors.Trace(err) } values, err := h.getRowData(value, colTps) if err != nil { return nil, errors.Trace(err) } for i, col := range columns { if col.GetPkHandle() { continue } v, ok := values[col.GetColumnId()] if !ok { if mysql.HasNotNullFlag(uint(col.GetFlag())) { return nil, errors.New("Miss column") } v = []byte{codec.NilFlag} values[col.GetColumnId()] = v } rowData[i] = v } // Evalue where match, err := h.evalWhereForRow(ctx, handle, values) if err != nil { return nil, errors.Trace(err) } if !match { return nil, nil } for _, d := range rowData { row.Data = append(row.Data, d...) } return row, nil }