/** * Verify that the given {@link SourceRecord} is a {@link Operation#CREATE INSERT/CREATE} record without primary key. * * @param record the source record; may not be null */ public static void isValidInsert(SourceRecord record) { isValidInsert(record, false); }
protected void assertInsert(SourceRecord record, String pkField, int pk) { VerifyRecord.isValidInsert(record, pkField, pk); }
/** * Verify that the given {@link SourceRecord} is a {@link Operation#CREATE INSERT/CREATE} record, and that the integer key * matches the expected value. * * @param record the source record; may not be null * @param pkField the single field defining the primary key of the struct; may not be null * @param pk the expected integer value of the primary key in the struct */ public static void isValidInsert(SourceRecord record, String pkField, int pk) { hasValidKey(record, pkField, pk); isValidInsert(record, true); }
private SourceRecord assertRecordInserted(String expectedTopicName, String pkColumn, Integer pk) throws InterruptedException { assertFalse("records not generated", consumer.isEmpty()); SourceRecord insertedRecord = consumer.remove(); assertEquals(topicName(expectedTopicName), insertedRecord.topic()); if (pk != null) { VerifyRecord.isValidInsert(insertedRecord, pkColumn, pk); } else { VerifyRecord.isValidInsert(insertedRecord); } return insertedRecord; }
private void assertRecordsAfterInsert(int expectedCount, int...pks) throws InterruptedException { SourceRecords actualRecords = consumeRecordsByTopic(expectedCount); assertThat(actualRecords.topics().size()).isEqualTo(expectedCount); // we have 2 schemas int expectedCountPerSchema = expectedCount / 2; List<SourceRecord> recordsForTopicS1 = actualRecords.recordsForTopic(topicName("s1.a")); assertThat(recordsForTopicS1.size()).isEqualTo(expectedCountPerSchema); IntStream.range(0, expectedCountPerSchema).forEach(i -> VerifyRecord.isValidInsert(recordsForTopicS1.remove(0), PK_FIELD, pks[i])); List<SourceRecord> recordsForTopicS2 = actualRecords.recordsForTopic(topicName("s2.a")); assertThat(recordsForTopicS2.size()).isEqualTo(expectedCountPerSchema); IntStream.range(0, expectedCountPerSchema).forEach(i -> VerifyRecord.isValidInsert(recordsForTopicS2.remove(0), PK_FIELD, pks[i])); }
@Test public void shouldReceiveChangesForDefaultValues() throws Exception { String statements = "ALTER TABLE test_table REPLICA IDENTITY FULL;" + "ALTER TABLE test_table ADD COLUMN default_column TEXT DEFAULT 'default';" + "INSERT INTO test_table (text) VALUES ('update');"; consumer = testConsumer(1); recordsProducer.start(consumer, blackHole); executeAndWait(statements); SourceRecord insertRecord = consumer.remove(); assertEquals(topicName("public.test_table"), insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); List<SchemaAndValueField> expectedSchemaAndValues = Arrays.asList( new SchemaAndValueField("text", SchemaBuilder.OPTIONAL_STRING_SCHEMA, "update"), new SchemaAndValueField("default_column", SchemaBuilder.OPTIONAL_STRING_SCHEMA ,"default")); assertRecordSchemaAndValues(expectedSchemaAndValues, insertRecord, Envelope.FieldName.AFTER); }
@Test public void shouldReceiveChangesForUpdatesWithPKChanges() throws Exception { consumer = testConsumer(3); recordsProducer.start(consumer, blackHole); executeAndWait("UPDATE test_table SET text = 'update', pk = 2"); String topicName = topicName("public.test_table"); // first should be a delete of the old pk SourceRecord deleteRecord = consumer.remove(); assertEquals(topicName, deleteRecord.topic()); VerifyRecord.isValidDelete(deleteRecord, PK_FIELD, 1); // followed by a tombstone of the old pk SourceRecord tombstoneRecord = consumer.remove(); assertEquals(topicName, tombstoneRecord.topic()); VerifyRecord.isValidTombstone(tombstoneRecord, PK_FIELD, 1); // and finally insert of the new value SourceRecord insertRecord = consumer.remove(); assertEquals(topicName, insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); }
updatedRecord = consumer.remove(); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 2); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", Decimal.builder(1).parameter(TestHelper.PRECISION_PARAMETER_KEY, "6").optional().build(), new BigDecimal("123.4"))), updatedRecord, Envelope.FieldName.AFTER); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 3); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", VariableScaleDecimal.builder().optional().build(), dvs)), updatedRecord, Envelope.FieldName.AFTER); updatedRecord = consumer.remove(); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 4); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", Decimal.builder(4).parameter(TestHelper.PRECISION_PARAMETER_KEY, "12").optional().build(), new BigDecimal("2.4800"))), updatedRecord, Envelope.FieldName.AFTER); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 5); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", Decimal.builder(0).parameter(TestHelper.PRECISION_PARAMETER_KEY, "12").optional().build(), new BigDecimal("1238"))), updatedRecord, Envelope.FieldName.AFTER); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 6); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", VariableScaleDecimal.builder().optional().build(), dvs2)), updatedRecord, Envelope.FieldName.AFTER); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 7); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("num_val", VariableScaleDecimal.builder().build(), dvs2)), updatedRecord, Envelope.FieldName.AFTER);
@Test @FixFor("DBZ-582") public void shouldReceiveChangesForUpdatesWithPKChangesWithoutTombstone() throws Exception { PostgresConnectorConfig config = new PostgresConnectorConfig(TestHelper.defaultConfig() .with(PostgresConnectorConfig.INCLUDE_UNKNOWN_DATATYPES, true) .with(CommonConnectorConfig.TOMBSTONES_ON_DELETE, false) .build() ); setupRecordsProducer(config); consumer = testConsumer(2); recordsProducer.start(consumer, blackHole); executeAndWait("UPDATE test_table SET text = 'update', pk = 2"); String topicName = topicName("public.test_table"); // first should be a delete of the old pk SourceRecord deleteRecord = consumer.remove(); assertEquals(topicName, deleteRecord.topic()); VerifyRecord.isValidDelete(deleteRecord, PK_FIELD, 1); // followed by insert of the new value SourceRecord insertRecord = consumer.remove(); assertEquals(topicName, insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); }
updatedRecord = consumer.remove(); VerifyRecord.isValidInsert(updatedRecord, PK_FIELD, 2); assertRecordSchemaAndValues( Collections.singletonList(new SchemaAndValueField("modtype", SchemaBuilder.OPTIONAL_INT32_SCHEMA, 1)), updatedRecord, Envelope.FieldName.AFTER);
VerifyRecord.isValidInsert(first, PK_FIELD, 2); assertEquals(topicName("s1.a"), first.topic()); assertRecordOffsetAndSnapshotSource(first, false, false); VerifyRecord.isValidInsert(second, PK_FIELD, 2); assertEquals(topicName("s2.a"), second.topic()); assertRecordOffsetAndSnapshotSource(second, false, false); VerifyRecord.isValidInsert(first, PK_FIELD, 4); assertRecordOffsetAndSnapshotSource(first, false, false); assertSourceInfo(first, "test_database", "s1", "a"); VerifyRecord.isValidInsert(second, PK_FIELD, 4); assertRecordOffsetAndSnapshotSource(second, false, false); assertSourceInfo(second, "test_database", "s2", "a");
VerifyRecord.isValidInsert(insert, "id", 1);
protected void assertInsert(SourceRecord record, String pkField, int pk) { VerifyRecord.isValidInsert(record, pkField, pk); }
private SourceRecord assertRecordInserted(String expectedTopicName, String pkColumn, Integer pk) throws InterruptedException { assertFalse("records not generated", consumer.isEmpty()); SourceRecord insertedRecord = consumer.remove(); assertEquals(topicName(expectedTopicName), insertedRecord.topic()); if (pk != null) { VerifyRecord.isValidInsert(insertedRecord, pkColumn, pk); } else { VerifyRecord.isValidInsert(insertedRecord); } return insertedRecord; }
private void assertRecordsAfterInsert(int expectedCount, int...pks) throws InterruptedException { SourceRecords actualRecords = consumeRecordsByTopic(expectedCount); assertThat(actualRecords.topics().size()).isEqualTo(expectedCount); // we have 2 schemas int expectedCountPerSchema = expectedCount / 2; List<SourceRecord> recordsForTopicS1 = actualRecords.recordsForTopic(topicName("s1.a")); assertThat(recordsForTopicS1.size()).isEqualTo(expectedCountPerSchema); IntStream.range(0, expectedCountPerSchema).forEach(i -> VerifyRecord.isValidInsert(recordsForTopicS1.remove(0), PK_FIELD, pks[i])); List<SourceRecord> recordsForTopicS2 = actualRecords.recordsForTopic(topicName("s2.a")); assertThat(recordsForTopicS2.size()).isEqualTo(expectedCountPerSchema); IntStream.range(0, expectedCountPerSchema).forEach(i -> VerifyRecord.isValidInsert(recordsForTopicS2.remove(0), PK_FIELD, pks[i])); }
@Test public void shouldReceiveChangesForDefaultValues() throws Exception { String statements = "ALTER TABLE test_table REPLICA IDENTITY FULL;" + "ALTER TABLE test_table ADD COLUMN default_column TEXT DEFAULT 'default';" + "INSERT INTO test_table (text) VALUES ('update');"; consumer = testConsumer(1); recordsProducer.start(consumer, blackHole); executeAndWait(statements); SourceRecord insertRecord = consumer.remove(); assertEquals(topicName("public.test_table"), insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); List<SchemaAndValueField> expectedSchemaAndValues = Arrays.asList( new SchemaAndValueField("text", SchemaBuilder.OPTIONAL_STRING_SCHEMA, "update"), new SchemaAndValueField("default_column", SchemaBuilder.OPTIONAL_STRING_SCHEMA ,"default")); assertRecordSchemaAndValues(expectedSchemaAndValues, insertRecord, Envelope.FieldName.AFTER); }
@Test public void shouldReceiveChangesForUpdatesWithPKChanges() throws Exception { consumer = testConsumer(3); recordsProducer.start(consumer, blackHole); executeAndWait("UPDATE test_table SET text = 'update', pk = 2"); String topicName = topicName("public.test_table"); // first should be a delete of the old pk SourceRecord deleteRecord = consumer.remove(); assertEquals(topicName, deleteRecord.topic()); VerifyRecord.isValidDelete(deleteRecord, PK_FIELD, 1); // followed by a tombstone of the old pk SourceRecord tombstoneRecord = consumer.remove(); assertEquals(topicName, tombstoneRecord.topic()); VerifyRecord.isValidTombstone(tombstoneRecord, PK_FIELD, 1); // and finally insert of the new value SourceRecord insertRecord = consumer.remove(); assertEquals(topicName, insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); }
@Test @FixFor("DBZ-582") public void shouldReceiveChangesForUpdatesWithPKChangesWithoutTombstone() throws Exception { PostgresConnectorConfig config = new PostgresConnectorConfig(TestHelper.defaultConfig() .with(PostgresConnectorConfig.INCLUDE_UNKNOWN_DATATYPES, true) .with(CommonConnectorConfig.TOMBSTONES_ON_DELETE, false) .build() ); setupRecordsProducer(config); consumer = testConsumer(2); recordsProducer.start(consumer, blackHole); executeAndWait("UPDATE test_table SET text = 'update', pk = 2"); String topicName = topicName("public.test_table"); // first should be a delete of the old pk SourceRecord deleteRecord = consumer.remove(); assertEquals(topicName, deleteRecord.topic()); VerifyRecord.isValidDelete(deleteRecord, PK_FIELD, 1); // followed by insert of the new value SourceRecord insertRecord = consumer.remove(); assertEquals(topicName, insertRecord.topic()); VerifyRecord.isValidInsert(insertRecord, PK_FIELD, 2); }
@Test public void intTypes() throws Exception { int expectedRecordCount = 0; if (insertRecordsDuringTest()) { insertIntTypes(); } Testing.debug("Inserted"); expectedRecordCount++; final SourceRecords records = consumeRecordsByTopic(expectedRecordCount); List<SourceRecord> testTableRecords = records.recordsForTopic("server1.DEBEZIUM.TYPE_INT"); assertThat(testTableRecords).hasSize(expectedRecordCount); SourceRecord record = testTableRecords.get(0); VerifyRecord.isValid(record); // insert if (insertRecordsDuringTest()) { VerifyRecord.isValidInsert(record, "ID", 1); } else { VerifyRecord.isValidRead(record, "ID", 1); } Struct after = (Struct) ((Struct)record.value()).get("after"); assertRecord(after, EXPECTED_INT); }
@Test public void stringTypes() throws Exception { int expectedRecordCount = 0; if (insertRecordsDuringTest()) { insertStringTypes(); } Testing.debug("Inserted"); expectedRecordCount++; final SourceRecords records = consumeRecordsByTopic(expectedRecordCount); List<SourceRecord> testTableRecords = records.recordsForTopic("server1.DEBEZIUM.TYPE_STRING"); assertThat(testTableRecords).hasSize(expectedRecordCount); SourceRecord record = testTableRecords.get(0); VerifyRecord.isValid(record); // insert if (insertRecordsDuringTest()) { VerifyRecord.isValidInsert(record, "ID", 1); } else { VerifyRecord.isValidRead(record, "ID", 1); } Struct after = (Struct) ((Struct)record.value()).get("after"); assertRecord(after, EXPECTED_STRING); }