예제 #1
0
    def runTest(self):
        messages = tap_mysql.generate_messages(self.con, {}, self.catalog, {})

        record_message = list(filter(lambda m: isinstance(m, singer.RecordMessage), messages))[0]

        self.assertTrue(isinstance(record_message, singer.RecordMessage))
        self.assertEqual(record_message.record, {'b c': 1})
예제 #2
0
 def test_with_no_state(self):
     state = {}
     (message_types, versions) = message_types_and_versions(
         tap_mysql.generate_messages(self.con, {}, self.catalog, state))
     self.assertEqual(['ActivateVersionMessage', 'RecordMessage', 'ActivateVersionMessage'], message_types)
     self.assertTrue(isinstance(versions[0], int))
     self.assertEqual(versions[0], versions[1])
예제 #3
0
    def runTest(self):
        con = get_test_connection()
        try:
            with con.cursor() as cur:
                cur.execute('''
                    CREATE TABLE tab (
                      id INTEGER PRIMARY KEY,
                      a INTEGER,
                      b INTEGER)
                ''')

            catalog = discover_catalog(con)
            catalog.streams[0].stream = 'tab'
            catalog.streams[0].schema.selected = True
            catalog.streams[0].schema.properties['a'].selected = True
            messages = list(
                tap_mysql.generate_messages(con, catalog,
                                            tap_mysql.build_state({},
                                                                  catalog)))
            schema_message = list(
                filter(lambda m: isinstance(m, singer.SchemaMessage),
                       messages))[0]
            self.assertTrue(isinstance(schema_message, singer.SchemaMessage))
            expectedKeys = ['id', 'a']

            self.assertEqual(schema_message.schema['properties'].keys(),
                             set(expectedKeys))

        finally:
            con.close()
예제 #4
0
    def test_with_state(self):
        state = tap_mysql.build_state(
            {
                'bookmarks': {
                    'tap_mysql_test-incremental': {
                        'version': 1,
                        'replication_key_value': '2017-06-20',
                        'replication_key': 'updated'
                    },
                    'tap_mysql_test-integer_incremental': {
                        'version': 1,
                        'replication_key_value': 3,
                        'replication_key': 'updated'
                    }
                }
            }, self.catalog)

        (message_types, versions) = message_types_and_versions(
            tap_mysql.generate_messages(self.con, self.catalog, state))
        self.assertEqual([
            'ActivateVersionMessage', 'RecordMessage', 'RecordMessage',
            'ActivateVersionMessage', 'RecordMessage'
        ], message_types)
        self.assertTrue(isinstance(versions[0], int))
        self.assertEqual(versions[0], versions[1])
        self.assertEqual(versions[1], 1)
예제 #5
0
    def test_fail_if_log_file_does_not_exist(self):
        log_file = 'chicken'
        stream = self.catalog.streams[0]
        state = {
            'bookmarks': {
                stream.tap_stream_id: {
                    'version': singer.utils.now(),
                    'log_file': log_file,
                    'log_pos': 1
                }
            }
        }

        failed = False
        exception_message = None
        expected_exception_message = "Unable to replicate stream({}) with binlog because log file {} does not exist.".format(
            stream,
            log_file
            )

        try:
            list(tap_mysql.generate_messages(self.con, {}, self.catalog, state))
        except Exception as e:
            failed = True
            exception_message = str(e)
            LOGGER.error(exception_message)
예제 #6
0
    def test_initial_full_table(self):
        state = {}
        expected_log_file, expected_log_pos = binlog.fetch_current_log_file_and_pos(self.con)

        messages = list(tap_mysql.generate_messages(self.con, {}, self.catalog, state))

        message_types = [type(m) for m in messages]

        self.assertEqual(message_types,
                         [singer.StateMessage,
                          singer.SchemaMessage,
                          singer.ActivateVersionMessage,
                          singer.RecordMessage,
                          singer.RecordMessage,
                          singer.StateMessage,
                          singer.ActivateVersionMessage,
                          singer.StateMessage,
                          singer.StateMessage])

        activate_version_message = list(filter(lambda m: isinstance(m, singer.ActivateVersionMessage), messages))[0]
        record_messages = list(filter(lambda m: isinstance(m, singer.RecordMessage), messages))

        self.assertEqual(singer.get_bookmark(state, 'tap_mysql_test-binlog', 'log_file'),
                         expected_log_file)

        self.assertEqual(singer.get_bookmark(state, 'tap_mysql_test-binlog', 'log_pos'),
                         expected_log_pos)

        self.assertEqual(singer.get_bookmark(state, 'tap_mysql_test-binlog', 'version'),
                         activate_version_message.version)
예제 #7
0
 def runTest(self):
     catalog = discover_catalog(self.con)
     catalog.streams[0].stream = 'some_stream_name'
     catalog.streams[0].schema.selected = True
     catalog.streams[0].key_properties = []
     catalog.streams[0].schema.properties['b c'].selected = True
     messages = tap_mysql.generate_messages(
         self.con, catalog, tap_mysql.build_state({}, catalog))
     record_message = list(
         filter(lambda m: isinstance(m, singer.RecordMessage), messages))[0]
     self.assertTrue(isinstance(record_message, singer.RecordMessage))
     self.assertEqual(record_message.record, {'b c': 1})
예제 #8
0
    def test_version_not_cleared_from_state_after_incremental_success(self):
        state = tap_mysql.build_state(
            {'bookmarks': {
                'tap_mysql_test-incremental': {
                    'version': 1,
                }
            }}, self.catalog)

        list(tap_mysql.generate_messages(self.con, self.catalog, state))

        self.assertEqual(
            state['bookmarks']['tap_mysql_test-incremental']['version'], 1)
예제 #9
0
    def test_version_cleared_from_state_after_full_table_success(self):
        state = tap_mysql.build_state(
            {'bookmarks': {
                'tap_mysql_test-full_table': {
                    'version': 1,
                }
            }}, self.catalog)

        list(tap_mysql.generate_messages(self.con, self.catalog, state))

        self.assertEqual(
            state['bookmarks']['tap_mysql_test-full_table']['version'], None)
예제 #10
0
 def test_with_no_version_in_state(self):
     state = tap_mysql.build_state(
         {'bookmarks': {
             'tap_mysql_test-full_table': {
                 'version': None,
             }
         }}, self.catalog)
     (message_types, versions) = message_types_and_versions(
         tap_mysql.generate_messages(self.con, self.catalog, state))
     self.assertEqual(['RecordMessage', 'ActivateVersionMessage'],
                      message_types)
     self.assertTrue(isinstance(versions[0], int))
     self.assertEqual(versions[0], versions[1])
예제 #11
0
    def test_version_not_cleared_from_state_after_incremental_success(self):
        state = {
            'bookmarks': {
                'tap_mysql_test-incremental': {
                    'version': 1,
                    'replication_key_value': '2017-06-20',
                    'replication_key': 'updated'
                }
            }
        }

        list(tap_mysql.generate_messages(self.con, {}, self.catalog, state))

        self.assertEqual(state['bookmarks']['tap_mysql_test-incremental']['version'], 1)
예제 #12
0
    def test_version_cleared_from_state_after_full_table_success(self):
        state = {
            'bookmarks': {
                'tap_mysql_test-full_table': {
                    'version': 1,
                    'initial_full_table_complete': True
                }
            }
        }

        list(tap_mysql.generate_messages(self.con, {}, self.catalog, state))

        self.assertFalse('version' in state['bookmarks']['tap_mysql_test-full_table'].keys())
        self.assertTrue(state['bookmarks']['tap_mysql_test-full_table']['initial_full_table_complete'])
예제 #13
0
    def test_with_initial_full_table_complete_in_state(self):
        common.get_stream_version = lambda a, b: 12345

        state = {
            'bookmarks': {
                'tap_mysql_test-full_table': {
                    'initial_full_table_complete': True
                }
            }
        }

        (message_types, versions) = message_types_and_versions(
            tap_mysql.generate_messages(self.con, {}, self.catalog, state))

        self.assertEqual(['RecordMessage', 'ActivateVersionMessage'], message_types)
        self.assertEqual(versions, [12345, 12345])
예제 #14
0
    def test_fail_on_view(self):
        for stream in self.catalog.streams:
            stream.is_view = True

        state = {}

        failed = False
        exception_message = None
        expected_exception_message = "Unable to replicate stream({}) with binlog because it is a view.".format(self.catalog.streams[0].stream)

        try:
            list(tap_mysql.generate_messages(self.con, {}, self.catalog, state))
        except Exception as e:
            failed = True
            exception_message = str(e)
            LOGGER.error(exception_message)

        self.assertTrue(failed)
        self.assertEqual(expected_exception_message, exception_message)
예제 #15
0
    def test_binlog_stream(self):
        stream = self.catalog.streams[0]
        reader = BinLogStreamReader(
            connection_settings=get_db_config(),
            server_id=binlog.fetch_server_id(self.con),
            only_events=[RotateEvent, WriteRowsEvent, UpdateRowsEvent, DeleteRowsEvent],
        )

        for _ in reader:
            expected_log_file = reader.log_file
            expected_log_pos = reader.log_pos

        messages = list(tap_mysql.generate_messages(self.con, get_db_config(), self.catalog, self.state))
        record_messages = list(filter(lambda m: isinstance(m, singer.RecordMessage), messages))

        message_types = [type(m) for m in messages]

        self.assertEqual(message_types,
                         [singer.StateMessage,
                          singer.SchemaMessage,
                          singer.RecordMessage,
                          singer.RecordMessage,
                          singer.RecordMessage,
                          singer.RecordMessage,
                          singer.RecordMessage,
                          singer.StateMessage,
                          singer.StateMessage])

        self.assertEqual([(1, False), (2, False), (3, False), (3, False), (2, True)],
                         [(m.record['id'], m.record.get(binlog.SDC_DELETED_AT) is not None)
                          for m in record_messages])

        self.assertEqual(singer.get_bookmark(self.state, 'tap_mysql_test-binlog', 'log_file'),
                         expected_log_file)

        self.assertEqual(singer.get_bookmark(self.state, 'tap_mysql_test-binlog', 'log_pos'),
                         expected_log_pos)
예제 #16
0
 def test_start_at_currently_syncing(self):
     state = tap_mysql.build_state(
         {'currently_syncing': 'tap_mysql_test-b'}, self.catalog)
     messages = list(
         tap_mysql.generate_messages(self.con, self.catalog, state))
     self.assertRegexpMatches(currently_syncing_seq(messages), '^b+_+')
예제 #17
0
 def test_emit_currently_syncing(self):
     state = tap_mysql.build_state({}, self.catalog)
     messages = list(
         tap_mysql.generate_messages(self.con, self.catalog, state))
     self.assertRegexpMatches(currently_syncing_seq(messages), '^a+b+_+')