vitess.io/vitess@v0.16.2/go/mysql/binlog_event.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mysql
    18  
    19  import (
    20  	"fmt"
    21  
    22  	binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
    23  )
    24  
    25  // BinlogEvent represents a single event from a raw MySQL binlog dump stream.
    26  // The implementation is provided by each supported flavor in go/vt/mysqlctl.
    27  //
    28  // binlog.Streamer receives these events through a mysqlctl.BinlogConnection and
    29  // processes them, grouping statements into BinlogTransactions as appropriate.
    30  //
    31  // Methods that only access header fields can't fail as long as IsValid()
    32  // returns true, so they have a single return value. Methods that might fail
    33  // even when IsValid() is true return an error value.
    34  //
    35  // Methods that require information from the initial FORMAT_DESCRIPTION_EVENT
    36  // will have a BinlogFormat parameter.
    37  //
    38  // A BinlogEvent should never be sent over the wire. UpdateStream service
    39  // will send BinlogTransactions from these events.
    40  type BinlogEvent interface {
    41  	// IsValid returns true if the underlying data buffer contains a valid
    42  	// event. This should be called first on any BinlogEvent, and other
    43  	// methods should only be called if this one returns true. This ensures
    44  	// you won't get panics due to bounds checking on the byte array.
    45  	IsValid() bool
    46  
    47  	// General protocol events.
    48  	NextPosition() uint32
    49  
    50  	// IsFormatDescription returns true if this is a
    51  	// FORMAT_DESCRIPTION_EVENT. Do not call StripChecksum before
    52  	// calling Format (Format returns the BinlogFormat anyway,
    53  	// required for calling StripChecksum).
    54  	IsFormatDescription() bool
    55  	// IsQuery returns true if this is a QUERY_EVENT, which encompasses
    56  	// all SQL statements.
    57  	IsQuery() bool
    58  	// IsXID returns true if this is an XID_EVENT, which is an alternate
    59  	// form of COMMIT.
    60  	IsXID() bool
    61  	// IsStop returns true if this is a STOP_EVENT.
    62  	IsStop() bool
    63  	// IsGTID returns true if this is a GTID_EVENT.
    64  	IsGTID() bool
    65  	// IsRotate returns true if this is a ROTATE_EVENT.
    66  	IsRotate() bool
    67  	// IsIntVar returns true if this is an INTVAR_EVENT.
    68  	IsIntVar() bool
    69  	// IsRand returns true if this is a RAND_EVENT.
    70  	IsRand() bool
    71  	// IsPreviousGTIDs returns true if this event is a PREVIOUS_GTIDS_EVENT.
    72  	IsPreviousGTIDs() bool
    73  	// IsHeartbeat returns true if this event is a HEARTBEAT_EVENT.
    74  	IsHeartbeat() bool
    75  	// IsSemiSyncAckRequested returns true if the source requests a semi-sync ack for this event
    76  	IsSemiSyncAckRequested() bool
    77  
    78  	// RBR events.
    79  
    80  	// IsTableMap returns true if this is a TABLE_MAP_EVENT.
    81  	IsTableMap() bool
    82  	// IsWriteRows returns true if this is a WRITE_ROWS_EVENT.
    83  	IsWriteRows() bool
    84  	// IsUpdateRows returns true if this is a UPDATE_ROWS_EVENT.
    85  	IsUpdateRows() bool
    86  	// IsDeleteRows returns true if this is a DELETE_ROWS_EVENT.
    87  	IsDeleteRows() bool
    88  
    89  	// Timestamp returns the timestamp from the event header.
    90  	Timestamp() uint32
    91  
    92  	// Format returns a BinlogFormat struct based on the event data.
    93  	// This is only valid if IsFormatDescription() returns true.
    94  	Format() (BinlogFormat, error)
    95  	// GTID returns the GTID from the event, and if this event
    96  	// also serves as a BEGIN statement.
    97  	// This is only valid if IsGTID() returns true.
    98  	GTID(BinlogFormat) (GTID, bool, error)
    99  	// Query returns a Query struct representing data from a QUERY_EVENT.
   100  	// This is only valid if IsQuery() returns true.
   101  	Query(BinlogFormat) (Query, error)
   102  	// IntVar returns the type and value of the variable for an INTVAR_EVENT.
   103  	// This is only valid if IsIntVar() returns true.
   104  	IntVar(BinlogFormat) (byte, uint64, error)
   105  	// Rand returns the two seed values for a RAND_EVENT.
   106  	// This is only valid if IsRand() returns true.
   107  	Rand(BinlogFormat) (uint64, uint64, error)
   108  	// PreviousGTIDs returns the Position from the event.
   109  	// This is only valid if IsPreviousGTIDs() returns true.
   110  	PreviousGTIDs(BinlogFormat) (Position, error)
   111  
   112  	// TableID returns the table ID for a TableMap, UpdateRows,
   113  	// WriteRows or DeleteRows event.
   114  	TableID(BinlogFormat) uint64
   115  	// TableMap returns a TableMap struct representing data from a
   116  	// TABLE_MAP_EVENT.  This is only valid if IsTableMapEvent() returns
   117  	// true.
   118  	TableMap(BinlogFormat) (*TableMap, error)
   119  	// Rows returns a Rows struct representing data from a
   120  	// {WRITE,UPDATE,DELETE}_ROWS_EVENT.  This is only valid if
   121  	// IsWriteRows(), IsUpdateRows(), or IsDeleteRows() returns
   122  	// true.
   123  	Rows(BinlogFormat, *TableMap) (Rows, error)
   124  	// NextLogFile returns the name of the next binary log file & pos.
   125  	// This is only valid if IsRotate() returns true
   126  	NextLogFile(BinlogFormat) (string, uint64, error)
   127  
   128  	// StripChecksum returns the checksum and a modified event with the
   129  	// checksum stripped off, if any. If there is no checksum, it returns
   130  	// the same event and a nil checksum.
   131  	StripChecksum(BinlogFormat) (ev BinlogEvent, checksum []byte, err error)
   132  
   133  	// IsPseudo is for custom implementations of GTID.
   134  	IsPseudo() bool
   135  
   136  	// IsCompressed returns true if a compressed event is found (binlog_transaction_compression=ON)
   137  	IsCompressed() bool
   138  
   139  	// Bytes returns the binary representation of the event
   140  	Bytes() []byte
   141  }
   142  
   143  // BinlogFormat contains relevant data from the FORMAT_DESCRIPTION_EVENT.
   144  // This structure is passed to subsequent event types to let them know how to
   145  // parse themselves.
   146  type BinlogFormat struct {
   147  	// HeaderSizes is an array of sizes of the headers for each message.
   148  	HeaderSizes []byte
   149  
   150  	// ServerVersion is the name of the MySQL server version.
   151  	// It starts with something like 5.6.33-xxxx.
   152  	ServerVersion string
   153  
   154  	// FormatVersion is the version number of the binlog file format.
   155  	// We only support version 4.
   156  	FormatVersion uint16
   157  
   158  	// HeaderLength is the size in bytes of event headers other
   159  	// than FORMAT_DESCRIPTION_EVENT. Almost always 19.
   160  	HeaderLength byte
   161  
   162  	// ChecksumAlgorithm is the ID number of the binlog checksum algorithm.
   163  	// See three possible values below.
   164  	ChecksumAlgorithm byte
   165  }
   166  
   167  // IsZero returns true if the BinlogFormat has not been initialized.
   168  func (f BinlogFormat) IsZero() bool {
   169  	return f.FormatVersion == 0 && f.HeaderLength == 0
   170  }
   171  
   172  // HeaderSize returns the header size of any event type.
   173  func (f BinlogFormat) HeaderSize(typ byte) byte {
   174  	return f.HeaderSizes[typ-1]
   175  }
   176  
   177  // Query contains data from a QUERY_EVENT.
   178  type Query struct {
   179  	Database string
   180  	Charset  *binlogdatapb.Charset
   181  	SQL      string
   182  }
   183  
   184  // String pretty-prints a Query.
   185  func (q Query) String() string {
   186  	return fmt.Sprintf("{Database: %q, Charset: %v, SQL: %q}",
   187  		q.Database, q.Charset, q.SQL)
   188  }
   189  
   190  // TableMap contains data from a TABLE_MAP_EVENT.
   191  type TableMap struct {
   192  	// Flags is the table's flags.
   193  	Flags uint16
   194  
   195  	// Database is the database name.
   196  	Database string
   197  
   198  	// Name is the name of the table.
   199  	Name string
   200  
   201  	// Types is an array of MySQL types for the fields.
   202  	Types []byte
   203  
   204  	// CanBeNull's bits are set if the column can be NULL.
   205  	CanBeNull Bitmap
   206  
   207  	// Metadata is an array of uint16, one per column.
   208  	// It contains a few extra information about each column,
   209  	// that is dependent on the type.
   210  	// - If the metadata is not present, this is zero.
   211  	// - If the metadata is one byte, only the lower 8 bits are used.
   212  	// - If the metadata is two bytes, all 16 bits are used.
   213  	Metadata []uint16
   214  }
   215  
   216  // Rows contains data from a {WRITE,UPDATE,DELETE}_ROWS_EVENT.
   217  type Rows struct {
   218  	// Flags has the flags from the event.
   219  	Flags uint16
   220  
   221  	// IdentifyColumns describes which columns are included to
   222  	// identify the row. It is a bitmap indexed by the TableMap
   223  	// list of columns.
   224  	// Set for UPDATE and DELETE.
   225  	IdentifyColumns Bitmap
   226  
   227  	// DataColumns describes which columns are included. It is
   228  	// a bitmap indexed by the TableMap list of columns.
   229  	// Set for WRITE and UPDATE.
   230  	DataColumns Bitmap
   231  
   232  	// Rows is an array of Row in the event.
   233  	Rows []Row
   234  }
   235  
   236  // Row contains data for a single Row in a Rows event.
   237  type Row struct {
   238  	// NullIdentifyColumns describes which of the identify columns are NULL.
   239  	// It is only set for UPDATE and DELETE events.
   240  	NullIdentifyColumns Bitmap
   241  
   242  	// NullColumns describes which of the present columns are NULL.
   243  	// It is only set for WRITE and UPDATE events.
   244  	NullColumns Bitmap
   245  
   246  	// Identify is the raw data for the columns used to identify a row.
   247  	// It is only set for UPDATE and DELETE events.
   248  	Identify []byte
   249  
   250  	// Data is the raw data.
   251  	// It is only set for WRITE and UPDATE events.
   252  	Data []byte
   253  }
   254  
   255  // Bitmap is used by the previous structures.
   256  type Bitmap struct {
   257  	// data is the slice this is based on.
   258  	data []byte
   259  
   260  	// count is how many bits we have in the map.
   261  	count int
   262  }
   263  
   264  func newBitmap(data []byte, pos int, count int) (Bitmap, int) {
   265  	byteSize := (count + 7) / 8
   266  	return Bitmap{
   267  		data:  data[pos : pos+byteSize],
   268  		count: count,
   269  	}, pos + byteSize
   270  }
   271  
   272  // NewServerBitmap returns a bitmap that can hold 'count' bits.
   273  func NewServerBitmap(count int) Bitmap {
   274  	byteSize := (count + 7) / 8
   275  	return Bitmap{
   276  		data:  make([]byte, byteSize),
   277  		count: count,
   278  	}
   279  }
   280  
   281  // Count returns the number of bits in this Bitmap.
   282  func (b *Bitmap) Count() int {
   283  	return b.count
   284  }
   285  
   286  // Bit returned the value of a given bit in the Bitmap.
   287  func (b *Bitmap) Bit(index int) bool {
   288  	byteIndex := index / 8
   289  	bitMask := byte(1 << (uint(index) & 0x7))
   290  	return b.data[byteIndex]&bitMask > 0
   291  }
   292  
   293  // Set sets the given boolean value.
   294  func (b *Bitmap) Set(index int, value bool) {
   295  	byteIndex := index / 8
   296  	bitMask := byte(1 << (uint(index) & 0x7))
   297  	if value {
   298  		b.data[byteIndex] |= bitMask
   299  	} else {
   300  		b.data[byteIndex] &= 0xff - bitMask
   301  	}
   302  }
   303  
   304  // BitCount returns how many bits are set in the bitmap.
   305  // Note values that are not used may be set to 0 or 1,
   306  // hence the non-efficient logic.
   307  func (b *Bitmap) BitCount() int {
   308  	sum := 0
   309  	for i := 0; i < b.count; i++ {
   310  		if b.Bit(i) {
   311  			sum++
   312  		}
   313  	}
   314  	return sum
   315  }