package jnpf.dmsMapper; import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.Configuration; import org.junit.jupiter.api.Test; import java.io.InputStream; import java.util.*; import static org.junit.jupiter.api.Assertions.*; class DmsApprovedDisableMapperXmlTest { @Test void nativeApplicationApplicantUsesEachFormsPersistedField() throws Exception { Configuration c=parse("DmsDisableApplicationMapper"); for (String operation : List.of("yichexiao", "yishixiao")) { String query=sql(c,"DmsDisableApplicationMapper","application",Map.of("operation",operation)); assertFalse(query.contains("f_creator_user_id")); assertTrue(query.contains((operation.equals("yichexiao") ? "tiyi_ren_id" : "shenqing_ren_id") + " creator_user_id")); assertTrue(c.getResultMap("jnpf.dmsMapper.DmsDisableApplicationMapper.Occupancy").getResultMappings().stream() .anyMatch(r -> "creator_user_id".equals(r.getColumn()) && "creatorUserId".equals(r.getProperty()))); String fixtureDir=System.getProperty("dms.occupancySqlDir"); if (fixtureDir != null) { java.nio.file.Path dir=java.nio.file.Paths.get(fixtureDir); java.nio.file.Files.createDirectories(dir); java.nio.file.Files.writeString(dir.resolve("application-"+operation+".sql"),query); } } } @Test void discoveryUsesStableTenantTaskOperationAndApplicationCursor() throws Exception { Configuration c=parse("DmsApprovedDisableMapper"); Map args=new HashMap<>();args.put("limit",100);args.put("after",null); String first=sql(c,"DmsApprovedDisableMapper","approvedApplications",args); assertFalse(first.contains("OFFSET"));assertFalse(first.contains(">")); assertTrue(first.contains("NOT EXISTS")); assertTrue(first.contains("ORDER BY COALESCE(a.tenant_id,''),COALESCE(a.task_id,''),a.operation,a.application_id LIMIT ?")); args.put("after",Map.of("tenantId","tenant","taskId","task","operation","yichexiao","applicationId","app")); org.apache.ibatis.mapping.BoundSql bound=c.getMappedStatement("jnpf.dmsMapper.DmsApprovedDisableMapper.approvedApplications").getBoundSql(args); assertTrue(bound.getSql().contains("> (COALESCE(")); assertEquals(List.of("after.tenantId","after.taskId","after.operation","after.applicationId","limit"), bound.getParameterMappings().stream().map(org.apache.ibatis.mapping.ParameterMapping::getProperty).toList()); } Configuration parse(String mapper) throws Exception { Configuration c=new Configuration();String resource="mapper/"+mapper+".xml"; try(InputStream in=Resources.getResourceAsStream(resource)){new XMLMapperBuilder(in,c,resource,c.getSqlFragments()).parse();}return c; } String sql(Configuration c,String mapper,String method,Map args){ return c.getMappedStatement("jnpf.dmsMapper."+mapper+"."+method).getBoundSql(args).getSql().replaceAll("\\s+"," "); } @Test void bothNativeBranchesAreBoundWithoutRawTableSubstitution() throws Exception { String name="DmsApprovedDisableMapper";Configuration c=parse(name); for(String op:List.of("yichexiao","yishixiao")){ Map args=new HashMap<>();args.put("operation",op); String s=sql(c,name,"nativeRows",args); assertTrue(s.contains(op.equals("yichexiao")?"dms_wenjian_chexiao_tiyi":"dms_wenjian_shixiao_shenqing")); assertTrue(s.contains("m.f_flow_state=2"));assertTrue(s.contains("FOR UPDATE OF m,c")); } assertTrue(c.getResultMap("jnpf.dmsMapper.DmsApprovedDisableMapper.Request").getResultMappings().stream() .anyMatch(r->"business_version_id".equals(r.getColumn())&&"businessVersionId".equals(r.getProperty()))); String target=sql(c,name,"validateTarget",new HashMap<>()); assertTrue(target.contains("z.wenjian_leixing='zhuwenjian'"));assertTrue(target.contains("z.biz_status='effective'")); String candidate=sql(c,name,"candidateExists",new HashMap<>()); assertTrue(candidate.contains("fresh.wenjian_leixing='zhuwenjian'"));assertTrue(candidate.contains("b.status='APPLIED'")); assertTrue(candidate.contains("b.activated_at<=CURRENT_TIMESTAMP")); } @Test void fixedOccupancyRetainsReturnedAndRequiresRealUnsuccessfulEnd() throws Exception { Configuration c=parse("DmsDisableApplicationMapper"); String s=sql(c,"DmsDisableApplicationMapper","pendingForFile",new HashMap<>()); assertTrue(s.contains("dms_file_operation_occupancies")); assertFalse(s.contains("dms_wenjian_chexiao_tiyi")); assertFalse(s.contains("UNION ALL")); assertTrue(s.contains("g.zhu_wenjian_id= o.file_id")); assertTrue(s.contains("g.guanlian_wenjian_id=z.f_id")); assertTrue(s.contains("g.guanxi_leixing='jilu'")); assertFalse(s.contains("wenjian_mulu_id")); assertTrue(s.contains("o.active=true")); assertFalse(s.contains("workflow_task")); for (String op:List.of("yichexiao","yishixiao")) { String rows=sql(c,"DmsDisableApplicationMapper","applicationFiles",Map.of("operation",op)); assertTrue(rows.contains("z.wenjian_leixing='zhuwenjian'")); } for (String method:List.of("legacyApplicationsForFile","legacyApplicationsForDocument")) { String legacy=sql(c,"DmsDisableApplicationMapper",method,new HashMap<>()); assertFalse(legacy.contains("workflow_task")); assertTrue(legacy.contains("g.zhu_wenjian_id= a.file_id")); assertFalse(legacy.contains("wenjian_mulu_id")); } String conflict=sql(c,"DmsDisableApplicationMapper","conflictingFiles",Map.of("fileIds",List.of("f1","f2"))); assertTrue(conflict.contains("o.task_id<>?"));assertFalse(conflict.contains("o.operation=")); String release=sql(c,"DmsDisableApplicationMapper","releaseFile",new HashMap<>()); assertTrue(release.contains("task_id=? AND operation=? AND file_id=?")); String fixtureDir=System.getProperty("dms.occupancySqlDir"); if (fixtureDir!=null) { Map args=new HashMap<>();args.put("tenantId","tenant");args.put("fileId","record"); args.put("taskId","own");args.put("operation","yichexiao");args.put("fileIds",List.of("main")); args.put("applicationId","application");args.put("flowId","flow");args.put("folderId","folder"); args.put("documentId",UUID.fromString("00000000-0000-0000-0000-000000000001")); java.nio.file.Path dir=java.nio.file.Paths.get(fixtureDir);java.nio.file.Files.createDirectories(dir); for(String method:List.of("pendingForFile","pendingForDocument","conflictingFiles","selectedFiles","releaseFile","releaseTask","occupy","application","applicationFiles","legacyApplicationsForFile")) { org.apache.ibatis.mapping.BoundSql bound=c.getMappedStatement("jnpf.dmsMapper.DmsDisableApplicationMapper."+method).getBoundSql(args); String rendered=bound.getSql(); for(org.apache.ibatis.mapping.ParameterMapping mapping:bound.getParameterMappings()) { String prop=mapping.getProperty();Object value=bound.hasAdditionalParameter(prop)?bound.getAdditionalParameter(prop):args.get(prop); String literal=value==null?"NULL":"'"+value.toString().replace("'","''")+"'"; rendered=rendered.replaceFirst("\\?",java.util.regex.Matcher.quoteReplacement(literal)); } java.nio.file.Files.writeString(dir.resolve(method+".sql"),rendered.replace("public.","pg_temp.")); } } } @Test void unifiedProgressSqlUsesSharedItemsAndBatchLease() throws Exception { Configuration c=parse("DmsApprovedDisableMapper"),b=parse("DmsApprovedBatchMapper"); String candidates=sql(b,"DmsApprovedBatchMapper","retryCandidates",Map.of("includeDisable",false)); assertTrue(candidates.contains("audit_type IN ('xinzeng_shenhe','xiuding_shenhe')")); assertFalse(sql(b,"DmsApprovedBatchMapper","retryCandidates",Map.of("includeDisable",true)).contains("audit_type IN")); String dirName=System.getProperty("dms.unifiedSqlDir"); Map args=new HashMap<>(); args.put("id","10000000-0000-0000-0000-000000000002");args.put("batchId","10000000-0000-0000-0000-000000000001"); args.put("tenantId","0");args.put("flowId","fixture-flow");args.put("taskId","fixture-task"); args.put("auditId","fixture-application");args.put("auditType","chexiao_shenqing"); args.put("operation","yichexiao");args.put("sourceRowId","fixture-row");args.put("fileId","fixture-file"); args.put("businessVersionId","fixture-version");args.put("sourceFileId","new-file");args.put("sourceVersionId","new-version"); args.put("documentId","10000000-0000-0000-0000-000000000003");args.put("fileVersionId","10000000-0000-0000-0000-000000000004"); args.put("folderId","10000000-0000-0000-0000-000000000005");args.put("actorId","fixture-actor"); args.put("scheduledAt","2020-01-01T00:00:00Z");args.put("approvedAt","2020-01-01T00:00:00Z"); args.put("sourceDigest","a".repeat(64));args.put("status","WAITING");args.put("leaseToken","fixture-lease"); args.put("token","fixture-lease");args.put("delay",60);args.put("includeDisable",false); for (String method:List.of("enqueue","lock","dueItems","refreshProgress")) { String query=sql(c,"DmsApprovedDisableMapper",method,args); assertFalse(query.contains("dms_approved_file_disables")); if(dirName!=null) { Map values=new HashMap<>(args); if(method.equals("refreshProgress"))values.put("id",args.get("batchId")); dump(c,"DmsApprovedDisableMapper",method,values,dirName,method); } } if(dirName!=null) { args.put("id",args.get("batchId")); for(String method:List.of("insertBatch","claim","finish","retryCandidates")) dump(b,"DmsApprovedBatchMapper",method,args,dirName,method); args.put("error","fixture-row-failed");dump(b,"DmsApprovedBatchMapper","finish",args,dirName,"finishError"); args.put("includeDisable",true);dump(b,"DmsApprovedBatchMapper","retryCandidates",args,dirName,"allCandidates"); } } void dump(Configuration c,String mapper,String method,Map args,String dir,String filename) throws Exception { org.apache.ibatis.mapping.BoundSql bound=c.getMappedStatement("jnpf.dmsMapper."+mapper+"."+method).getBoundSql(args); String rendered=bound.getSql(); for(org.apache.ibatis.mapping.ParameterMapping mapping:bound.getParameterMappings()) { Object value=args.get(mapping.getProperty()); String literal=value==null?"NULL":value instanceof Number?value.toString():"'"+value.toString().replace("'","''")+"'"; rendered=rendered.replaceFirst("\\?",java.util.regex.Matcher.quoteReplacement(literal)); } java.nio.file.Path path=java.nio.file.Paths.get(dir);java.nio.file.Files.createDirectories(path); java.nio.file.Files.writeString(path.resolve(filename+".sql"),rendered.replace("public.","pg_temp.")); } @Test void disableAndOccupancyMappersNeverAccessFileCenterTables() throws Exception { for (String mapper:List.of("DmsApprovedDisableMapper","DmsDisableApplicationMapper")) { try(InputStream in=Resources.getResourceAsStream("mapper/"+mapper+".xml")) { String xml=new String(in.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); for (String center:List.of("dms_documents","dms_folders","dms_file_versions","dms_version_states")) assertFalse(xml.contains(center), mapper+" must use DMS center services, not "+center); } } } }