Search in sources :

Example 1 with QueryEvent

use of com.airbnb.spinaltap.mysql.event.QueryEvent in project SpinalTap by airbnb.

the class MysqlSource method toBinlogEvent.

public static BinlogEvent toBinlogEvent(Event event, BinlogFilePos filePos) {
    EventHeaderV4 header = event.getHeader();
    EventType eventType = header.getEventType();
    long serverId = header.getServerId();
    long timestamp = header.getTimestamp();
    if (EventType.isWrite(eventType)) {
        WriteRowsEventData data = event.getData();
        return new WriteEvent(data.getTableId(), serverId, timestamp, filePos, data.getRows());
    } else if (EventType.isUpdate(eventType)) {
        UpdateRowsEventData data = event.getData();
        return new UpdateEvent(data.getTableId(), serverId, timestamp, filePos, data.getRows());
    } else if (EventType.isDelete(eventType)) {
        DeleteRowsEventData data = event.getData();
        return new DeleteEvent(data.getTableId(), serverId, timestamp, filePos, data.getRows());
    } else {
        switch(eventType) {
            case TABLE_MAP:
                TableMapEventData tableMapData = event.getData();
                return new TableMapEvent(tableMapData.getTableId(), serverId, timestamp, filePos, tableMapData.getDatabase(), tableMapData.getTable(), tableMapData.getColumnTypes());
            case XID:
                XidEventData xidData = event.getData();
                return new XidEvent(serverId, timestamp, filePos, xidData.getXid());
            case QUERY:
                QueryEventData queryData = event.getData();
                return new QueryEvent(serverId, timestamp, filePos, queryData.getDatabase(), queryData.getSql());
            case FORMAT_DESCRIPTION:
                return new StartEvent(serverId, timestamp, filePos);
            default:
                return null;
        }
    }
}
Also used : WriteEvent(com.airbnb.spinaltap.mysql.event.WriteEvent) QueryEventData(com.github.shyiko.mysql.binlog.event.QueryEventData) TableMapEvent(com.airbnb.spinaltap.mysql.event.TableMapEvent) WriteRowsEventData(com.github.shyiko.mysql.binlog.event.WriteRowsEventData) EventType(com.github.shyiko.mysql.binlog.event.EventType) UpdateRowsEventData(com.github.shyiko.mysql.binlog.event.UpdateRowsEventData) DeleteRowsEventData(com.github.shyiko.mysql.binlog.event.DeleteRowsEventData) XidEventData(com.github.shyiko.mysql.binlog.event.XidEventData) QueryEvent(com.airbnb.spinaltap.mysql.event.QueryEvent) DeleteEvent(com.airbnb.spinaltap.mysql.event.DeleteEvent) TableMapEventData(com.github.shyiko.mysql.binlog.event.TableMapEventData) StartEvent(com.airbnb.spinaltap.mysql.event.StartEvent) EventHeaderV4(com.github.shyiko.mysql.binlog.event.EventHeaderV4) XidEvent(com.airbnb.spinaltap.mysql.event.XidEvent) UpdateEvent(com.airbnb.spinaltap.mysql.event.UpdateEvent)

Example 2 with QueryEvent

use of com.airbnb.spinaltap.mysql.event.QueryEvent in project SpinalTap by airbnb.

the class MysqlSchemaTrackerTest method testCreateDatabase.

@Test
public void testCreateDatabase() throws Exception {
    Table<String, String, TreeMap<Integer, MysqlTableSchema>> allTableSchemaInStore = Tables.newCustomTable(Maps.newHashMap(), Maps::newHashMap);
    allTableSchemaInStore.put(DATABASE_NAME, "table1", new TreeMap<Integer, MysqlTableSchema>() {

        {
            put(1, TABLE1_SCHEMA);
        }
    });
    allTableSchemaInStore.put(DATABASE_NAME, "table2", new TreeMap<Integer, MysqlTableSchema>() {

        {
            put(1, TABLE2_SCHEMA);
        }
    });
    when(schemaDatabase.listDatabases()).thenReturn(Sets.newHashSet(DATABASE_NAME, DATABASE2_NAME));
    when(schemaStore.getAll()).thenReturn(allTableSchemaInStore);
    when(schemaDatabase.fetchTableSchema(DATABASE_NAME)).thenReturn(ImmutableMap.of("table1", TABLE1_SCHEMA, "table2", TABLE2_SCHEMA));
    when(schemaDatabase.fetchTableSchema(DATABASE2_NAME)).thenReturn(ImmutableMap.of("table1", DATABASE2_TABLE1_SCHEMA));
    QueryEvent queryEvent = new QueryEvent(0, 0, binlogFilePos, DATABASE2_NAME, "CREATE DATABASE `database2`");
    SchemaTracker schemaTracker = new MysqlSchemaTracker(schemaStore, schemaDatabase);
    schemaTracker.processDDLStatement(queryEvent);
    verify(schemaDatabase).applyDDLStatement("", queryEvent.getSql());
    verify(schemaStore).put(DATABASE2_NAME, "table1", queryEvent.getBinlogFilePos(), queryEvent.getTimestamp(), queryEvent.getSql(), DATABASE2_TABLE1_SCHEMA.getColumnInfo());
}
Also used : Maps(com.google.common.collect.Maps) TreeMap(java.util.TreeMap) QueryEvent(com.airbnb.spinaltap.mysql.event.QueryEvent) Test(org.junit.Test)

Example 3 with QueryEvent

use of com.airbnb.spinaltap.mysql.event.QueryEvent in project SpinalTap by airbnb.

the class MysqlSchemaTracker method processDDLStatement.

public void processDDLStatement(@NotNull final QueryEvent event) {
    BinlogFilePos binlogFilePos = event.getBinlogFilePos();
    String ddl = event.getSql();
    if (schemaStore.get(binlogFilePos) != null) {
        log.info(String.format("DDL Statement (%s) has already been processed. (BinlogFilePos: %s)", ddl, binlogFilePos));
        return;
    }
    // It could be a new database which has not been created in schema store database, so don't
    // switch to any database before applying database DDL.
    schemaDatabase.applyDDLStatement(DATABASE_DDL_SQL_PATTERN.matcher(ddl).find() ? "" : event.getDatabase(), ddl);
    // Get schemas for active tables in schema store
    Table<String, String, MysqlTableSchema> activeTableSchemasInStore = Tables.newCustomTable(Maps.newHashMap(), Maps::newHashMap);
    schemaStore.getAll().values().stream().map(treeMap -> treeMap.lastEntry().getValue()).filter(schema -> !schema.getColumnInfo().isEmpty()).forEach(schema -> activeTableSchemasInStore.put(schema.getDatabase(), schema.getTable(), schema));
    Set<String> activeDatabasesInStore = activeTableSchemasInStore.rowKeySet();
    Set<String> databasesInSchemaDatabase = schemaDatabase.listDatabases();
    // Handle new databases
    Sets.difference(databasesInSchemaDatabase, activeDatabasesInStore).forEach(newDatabase -> updateSchemaStore(newDatabase, event, Maps.newHashMap(), schemaDatabase.fetchTableSchema(newDatabase)));
    // Handle existing databases
    activeDatabasesInStore.forEach(database -> updateSchemaStore(database, event, activeTableSchemasInStore.row(database), schemaDatabase.fetchTableSchema(database)));
}
Also used : QueryEvent(com.airbnb.spinaltap.mysql.event.QueryEvent) BinlogFilePos(com.airbnb.spinaltap.mysql.BinlogFilePos) RequiredArgsConstructor(lombok.RequiredArgsConstructor) Set(java.util.Set) NotNull(javax.validation.constraints.NotNull) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) Tables(com.google.common.collect.Tables) Slf4j(lombok.extern.slf4j.Slf4j) Lists(com.google.common.collect.Lists) Map(java.util.Map) Pattern(java.util.regex.Pattern) Table(com.google.common.collect.Table) Maps(com.google.common.collect.Maps) BinlogFilePos(com.airbnb.spinaltap.mysql.BinlogFilePos)

Example 4 with QueryEvent

use of com.airbnb.spinaltap.mysql.event.QueryEvent in project SpinalTap by airbnb.

the class MysqlEventFilterTest method testEventFilter.

@Test
public void testEventFilter() throws Exception {
    TableCache tableCache = mock(TableCache.class);
    BinlogEvent lastEvent = new XidEvent(0l, 0l, BINLOG_FILE_POS, 0l);
    BinlogFilePos nextPosition = new BinlogFilePos("test.123", 15, 100);
    SourceState state = new SourceState(0l, lastEvent.getOffset(), 0l, BINLOG_FILE_POS);
    Filter<BinlogEvent> filter = MysqlEventFilter.create(tableCache, TABLE_NAMES, new AtomicReference(state));
    when(tableCache.contains(TABLE_ID)).thenReturn(true);
    assertTrue(filter.apply(new TableMapEvent(TABLE_ID, 0l, 0l, nextPosition, DATABASE_NAME, TABLE_NAME, new byte[1])));
    assertTrue(filter.apply(new WriteEvent(TABLE_ID, 0l, 0l, nextPosition, Collections.emptyList())));
    assertTrue(filter.apply(new DeleteEvent(TABLE_ID, 0l, 0l, nextPosition, Collections.emptyList())));
    assertTrue(filter.apply(new UpdateEvent(TABLE_ID, 0l, 0l, nextPosition, Collections.emptyList())));
    assertTrue(filter.apply(new XidEvent(0l, 0l, BINLOG_FILE_POS, 12l)));
    assertTrue(filter.apply(new QueryEvent(0l, 0l, BINLOG_FILE_POS, DATABASE_NAME, "")));
    assertTrue(filter.apply(new StartEvent(0l, 0l, BINLOG_FILE_POS)));
    assertFalse(filter.apply(new TableMapEvent(TABLE_ID, 0l, 0l, BINLOG_FILE_POS, "", "", new byte[1])));
    assertFalse(filter.apply(new WriteEvent(0l, 0l, 0l, BINLOG_FILE_POS, Collections.emptyList())));
    assertFalse(filter.apply(new WriteEvent(TABLE_ID, 0l, 0l, BINLOG_FILE_POS, Collections.emptyList())));
    assertFalse(filter.apply(mock(BinlogEvent.class)));
}
Also used : WriteEvent(com.airbnb.spinaltap.mysql.event.WriteEvent) SourceState(com.airbnb.spinaltap.common.source.SourceState) TableMapEvent(com.airbnb.spinaltap.mysql.event.TableMapEvent) TableCache(com.airbnb.spinaltap.mysql.TableCache) AtomicReference(java.util.concurrent.atomic.AtomicReference) BinlogEvent(com.airbnb.spinaltap.mysql.event.BinlogEvent) QueryEvent(com.airbnb.spinaltap.mysql.event.QueryEvent) DeleteEvent(com.airbnb.spinaltap.mysql.event.DeleteEvent) BinlogFilePos(com.airbnb.spinaltap.mysql.BinlogFilePos) StartEvent(com.airbnb.spinaltap.mysql.event.StartEvent) XidEvent(com.airbnb.spinaltap.mysql.event.XidEvent) UpdateEvent(com.airbnb.spinaltap.mysql.event.UpdateEvent) Test(org.junit.Test)

Example 5 with QueryEvent

use of com.airbnb.spinaltap.mysql.event.QueryEvent in project SpinalTap by airbnb.

the class MysqlMutationMapperTest method testQuery.

@Test
public void testQuery() throws Exception {
    QueryEvent queryEvent = new QueryEvent(SERVER_ID, 15l, BINLOG_FILE_POS, DATABASE_NAME, "BEGIN");
    List<? extends Mutation> mutations = eventMapper.map(queryEvent);
    assertTrue(mutations.isEmpty());
    assertEquals(15L, beginTransaction.get().getTimestamp());
    queryEvent = new QueryEvent(SERVER_ID, 30l, BINLOG_FILE_POS, DATABASE_NAME, "");
    mutations = eventMapper.map(queryEvent);
    assertTrue(mutations.isEmpty());
    assertEquals(15L, beginTransaction.get().getTimestamp());
    queryEvent = new QueryEvent(SERVER_ID, 30l, BINLOG_FILE_POS, DATABASE_NAME, "BEGIN");
    mutations = eventMapper.map(queryEvent);
    assertTrue(mutations.isEmpty());
    assertEquals(30L, beginTransaction.get().getTimestamp());
}
Also used : QueryEvent(com.airbnb.spinaltap.mysql.event.QueryEvent) Test(org.junit.Test)

Aggregations

QueryEvent (com.airbnb.spinaltap.mysql.event.QueryEvent)6 Test (org.junit.Test)4 Maps (com.google.common.collect.Maps)3 BinlogFilePos (com.airbnb.spinaltap.mysql.BinlogFilePos)2 DeleteEvent (com.airbnb.spinaltap.mysql.event.DeleteEvent)2 StartEvent (com.airbnb.spinaltap.mysql.event.StartEvent)2 TableMapEvent (com.airbnb.spinaltap.mysql.event.TableMapEvent)2 UpdateEvent (com.airbnb.spinaltap.mysql.event.UpdateEvent)2 WriteEvent (com.airbnb.spinaltap.mysql.event.WriteEvent)2 XidEvent (com.airbnb.spinaltap.mysql.event.XidEvent)2 TreeMap (java.util.TreeMap)2 SourceState (com.airbnb.spinaltap.common.source.SourceState)1 TableCache (com.airbnb.spinaltap.mysql.TableCache)1 BinlogEvent (com.airbnb.spinaltap.mysql.event.BinlogEvent)1 DeleteRowsEventData (com.github.shyiko.mysql.binlog.event.DeleteRowsEventData)1 EventHeaderV4 (com.github.shyiko.mysql.binlog.event.EventHeaderV4)1 EventType (com.github.shyiko.mysql.binlog.event.EventType)1 QueryEventData (com.github.shyiko.mysql.binlog.event.QueryEventData)1 TableMapEventData (com.github.shyiko.mysql.binlog.event.TableMapEventData)1 UpdateRowsEventData (com.github.shyiko.mysql.binlog.event.UpdateRowsEventData)1