Repository: tapdata/tapdata (language: python)

Issue:
feat: TAP-3982 whether create unique index according to update condit…
…ion fileds


Discussion / hints:

Fix patch:
diff --git a/manager/tm/src/main/java/com/tapdata/tm/task/service/TaskServiceImpl.java b/manager/tm/src/main/java/com/tapdata/tm/task/service/TaskServiceImpl.java
index ec52ba9dcc..1fe9eb25b7 100644
--- a/manager/tm/src/main/java/com/tapdata/tm/task/service/TaskServiceImpl.java
+++ b/manager/tm/src/main/java/com/tapdata/tm/task/service/TaskServiceImpl.java
@@ -34,6 +34,8 @@
 import com.tapdata.tm.shareCdcTableMapping.service.ShareCdcTableMappingService;
 import com.tapdata.tm.task.bean.*;
 import com.tapdata.tm.task.vo.*;
+import io.tapdata.pdk.apis.entity.Capability;
+import io.tapdata.pdk.apis.entity.TestItem;
 import io.tapdata.pdk.core.api.PDKIntegration;
 import org.apache.commons.io.FileUtils;
 import org.mockito.Mockito;
diff --git a/manager/tm/src/main/resources/messages_zh_CN.properties b/manager/tm/src/main/resources/messages_zh_CN.properties
index ed834cb69c..5f3819aa17 100644
--- a/manager/tm/src/main/resources/messages_zh_CN.properties
+++ b/manager/tm/src/main/resources/messages_zh_CN.properties
@@ -302,4 +302,4 @@ inspect.result.not.exists=\u5F53\u524D\u6821\u9A8C\u4EFB\u52A1\u7684\u6821\u9A8C
 
 source.setting.check.cdc= \u589E\u91CF\u68C0\u67E5\u3011\u0020\u6570\u636E\u6E90:{0}\u7684\u589E\u91CF\u529F\u80FD\u4E0D\u652F\u6301\uFF0C\u4E0D\u80FD\u914D\u7F6E\u589E\u91CF\u4EFB\u52A1\u000d\u000a
 
-export.inspectDetails.failed =\u4E0B\u8F7D\u6821\u9A8C\u8BE6\u60C5\u5931\u8D25 :{0}
+export.inspectDetails.failed =\u4E0B\u8F7D\u6821\u9A8C\u8BE6\u60C5\u5931\u8D25 :{0}
\ No newline at end of file


Test patch:
diff --git a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastSourcePdkBaseNodeTest.java b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastSourcePdkBaseNodeTest.java
index 06c680e316..b359723042 100644
--- a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastSourcePdkBaseNodeTest.java
+++ b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastSourcePdkBaseNodeTest.java
@@ -10,6 +10,7 @@
 import com.tapdata.entity.dataflow.SyncProgress;
 import com.tapdata.entity.task.config.TaskConfig;
 import com.tapdata.entity.task.config.TaskRetryConfig;
+import com.tapdata.entity.task.context.DataProcessorContext;
 import com.tapdata.tm.commons.cdcdelay.CdcDelay;
 import com.tapdata.tm.commons.cdcdelay.ICdcDelay;
 import com.tapdata.tm.commons.dag.DAG;
@@ -71,6 +72,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ScheduledExecutorService;
diff --git a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkBaseNodeTest.java b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkBaseNodeTest.java
index be4003ad20..12beba6a57 100644
--- a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkBaseNodeTest.java
+++ b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkBaseNodeTest.java
@@ -16,6 +16,7 @@
 import com.tapdata.tm.commons.dag.process.MergeTableNode;
 import com.tapdata.tm.commons.dag.process.UnwindProcessNode;
 import com.tapdata.tm.commons.task.dto.TaskDto;
+import com.tapdata.tm.commons.util.JsonUtil;
 import io.tapdata.aspect.CreateTableFuncAspect;
 import io.tapdata.aspect.DropTableFuncAspect;
 import io.tapdata.aspect.supervisor.DataNodeThreadGroupAspect;
@@ -66,6 +67,7 @@
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 import org.mockito.internal.verification.Times;
+import org.springframework.beans.BeanUtils;
 import org.springframework.test.util.ReflectionTestUtils;
 
 import java.time.Instant;
diff --git a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkDataNodeTest.java b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkDataNodeTest.java
index 301d524937..b0e80f0e47 100644
--- a/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkDataNodeTest.java
+++ b/iengine/iengine-app/src/test/java/io/tapdata/flow/engine/V2/node/hazelcast/data/pdk/HazelcastTargetPdkDataNodeTest.java
@@ -580,25 +580,37 @@ void beforeEach(){
 			ArrayList<String> pks = new ArrayList<>();
 			when(tapTable.primaryKeys()).thenReturn(pks);
 			when(hazelcastTargetPdkDataNode.usePkAsUpdateConditions(updateConditionFields,pks)).thenReturn(false);
+			createUnique = true;
 			createdTable = true;
 			String writeStrategy = "updateOrInsert";
 			ReflectionTestUtils.setField(hazelcastTargetPdkDataNode,"writeStrategy",writeStrategy);
 			Boolean unwindProcess = false;
 			ReflectionTestUtils.setField(hazelcastTargetPdkDataNode,"unwindProcess",unwindProcess);
 			doCallRealMethod().when(hazelcastTargetPdkDataNode).executeDataFuncAspect(any(Class.class),any(Callable.class),any(CommonUtils.AnyErrorConsumer.class));
-		}
-		@Test
-		@DisplayName("test createTargetIndex method for build error consumer")
-		void test1(){
+			ReflectionTestUtils.setField(hazelcastTargetPdkDataNode,"obsLogger",mockObsLogger);
 			ConnectorNode connectorNode = mock(ConnectorNode.class);
 			when(hazelcastTargetPdkDataNode.getConnectorNode()).thenReturn(connectorNode);
 			ConnectorFunctions functions = mock(ConnectorFunctions.class);
 			when(connectorNode.getConnectorFunctions()).thenReturn(functions);
 			when(functions.getCreateIndexFunction()).thenReturn(mock(CreateIndexFunction.class));
 			doCallRealMethod().when(hazelcastTargetPdkDataNode).createTargetIndex(updateConditionFields,createUnique,tableId,tapTable,createdTable);
+		}
+		@Test
+		@DisplayName("test createTargetIndex method for build error consumer")
+		void test1(){
 			hazelcastTargetPdkDataNode.createTargetIndex(updateConditionFields,createUnique,tableId,tapTable,createdTable);
 			verify(hazelcastTargetPdkDataNode,new Times(1)).buildErrorConsumer(tableId);
 		}
+		@Test
+		@SneakyThrows
+		@DisplayName("test createTargetIndex method when index already exists")
+		void test3(){
+			List<TapIndex> existsIndexes = new ArrayList<>();
+			existsIndexes.add(mock(TapIndex.class));
+			when(hazelcastTargetPdkDataNode.queryExistsIndexes(any(TapTable.class),anyList())).thenReturn(existsIndexes);
+			hazelcastTargetPdkDataNode.createTargetIndex(updateConditionFields,createUnique,tableId,tapTable,createdTable);
+			verify(hazelcastTargetPdkDataNode,never()).executeDataFuncAspect(any(Class.class),any(Callable.class),any(CommonUtils.AnyErrorConsumer.class));
+		}
 	}
 	@Nested
 	class clearDataTest{
@@ -807,4 +819,46 @@ void test3(){
 			assertEquals(node.getConcurrentWritePartitionMap().size(),concurrentWritePartitionMap.size());
 		}
 	}
+	@Nested
+	class checkCreateUniqueIndexOpenTest{
+		private Node node;
+		private DataParentNode dataParentNode;
+		@BeforeEach
+		void beforeEach(){
+			node = mock(DatabaseNode.class);
+			dataParentNode = (DataParentNode) node;
+			doCallRealMethod().when(hazelcastTargetPdkDataNode).checkCreateUniqueIndexOpen();
+		}
+		@Test
+		@DisplayName("test checkCreateUniqueIndexOpen method when switch is on")
+		void test1(){
+			when(dataParentNode.getUniqueIndexEnable()).thenReturn(true);
+			when(hazelcastTargetPdkDataNode.getNode()).thenReturn(node);
+			boolean actual = hazelcastTargetPdkDataNode.checkCreateUniqueIndexOpen();
+			assertEquals(true, actual);
+		}
+		@Test
+		@DisplayName("test checkCreateUniqueIndexOpen method when switch is off")
+		void test2(){
+			when(dataParentNode.getUniqueIndexEnable()).thenReturn(false);
+			when(hazelcastTargetPdkDataNode.getNode()).thenReturn(node);
+			boolean actual = hazelcastTargetPdkDataNode.checkCreateUniqueIndexOpen();
+			assertEquals(false, actual);
+		}
+		@Test
+		@DisplayName("test checkCreateUniqueIndexOpen method when node is null")
+		void test3(){
+			when(hazelcastTargetPdkDataNode.getNode()).thenReturn(null);
+			boolean actual = hazelcastTargetPdkDataNode.checkCreateUniqueIndexOpen();
+			assertEquals(true, actual);
+		}
+		@Test
+		@DisplayName("test checkCreateUniqueIndexOpen method when node is not database node or table node")
+		void test4(){
+			Node node1 = mock(Node.class);
+			when(hazelcastTargetPdkDataNode.getNode()).thenReturn(node1);
+			boolean actual = hazelcastTargetPdkDataNode.checkCreateUniqueIndexOpen();
+			assertEquals(true, actual);
+		}
+	}
 }
diff --git a/manager/tm/src/test/java/com/tapdata/tm/task/service/TaskServiceImplTest.java b/manager/tm/src/test/java/com/tapdata/tm/task/service/TaskServiceImplTest.java
index 5842e9eb35..ec06526781 100644
--- a/manager/tm/src/test/java/com/tapdata/tm/task/service/TaskServiceImplTest.java
+++ b/manager/tm/src/test/java/com/tapdata/tm/task/service/TaskServiceImplTest.java
@@ -25,6 +25,8 @@
 import com.tapdata.tm.commons.externalStorage.ExternalStorageDto;
 import com.tapdata.tm.commons.schema.DataSourceConnectionDto;
 import com.tapdata.tm.commons.schema.MetadataTransformerDto;
+import com.tapdata.tm.commons.schema.bean.ResponseBody;
+import com.tapdata.tm.commons.schema.bean.ValidateDetail;
 import com.tapdata.tm.commons.task.constant.NotifyEnum;
 import com.tapdata.tm.commons.task.dto.*;
 import com.tapdata.tm.commons.task.dto.alarm.AlarmSettingVO;