package com.thinkbiganalytics.ingest; /*- * #%L * thinkbig-nifi-core-processors * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.klarna.hiverunner.HiveShell; import com.klarna.hiverunner.StandaloneHiveRunner; import com.klarna.hiverunner.annotations.HiveProperties; import com.klarna.hiverunner.annotations.HiveRunnerSetup; import com.klarna.hiverunner.annotations.HiveSQL; import com.klarna.hiverunner.config.HiveRunnerConfig; import com.thinkbiganalytics.hive.util.HiveUtils; import com.thinkbiganalytics.util.ColumnSpec; import com.thinkbiganalytics.util.PartitionBatch; import com.thinkbiganalytics.util.PartitionSpec; import org.apache.commons.collections4.MapUtils; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Vector; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @RunWith(StandaloneHiveRunner.class) public class TableMergeSyncSupportTest { /** * Explicit test class configuration of the HiveRunner runtime. See {@link HiveRunnerConfig} for further details. */ @HiveRunnerSetup public final HiveRunnerConfig CONFIG = new HiveRunnerConfig() {{ setHiveExecutionEngine("mr"); }}; private final String sourceSchema = "emp_sr"; private final String sourceTable = "employee_valid"; private final String targetSchema = "emp_sr"; private final String targetTable = "employee"; private final String targetTableNP = "employee_np"; private final String processingPartition = "20160119074340"; private final PartitionSpec spec = new PartitionSpec("country|string|country\nyear|int|year(hired)"); private final PartitionSpec specNP = new PartitionSpec(""); /** * Cater for all the parameters in the script that we want to test. Note that the "hadoop.tmp.dir" is one of the dirs defined by the test harness */ @HiveProperties public Map<String, String> hiveProperties = MapUtils.putAll(new HashMap<String, String>(), new Object[]{ "MY.HDFS.DIR", "${hadoop.tmp.dir}", "my.schema", "bar", }); private TableMergeSyncSupport mergeSyncSupport; /** * Define the script files under test. The files will be loaded in the given order. <p/> The HiveRunner instantiate and inject the HiveShell */ @HiveSQL(files = { "hive-test-support/create_table.sql" }, encoding = "UTF-8") private HiveShell hiveShell; @Before public void setupSupport() throws SQLException { this.mergeSyncSupport = new HiveShellTableMergeSyncSupport(hiveShell); mergeSyncSupport.enableDynamicPartitions(); } @Test public void testPartitionBatches() { List<PartitionBatch> batches = fetchPartitionBatches(); assertTrue(batches.size() == 4); } private List<PartitionBatch> fetchPartitionBatches() { List<PartitionBatch> vBatch = new Vector<>(); String sql = spec.toDistinctSelectSQL(sourceSchema, sourceTable, processingPartition); List<Object[]> results = hiveShell.executeStatement(sql); for (Object[] vals : results) { vBatch.add(new PartitionBatch((Long) vals[2], spec, new String[]{vals[0].toString(), vals[1].toString()})); } return vBatch; } private List<String> fetchEmployees(String targetSchema, String targetTable) { return hiveShell.executeQuery("select * from " + HiveUtils.quoteIdentifier(targetSchema, targetTable)); } @Test /** * Tests the sync function */ public void testSyncWithPartitions() throws Exception { doTestSync(targetSchema, targetTable, spec); } @Test /** * Tests the sync function */ public void testSyncNonPartitioned() throws Exception { doTestSync(targetSchema, targetTableNP, specNP); } private void doTestSync(String targetSchema, String targetTable, PartitionSpec spec) throws SQLException { mergeSyncSupport.doSync(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition); List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(4, results.size()); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074340') ( `id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values " + "(100,'1'," + "'Bruce'," + "'ABC'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); mergeSyncSupport.doSync(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition); results = fetchEmployees(targetSchema, targetTable); assertEquals(5, results.size()); } @Test /** * Tests the merge with empty target table */ public void testMergePKWithEmptyTargetTable() throws Exception { List<String> results = fetchEmployees(targetSchema, targetTableNP); assertEquals(0, results.size()); ColumnSpec columnSpec1 = new ColumnSpec("id", "String", "", true, false, false); ColumnSpec columnSpec2 = new ColumnSpec("name", "String", "", false, false, false); ColumnSpec[] columnSpecs = Arrays.asList(columnSpec1, columnSpec2).toArray(new ColumnSpec[0]); // Call merge mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, new PartitionSpec(), processingPartition, columnSpecs); // We should have 4 records results = fetchEmployees(targetSchema, targetTableNP); assertEquals(4, results.size()); // Merge with same source should leave us with 4 records mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, new PartitionSpec(), processingPartition, columnSpecs); // We should have 4 records results = fetchEmployees(targetSchema, targetTableNP); assertEquals(4, results.size()); // Should update 1 and add 1 hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074350') ( `id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values " + "(1,'1'," + "'NEW VALUE'," + "'ABC'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074350') ( `id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values " + "(10010,'1'," + "'Bruce'," + "'ABC'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); // Call merge mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, new PartitionSpec(), "20160119074350", columnSpecs); // We should have 4 records results = fetchEmployees(targetSchema, targetTableNP); assertEquals(5, results.size()); } @Test /** * Tests the merge partition with empty target table */ public void testMergePartitionPKWithEmptyTargetTable() throws Exception { List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(0, results.size()); ColumnSpec columnSpec1 = new ColumnSpec("id", "String", "", true, false, false); ColumnSpec columnSpec2 = new ColumnSpec("name", "String", "", false, false, false); ColumnSpec[] columnSpecs = Arrays.asList(columnSpec1, columnSpec2).toArray(new ColumnSpec[0]); // Call merge mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, columnSpecs); // We should have 4 records results = fetchEmployees(targetSchema, targetTable); assertEquals(4, results.size()); } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergePartitionPK() throws Exception { // Insert one record to start hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2015) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (1,'1','Sally','OLD VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2015-01-01');"); doTestMergePK(targetSchema, targetTable, spec); } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergePartitionMovingPartitionPK() throws Exception { doTestMergePKWithDifferentPartitions(targetSchema, targetTable, spec); } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergePartition() throws Exception { // Insert one record to start hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2015) (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`, `processing_dttm`) values (60,'1','Billy'," + "'ABC','94550'," + "'555-1212'," + "'billy@acme.org','2015-01-01','20150119974340');"); // Validate one record initial test condition List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(1, results.size()); // Call merge mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, false); // We should have 5 records 4 from the sourceTable and 1 existing results = fetchEmployees(targetSchema, targetTable); assertEquals(5, results.size()); // Now create a duplicate record and ensure we don't see it twice the final table hiveShell.execute("insert into emp_sr.employee partition(country='Canada',year=2016) (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`processing_dttm`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01','20150119974340');"); mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, "20160119974350", true); results = fetchEmployees(targetSchema, targetTable); assertEquals(7, results.size()); verifyUnique(results); } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergePartitionNoProcessingDttm() throws Exception { String targetTable = "employeepd"; // Insert one record to start hiveShell.execute( "insert into emp_sr.employeepd partition(country='USA',year=2015) (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`) values (60,'1','Billy'," + "'ABC','94550'," + "'555-1212'," + "'billy@acme.org','2015-01-01');"); // Validate one record initial test condition List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(1, results.size()); // Call merge mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, false); // We should have 5 records 4 from the sourceTable and 1 existing results = fetchEmployees(targetSchema, targetTable); assertEquals(5, results.size()); // Now create a duplicate record and ensure we don't see it twice the final table hiveShell.execute("insert into emp_sr.employeepd partition(country='Canada',year=2016) (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01');"); mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, "20160119974350", true); results = fetchEmployees(targetSchema, targetTable); assertEquals(7, results.size()); verifyUnique(results); } // Verify no duplicates exist in the table private void verifyUnique(List<String> results) { HashSet<String> existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergeNonPartitioned() throws Exception { // Insert one record to start hiveShell.execute( "insert into emp_sr.employee_np (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`, `country`) values (60, '1', 'Billy'," + "'ABC'," + "'94550'," + "'555-1212'," + "'billy@acme.org','2015-01-01', 'USA');"); List<String> results = fetchEmployees(targetSchema, targetTableNP); assertEquals(1, results.size()); // Call merge without dedupe mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, specNP, processingPartition, false); // We should have 5 records 4 from the sourceTable and 1 existing results = fetchEmployees(targetSchema, targetTableNP); assertEquals(5, results.size()); // Now create a duplicate record and ensure we don't see it in the final table hiveShell.execute("insert into emp_sr.employee_np (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`, `country`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01', 'Canada');"); mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, specNP, "20160119974350", true); results = fetchEmployees(targetSchema, targetTableNP); assertEquals(7, results.size()); verifyUnique(results); } @Test /** * Tests the merge partition without dedupe and the merge partition with dedupe */ public void testMergeNonPartitionedWithProcessingDttm() throws Exception { String targetTableNP = "employeepd_np"; // Insert one record to start hiveShell.execute( "insert into emp_sr.employeepd_np (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`, `country`, `processing_dttm`) values (60, '1', 'Billy'," + "'ABC'," + "'94550'," + "'555-1212'," + "'billy@acme.org','2015-01-01', 'USA', '20150119974350');"); List<String> results = fetchEmployees(targetSchema, targetTableNP); assertEquals(1, results.size()); // Call merge without dedupe mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, specNP, processingPartition, false); // We should have 5 records 4 from the sourceTable and 1 existing results = fetchEmployees(targetSchema, targetTableNP); assertEquals(5, results.size()); // Now create a duplicate record and ensure we don't see it in the final table hiveShell.execute("insert into emp_sr.employeepd_np (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`, `country`, `processing_dttm`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01', 'Canada', '20150119974350');"); mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTableNP, specNP, "20160119974350", true); results = fetchEmployees(targetSchema, targetTableNP); assertEquals(7, results.size()); verifyUnique(results); } @Test /** * Test Rolling Sync. */ public void testRollingSync() throws Exception { List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(0, results.size()); doTestRollingSyncMerge(processingPartition); //Target table is empty. All 4 records should be inserted. results = fetchEmployees(targetSchema, targetTable); assertEquals(4, results.size()); //update existing partition String job1 = "20110119074340"; hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='" + job1 + "') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Harry'," + "'ABC'," + "'94550','555-1212','harry@acme.org','2016-01-01','Canada');"); doTestRollingSyncMerge(job1); //Target table should still have 4 records. Partition Canada/2016 had one record before merge. It should now have 1 updated record. results = fetchEmployees(targetSchema, targetTable); assertEquals(4, results.size()); //Record Jen is gone and replaced by Hary assertFalse(results.stream().anyMatch(x -> x.contains("Jen"))); assertTrue(results.stream().anyMatch(x -> x.contains("Harry"))); //add new existing partition String job2 = "20120119074340"; hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='" + job2 + "') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Flora'," + "'ABC'," + "'94550','555-1212','harry@acme.org','2017-01-01','France');"); doTestRollingSyncMerge(job2); //Target table should now have 5 records. Partition France/2017 has new data. No other partitions are disturbed. results = fetchEmployees(targetSchema, targetTable); assertEquals(5, results.size()); } private void doTestRollingSyncMerge(String processingPartition) throws SQLException { mergeSyncSupport.doRollingSync(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition); } private void doTestMergeNoProcessingDttm(String targetTable, PartitionSpec spec) { List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(1, results.size()); // Call merge mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, false); // We should have 5 records 4 from the sourceTable and 1 existing results = fetchEmployees(targetSchema, targetTable); assertEquals(5, results.size()); // Run merge with dedupe and should get the following two additional results. The result should not include any duplicates in the target table. hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119974340') ( `id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119974340') ( `id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) " + "values (101, '1','Harry','ABC','94550','555-1212','harry@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee partition(country='Canada',year=2016) (`id`, `timestamp`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`processing_dttm`) " + "values (100, '1', 'Bruce','ABC','94550','555-1212','bruce@acme.org','2016-01-01','20150119974340');"); mergeSyncSupport.doMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, "20160119974340", true); results = fetchEmployees(targetSchema, targetTable); assertEquals(7, results.size()); // Verify no duplicates exist in the table HashSet<String> existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } } private void doTestMergePK(String targetSchema, String targetTable, PartitionSpec spec) { List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(1, results.size()); ColumnSpec columnSpec1 = new ColumnSpec("id", "String", "", true, false, false); ColumnSpec columnSpec2 = new ColumnSpec("name", "String", "", false, false, false); ColumnSpec[] columnSpecs = Arrays.asList(columnSpec1, columnSpec2).toArray(new ColumnSpec[0]); // Call merge mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, columnSpecs); // We should have 4 records results = fetchEmployees(targetSchema, targetTable); assertEquals(4, results.size()); assertFalse("Should not have old valur", results.stream().anyMatch(s -> s.contains("OLD"))); // Run merge with dedupe and should get the following two additional results. The result should not include any duplicates in the target table. hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074340') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (100,'Bruce'," + "'OLD'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074340') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Harry'," + "'OLD'," + "'94550','555-1212','harry@acme.org','2016-01-01','Canada');"); mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, columnSpecs); results = fetchEmployees(targetSchema, targetTable); assertEquals(6, results.size()); // Verify no duplicates exist in the table HashSet<String> existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (100,'Bruce'," + "'ABC'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Harry'," + "'ABC'," + "'94550','555-1212','harry@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (102,'Buddy'," + "'ABC'," + "'94550','555-1212','buddy@acme.org','2016-01-01','Canada');"); mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, "20160119074540", columnSpecs); results = fetchEmployees(targetSchema, targetTable); assertEquals(7, results.size()); existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } assertFalse("Should not have old valur", results.stream().anyMatch(s -> s.contains("OLD"))); } /* Test ability to strip records that match the ID but are in a different partition than the newer record */ private void doTestMergePKWithDifferentPartitions(String targetSchema, String targetTable, PartitionSpec spec) { // Insert one record to start hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2012) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (1,'1','Sally','OLD VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2012-01-01');"); hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2012) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (1002,'1','Jimbo','VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2012-01-01');"); hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2015) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (1000,'1','Jill','ORIG','94550'," + "'555-1212'," + "'sally@acme.org','2015-01-01');"); hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2013) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (2,'1','Bill','OLD VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2013-01-01');"); hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2013) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (3,'1','Ray','OLD VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2013-01-01');"); hiveShell.execute( "insert into emp_sr.employee partition(country='USA',year=2013) ( `id`, `timestamp`,`name`,`company`,`zip`,`phone`,`email`, `hired`) values (1001,'1','Fred','VALUE','94550'," + "'555-1212'," + "'sally@acme.org','2013-01-01');"); List<String> results = fetchEmployees(targetSchema, targetTable); assertEquals(6, results.size()); ColumnSpec columnSpec1 = new ColumnSpec("id", "String", "", true, false, false); ColumnSpec columnSpec2 = new ColumnSpec("name", "String", "", false, false, false); ColumnSpec[] columnSpecs = Arrays.asList(columnSpec1, columnSpec2).toArray(new ColumnSpec[0]); // Call merge mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, columnSpecs); // We should have 6 records results = fetchEmployees(targetSchema, targetTable); assertEquals(6, results.size()); assertFalse("Should not have old value", results.stream().anyMatch(s -> s.contains("OLD"))); // Run merge with dedupe and should get the following two additional results. The result should not include any duplicates in the target table. hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074340') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (100,'Bruce'," + "'OLD'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074340') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Harry'," + "'OLD'," + "'94550','555-1212','harry@acme.org','2016-01-01','Canada');"); mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, processingPartition, columnSpecs); results = fetchEmployees(targetSchema, targetTable); assertEquals(8, results.size()); // Verify no duplicates exist in the table HashSet<String> existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (100,'Bruce'," + "'ABC'," + "'94550','555-1212','bruce@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (101,'Harry'," + "'ABC'," + "'94550','555-1212','harry@acme.org','2016-01-01','Canada');"); hiveShell.execute("insert into emp_sr.employee_valid partition(processing_dttm='20160119074540') ( `id`, `name`,`company`,`zip`,`phone`,`email`, `hired`,`country`) values (102,'Buddy'," + "'ABC'," + "'94550','555-1212','buddy@acme.org','2016-01-01','Canada');"); mergeSyncSupport.doPKMerge(sourceSchema, sourceTable, targetSchema, targetTable, spec, "20160119074540", columnSpecs); results = fetchEmployees(targetSchema, targetTable); assertEquals(9, results.size()); existing = new HashSet<>(); for (String r : results) { assertFalse(existing.contains(r)); existing.add(r); } assertFalse("Should not have old value", results.stream().anyMatch(s -> s.contains("OLD"))); } }