func (krval bvcKeyRange) eval(bv interface{}, op Operator, onMismatch bool) bool { switch op { case QR_IN: switch num, status := getuint64(bv); status { case QR_OK: k := key.Uint64Key(num).KeyspaceId() return key.KeyRange(krval).Contains(k) case QR_OUT_OF_RANGE: return false } // Not a number. Check string. switch str, status := getstring(bv); status { case QR_OK: return key.KeyRange(krval).Contains(key.KeyspaceId(str)) } case QR_NOTIN: switch num, status := getuint64(bv); status { case QR_OK: k := key.Uint64Key(num).KeyspaceId() return !key.KeyRange(krval).Contains(k) case QR_OUT_OF_RANGE: return true } // Not a number. Check string. switch str, status := getstring(bv); status { case QR_OK: return !key.KeyRange(krval).Contains(key.KeyspaceId(str)) } default: panic("unexpected:") } return onMismatch }
func numKeyRange(start, end uint64) bvcKeyRange { kr := key.KeyRange{ Start: key.Uint64Key(start).KeyspaceId(), End: key.Uint64Key(end).KeyspaceId(), } return bvcKeyRange(kr) }
// Split will split the rows into subset for each distribution func (rs *RowSplitter) Split(result [][][]sqltypes.Value, rows [][]sqltypes.Value) error { if rs.Type == key.KIT_UINT64 { for _, row := range rows { v := sqltypes.MakeNumeric(row[rs.ValueIndex].Raw()) i, err := v.ParseUint64() if err != nil { return fmt.Errorf("Non numerical value: %v", err) } k := key.Uint64Key(i).KeyspaceId() for i, kr := range rs.KeyRanges { if kr.Contains(k) { result[i] = append(result[i], row) break } } } } else { for _, row := range rows { k := key.KeyspaceId(row[rs.ValueIndex].Raw()) for i, kr := range rs.KeyRanges { if kr.Contains(k) { result[i] = append(result[i], row) break } } } } return nil }
// Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package binlog import ( "fmt" "testing" "github.com/henryanand/vitess/go/vt/binlog/proto" "github.com/henryanand/vitess/go/vt/key" myproto "github.com/henryanand/vitess/go/vt/mysqlctl/proto" ) var testKeyRange = key.KeyRange{ Start: key.KeyspaceId(key.Uint64Key(0).String()), End: key.KeyspaceId(key.Uint64Key(10).String()), } func TestKeyRangeFilterPass(t *testing.T) { input := proto.BinlogTransaction{ Statements: []proto.Statement{ { Category: proto.BL_SET, Sql: []byte("set1"), }, { Category: proto.BL_DML, Sql: []byte("dml1 /* EMD keyspace_id:20 */"), }, { Category: proto.BL_DML, Sql: []byte("dml2 /* EMD keyspace_id:2 */"),
// KeyRangeFilterFunc returns a function that calls sendReply only if statements // in the transaction match the specified keyrange. The resulting function can be // passed into the BinlogStreamer: bls.Stream(file, pos, sendTransaction) -> // bls.Stream(file, pos, KeyRangeFilterFunc(sendTransaction)) func KeyRangeFilterFunc(kit key.KeyspaceIdType, keyrange key.KeyRange, sendReply sendTransactionFunc) sendTransactionFunc { isInteger := true if kit == key.KIT_BYTES { isInteger = false } return func(reply *proto.BinlogTransaction) error { matched := false filtered := make([]proto.Statement, 0, len(reply.Statements)) for _, statement := range reply.Statements { switch statement.Category { case proto.BL_SET: filtered = append(filtered, statement) case proto.BL_DDL: log.Warningf("Not forwarding DDL: %s", string(statement.Sql)) continue case proto.BL_DML: keyspaceIndex := bytes.LastIndex(statement.Sql, KEYSPACE_ID_COMMENT) if keyspaceIndex == -1 { updateStreamErrors.Add("KeyRangeStream", 1) log.Errorf("Error parsing keyspace id: %s", string(statement.Sql)) continue } idstart := keyspaceIndex + len(KEYSPACE_ID_COMMENT) idend := bytes.Index(statement.Sql[idstart:], SPACE) if idend == -1 { updateStreamErrors.Add("KeyRangeStream", 1) log.Errorf("Error parsing keyspace id: %s", string(statement.Sql)) continue } textId := string(statement.Sql[idstart : idstart+idend]) if isInteger { id, err := strconv.ParseUint(textId, 10, 64) if err != nil { updateStreamErrors.Add("KeyRangeStream", 1) log.Errorf("Error parsing keyspace id: %s", string(statement.Sql)) continue } if !keyrange.Contains(key.Uint64Key(id).KeyspaceId()) { continue } } else { data, err := base64.StdEncoding.DecodeString(textId) if err != nil { updateStreamErrors.Add("KeyRangeStream", 1) log.Errorf("Error parsing keyspace id: %s", string(statement.Sql)) continue } if !keyrange.Contains(key.KeyspaceId(data)) { continue } } filtered = append(filtered, statement) matched = true case proto.BL_UNRECOGNIZED: updateStreamErrors.Add("KeyRangeStream", 1) log.Errorf("Error parsing keyspace id: %s", string(statement.Sql)) continue } } if matched { reply.Statements = filtered } else { reply.Statements = nil } return sendReply(reply) } }