Пример #1
0
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 */"),
			},
		},
		GTIDField: myproto.GTIDField{Value: myproto.MustParseGTID("MariaDB", "0-41983-1")},
	}
	var got string
	f := KeyRangeFilterFunc(key.KIT_UINT64, testKeyRange, func(reply *proto.BinlogTransaction) error {
		got = bltToString(reply)
		return nil
	})
	f(&input)
	want := `statement: <6, "set1"> statement: <4, "dml2 /* EMD keyspace_id:2 */"> position: "0-41983-1" `
	if want != got {
		t.Errorf("want %s, got %s", want, got)
	}
}
Пример #2
0
func TestKeyRangeFilterMalformed(t *testing.T) {
	input := proto.BinlogTransaction{
		Statements: []proto.Statement{
			{
				Category: proto.BL_SET,
				Sql:      []byte("set1"),
			}, {
				Category: proto.BL_DML,
				Sql:      []byte("ddl"),
			}, {
				Category: proto.BL_DML,
				Sql:      []byte("dml1 /* EMD keyspace_id:20*/"),
			}, {
				Category: proto.BL_DML,
				Sql:      []byte("dml1 /* EMD keyspace_id:2a */"),
			},
		},
		GTIDField: myproto.GTIDField{Value: myproto.MustParseGTID(blsMysqlFlavor, "41983-1")},
	}
	var got string
	f := KeyRangeFilterFunc(key.KIT_UINT64, testKeyRange, func(reply *proto.BinlogTransaction) error {
		got = bltToString(reply)
		return nil
	})
	f(&input)
	want := `position: "41983-1" `
	if want != got {
		t.Errorf("want %s, got %s", want, got)
	}
}
Пример #3
0
func TestUpdateBlpCheckpointTimestamp(t *testing.T) {
	gtid := myproto.MustParseGTID("MariaDB", "0-2-582")
	want := "UPDATE _vt.blp_checkpoint " +
		"SET pos='MariaDB/0-2-582', time_updated=88822, transaction_timestamp=481828 " +
		"WHERE source_shard_uid=78522"

	got := UpdateBlpCheckpoint(78522, myproto.ReplicationPosition{GTIDSet: gtid.GTIDSet()}, 88822, 481828)
	if got != want {
		t.Errorf("UpdateBlpCheckpoint() = %#v, want %#v", got, want)
	}
}
Пример #4
0
func TestPopulateBlpCheckpoint(t *testing.T) {
	gtid := myproto.MustParseGTID("MariaDB", "0-1-1083")
	want := "INSERT INTO _vt.blp_checkpoint " +
		"(source_shard_uid, pos, time_updated, transaction_timestamp, flags) " +
		"VALUES (18372, 'MariaDB/0-1-1083', 481823, 0, 'myflags')"

	got := PopulateBlpCheckpoint(18372, myproto.ReplicationPosition{GTIDSet: gtid.GTIDSet()}, 481823, "myflags")
	if got != want {
		t.Errorf("PopulateBlpCheckpoint() = %#v, want %#v", got, want)
	}
}
Пример #5
0
func TestUpdateBlpCheckpoint(t *testing.T) {
	gtid := myproto.MustParseGTID("GoogleMysql", "41983-58283")
	want := "UPDATE _vt.blp_checkpoint " +
		"SET pos='GoogleMysql/41983-58283', time_updated=88822 " +
		"WHERE source_shard_uid=78522"

	got := UpdateBlpCheckpoint(78522, myproto.ReplicationPosition{GTIDSet: gtid.GTIDSet()}, 88822, 0)
	if got != want {
		t.Errorf("UpdateBlpCheckpoint() = %#v, want %#v", got, want)
	}
}
Пример #6
0
func TestUpdateBlpCheckpointTimestamp(t *testing.T) {
	gtid := myproto.MustParseGTID("GoogleMysql", "58283")
	want := "UPDATE _vt.blp_checkpoint " +
		"SET gtid='GoogleMysql/58283', time_updated=88822, transaction_timestamp=481828 " +
		"WHERE source_shard_uid=78522"

	got := UpdateBlpCheckpoint(78522, gtid, 88822, 481828)
	if got != want {
		t.Errorf("UpdateBlpCheckpoint() = %#v, want %#v", got, want)
	}
}
Пример #7
0
func TestPopulateBlpCheckpoint(t *testing.T) {
	gtid := myproto.MustParseGTID("GoogleMysql", "19283")
	want := "INSERT INTO _vt.blp_checkpoint " +
		"(source_shard_uid, gtid, time_updated, transaction_timestamp, flags) " +
		"VALUES (18372, 'GoogleMysql/19283', 481823, 0, 'myflags')"

	got := PopulateBlpCheckpoint(18372, gtid, 481823, "myflags")
	if got != want {
		t.Errorf("PopulateBlpCheckpoint() = %#v, want %#v", got, want)
	}
}
Пример #8
0
func TestDMLEvent(t *testing.T) {
	trans := &proto.BinlogTransaction{
		Statements: []proto.Statement{
			{
				Category: proto.BL_SET,
				Sql:      []byte("SET TIMESTAMP=2"),
			}, {
				Category: proto.BL_SET,
				Sql:      []byte("SET INSERT_ID=10"),
			}, {
				Category: proto.BL_DML,
				Sql:      []byte("query /* _stream vtocc_e (eid id name)  (null -1 'bmFtZQ==' ) (null 18446744073709551615 'bmFtZQ==' ); */"),
			}, {
				Category: proto.BL_DML,
				Sql:      []byte("query"),
			},
		},
		Timestamp: 1,
		GTIDField: myproto.GTIDField{Value: myproto.MustParseGTID("MariaDB", "0-41983-20")},
	}
	evs := &EventStreamer{
		sendEvent: func(event *proto.StreamEvent) error {
			switch event.Category {
			case "DML":
				want := `&{DML vtocc_e [eid id name] [[10 -1 [110 97 109 101]] [11 18446744073709551615 [110 97 109 101]]]  1 <nil>}`
				got := fmt.Sprintf("%v", event)
				if got != want {
					t.Errorf("got \n%s, want \n%s", got, want)
				}
			case "ERR":
				want := `&{ERR  [] [] query 1 <nil>}`
				got := fmt.Sprintf("%v", event)
				if got != want {
					t.Errorf("got %s, want %s", got, want)
				}
			case "POS":
				want := `&{POS  [] []  1 0-41983-20}`
				got := fmt.Sprintf("%v", event)
				if got != want {
					t.Errorf("got %s, want %s", got, want)
				}
			default:
				t.Errorf("unexppected: %#v", event)
			}
			return nil
		},
	}
	err := evs.transactionToEvent(trans)
	if err != nil {
		t.Error(err)
	}
}
Пример #9
0
// nextStatement returns the next statement encountered in the binlog stream. If there are
// positional comments, it updates the binlogFileStreamer state. It also ignores events that
// are not material. If it returns nil, it's the end of stream. If err is also nil, then
// it was due to a normal termination.
func (bls *binlogFileStreamer) nextStatement(ctx *sync2.ServiceContext, bufReader *bufio.Reader) (stmt []byte, err error) {
eventLoop:
	for {
		// Stop processing if we're shutting down
		if !ctx.IsRunning() {
			return nil, io.EOF
		}
		event, err := bls.readEvent(bufReader)
		if err != nil {
			if err == io.EOF {
				return nil, nil
			}
			return nil, err
		}
		values := posRE.FindSubmatch(event)
		if values != nil {
			bls.blPos.ServerId = mustParseInt64(values[1])
			bls.file.Set(mustParseInt64(values[2]))

			// Make the fake Google GTID format we invented.
			gtid := string(values[1]) + "-" + string(values[3])
			bls.blPos.GTID = myproto.MustParseGTID(blsMysqlFlavor, gtid)
			continue
		}
		values = rotateRE.FindSubmatch(event)
		if values != nil {
			err = bls.file.Rotate(path.Join(bls.dir, string(values[1])), mustParseInt64(values[2]))
			if err != nil {
				return nil, err
			}
			return nil, nil
		}
		if bytes.HasPrefix(event, eolfPrefix) {
			return nil, nil
		}
		values = delimRE.FindSubmatch(event)
		if values != nil {
			bls.delim = values[1]
			continue
		}
		for _, ignorePrefix := range ignorePrefixes {
			if bytes.HasPrefix(event, ignorePrefix) {
				continue eventLoop
			}
		}
		return event, nil
	}
}
Пример #10
0
// nextStatement returns the next statement encountered in the binlog stream. If there are
// positional comments, it updates the binlogFileStreamer state. It also ignores events that
// are not material. If it returns nil, it's the end of stream. If err is also nil, then
// it was due to a normal termination.
func (bls *binlogFileStreamer) nextStatement(bufReader *bufio.Reader) (stmt []byte, err error) {
eventLoop:
	for {
		// Stop processing if we're shutting down
		if bls.svm.State() != sync2.SERVICE_RUNNING {
			return nil, io.EOF
		}
		event, err := bls.readEvent(bufReader)
		if err != nil {
			if err == io.EOF {
				return nil, nil
			}
			return nil, err
		}
		values := posRE.FindSubmatch(event)
		if values != nil {
			bls.blPos.ServerId = mustParseInt64(values[1])
			bls.file.Set(mustParseInt64(values[2]))
			bls.blPos.GTID = myproto.MustParseGTID(blsMysqlFlavor, string(values[3]))
			continue
		}
		values = rotateRE.FindSubmatch(event)
		if values != nil {
			err = bls.file.Rotate(path.Join(bls.dir, string(values[1])), mustParseInt64(values[2]))
			if err != nil {
				return nil, err
			}
			return nil, nil
		}
		if bytes.HasPrefix(event, eolfPrefix) {
			return nil, nil
		}
		values = delimRE.FindSubmatch(event)
		if values != nil {
			bls.delim = values[1]
			continue
		}
		for _, ignorePrefix := range ignorePrefixes {
			if bytes.HasPrefix(event, ignorePrefix) {
				continue eventLoop
			}
		}
		return event, nil
	}
}
Пример #11
0
func TestDDLEvent(t *testing.T) {
	trans := &proto.BinlogTransaction{
		Statements: []proto.Statement{
			{
				Category: proto.BL_SET,
				Sql:      []byte("SET TIMESTAMP=2"),
			}, {
				Category: proto.BL_DDL,
				Sql:      []byte("DDL"),
			},
		},
		Timestamp: 1,
		GTIDField: myproto.GTIDField{Value: myproto.MustParseGTID("MariaDB", "0-41983-20")},
	}
	evs := &EventStreamer{
		sendEvent: func(event *proto.StreamEvent) error {
			switch event.Category {
			case "DDL":
				want := `&{DDL  [] [] DDL 1 <nil>}`
				got := fmt.Sprintf("%v", event)
				if got != want {
					t.Errorf("got %s, want %s", got, want)
				}
			case "POS":
				want := `&{POS  [] []  1 0-41983-20}`
				got := fmt.Sprintf("%v", event)
				if got != want {
					t.Errorf("got %s, want %s", got, want)
				}
			default:
				t.Errorf("unexppected: %#v", event)
			}
			return nil
		},
	}
	err := evs.transactionToEvent(trans)
	if err != nil {
		t.Error(err)
	}
}