From d1d08b94e3068ff9e2a57540a145d290551170ff Mon Sep 17 00:00:00 2001 From: Gisli Magnusson Date: Fri, 8 May 2026 15:41:05 +0000 Subject: [PATCH] fix(ENGKNOW-3472): include meta sources in query fingerprinting --- .../scala/gorsat/process/GorPrePipe.scala | 2 +- .../java/gorsat/Script/UTestSignature.java | 34 +++++++++++++++++++ .../gorsat/Utilities/UTestGorPrePipe.scala | 8 +++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/gortools/src/main/scala/gorsat/process/GorPrePipe.scala b/gortools/src/main/scala/gorsat/process/GorPrePipe.scala index 3a181305..41c75dd8 100644 --- a/gortools/src/main/scala/gorsat/process/GorPrePipe.scala +++ b/gortools/src/main/scala/gorsat/process/GorPrePipe.scala @@ -45,7 +45,7 @@ object GorPrePipe { val availNorCommands: Array[String] = GorPipeCommands.getNorCommands ++ GorInputSources.getInputSources private val supportedGorSQLFileEndings = Array[String](".json",".csv",".tsv",".gor",".gorz",".gor.gz",".gord",".txt",".vcf",".bgen",".parquet",".adam",".mt",".xml") - private val commandsContainingInputSources = Array[String]("PARALLEL", "GOR","NOR","SPARK","MAP","MULTIMAP","INSET","MERGE","JOIN","LEFTJOIN","VARJOIN","GORIF", "NORIF", "EXEC"/*,"CSVSEL","CSVCC","GTGEN"*/) + private val commandsContainingInputSources = Array[String]("PARALLEL", "GOR","NOR","SPARK","MAP","MULTIMAP","INSET","MERGE","JOIN","LEFTJOIN","VARJOIN","GORIF", "NORIF", "META", "EXEC"/*,"CSVSEL","CSVCC","GTGEN"*/) val gorpred = (p: String) => supportedGorSQLFileEndings.map(e => p.toLowerCase.endsWith(e)).reduce((a,b) => a || b) private def getCommandArgument(command: String) : Option[CommandArguments] = { diff --git a/gortools/src/test/java/gorsat/Script/UTestSignature.java b/gortools/src/test/java/gorsat/Script/UTestSignature.java index b9eea927..c0173e1c 100644 --- a/gortools/src/test/java/gorsat/Script/UTestSignature.java +++ b/gortools/src/test/java/gorsat/Script/UTestSignature.java @@ -15,6 +15,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.Arrays; public class UTestSignature { @@ -31,6 +32,17 @@ public void setUp() { GorInputSources.register(); } + private String extractSingleValue(String output) { + var lines = Arrays.stream(output.split("\n")) + .map(String::trim) + .filter(line -> !line.isEmpty()) + .toArray(String[]::new); + + Assert.assertEquals("Expected a header row and one data row", 2, lines.length); + var values = lines[1].split("\t"); + return values[values.length - 1]; + } + @Test public void testQuerySignatureAfterUpdate() throws IOException, InterruptedException { var cachePath = workPath.resolve("cache"); @@ -50,6 +62,28 @@ public void testQuerySignatureAfterUpdate() throws IOException, InterruptedExcep Assert.assertEquals(3, res.length); } + @Test + public void testQuerySignatureAfterUpdateWithMetaVirtualRelation() throws IOException { + var cachePath = workPath.resolve("cache"); + Files.createDirectory(cachePath); + + var dataPath = workPath.resolve("data_meta.gor"); + Files.writeString(dataPath, "#Chrom\tPos\nchr1\t1\n"); + + var query = "create meta_size = meta " + dataPath + + " | where source='FILE' and name='SIZE' | rename value file_size | select file_size; nor [meta_size]"; + + var before = extractSingleValue(TestUtils.runGorPipe(query, workPath.toString(), cachePath.toString(), false, "", null)); + Assert.assertEquals(String.valueOf(Files.size(dataPath)), before); + + Files.writeString(dataPath, "chr1\t2\n", StandardOpenOption.APPEND); + + var after = extractSingleValue(TestUtils.runGorPipe(query, workPath.toString(), cachePath.toString(), false, "", null)); + Assert.assertEquals("META virtual relation should be invalidated when the source file size changes", + String.valueOf(Files.size(dataPath)), after); + Assert.assertNotEquals("META virtual relation should not reuse stale cached results", before, after); + } + @Test public void testQuerySignatureAfterUpdateWithLink() throws IOException, InterruptedException { var cachePath = workPath.resolve("cache"); diff --git a/gortools/src/test/scala/gorsat/Utilities/UTestGorPrePipe.scala b/gortools/src/test/scala/gorsat/Utilities/UTestGorPrePipe.scala index 4a29356d..194b39da 100644 --- a/gortools/src/test/scala/gorsat/Utilities/UTestGorPrePipe.scala +++ b/gortools/src/test/scala/gorsat/Utilities/UTestGorPrePipe.scala @@ -92,6 +92,14 @@ class UTestGorPrePipe extends AnyFunSuite with BeforeAndAfterAll { assert(result.head == "../tests/data/gor/dbsnp_test.gorz") } + test("Get used file from meta query") { + val query = "meta ../tests/data/gor/dbsnp_test.gorz | where source='FILE' and name='SIZE'" + val result = process.GorPrePipe.getUsedFiles(query, session) + + assert(result.length == 1) + assert(result.head == "../tests/data/gor/dbsnp_test.gorz") + } + test("Get used file from gor query with join") { val query = "nor ../tests/data/gor/dbsnp_test.gorz | join -snpsnp multicolumns.gor" val result = process.GorPrePipe.getUsedFiles(query, session)