Skip to content

Commit 8afcf8b

Browse files
committed
Fix LadybugDB multi-pair COPY syntax by splitting data_flow CSVs
1 parent 7a587cf commit 8afcf8b

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

src/main/java/com/neuvem/java2graph/passes/ExportPass.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public void execute(Java2GraphConfig config, GraphContext context) throws Except
8383
exportMethodDefinitionsCsv(config.getOutCsvDir(), context);
8484
exportFieldsCsv(config.getOutCsvDir(), context);
8585
exportDependsOnCsv(config.getOutCsvDir(), context);
86+
exportParametersCsv(config.getOutCsvDir(), context);
87+
exportVariablesCsv(config.getOutCsvDir(), context);
88+
exportDataFlowCsv(config.getOutCsvDir(), context);
8689
}
8790

8891
if (resolvedDbPath != null) {
@@ -195,6 +198,39 @@ private void exportDependsOnCsv(Path dir, GraphContext context) throws IOExcepti
195198
}
196199
}
197200

201+
private void exportParametersCsv(Path dir, GraphContext context) throws IOException {
202+
try (FileWriter out = new FileWriter(dir.resolve("parameters.csv").toFile());
203+
CSVPrinter printer = new CSVPrinter(out, CSVFormat.Builder.create().setHeader("id", "methodFqn", "name", "typeFqn", "index").build())) {
204+
for (ParameterNode node : context.parameters.values()) {
205+
if (node.getId() != null && !node.getId().isBlank()) {
206+
printer.printRecord(node.getId(), node.getMethodFqn(), node.getName(), node.getTypeFqn(), node.getIndex());
207+
}
208+
}
209+
}
210+
}
211+
212+
private void exportVariablesCsv(Path dir, GraphContext context) throws IOException {
213+
try (FileWriter out = new FileWriter(dir.resolve("variables.csv").toFile());
214+
CSVPrinter printer = new CSVPrinter(out, CSVFormat.Builder.create().setHeader("id", "methodFqn", "name", "typeFqn").build())) {
215+
for (VariableNode node : context.variables.values()) {
216+
if (node.getId() != null && !node.getId().isBlank()) {
217+
printer.printRecord(node.getId(), node.getMethodFqn(), node.getName(), node.getTypeFqn());
218+
}
219+
}
220+
}
221+
}
222+
223+
private void exportDataFlowCsv(Path dir, GraphContext context) throws IOException {
224+
try (FileWriter out = new FileWriter(dir.resolve("data_flow.csv").toFile());
225+
CSVPrinter printer = new CSVPrinter(out, CSVFormat.Builder.create().setHeader("sourceId", "targetId", "flowType").build())) {
226+
for (DataFlowEdge edge : context.dataFlowEdges) {
227+
if (edge.getSourceId() != null && edge.getTargetId() != null) {
228+
printer.printRecord(edge.getSourceId(), edge.getTargetId(), edge.getFlowType());
229+
}
230+
}
231+
}
232+
}
233+
198234
private void exportLadybug(Java2GraphConfig config, GraphContext context) {
199235
Set<String> affectedPaths = new HashSet<>();
200236
if (isIncremental) {
@@ -263,6 +299,9 @@ private void exportLadybug(Java2GraphConfig config, GraphContext context) {
263299
executeOrThrow(conn, "CREATE NODE TABLE Field(id STRING, fqn STRING, name STRING, typeFqn STRING, containingClassFqn STRING, annotations STRING, filePath STRING, PRIMARY KEY (id))");
264300
executeOrThrow(conn, "CREATE REL TABLE DependsOn(FROM Class TO Class, injectionType STRING)");
265301
executeOrThrow(conn, "CREATE REL TABLE HasField(FROM Class TO Field)");
302+
executeOrThrow(conn, "CREATE NODE TABLE Parameter(id STRING, methodFqn STRING, name STRING, typeFqn STRING, index INT64, PRIMARY KEY (id))");
303+
executeOrThrow(conn, "CREATE NODE TABLE Variable(id STRING, methodFqn STRING, name STRING, typeFqn STRING, PRIMARY KEY (id))");
304+
executeOrThrow(conn, "CREATE REL TABLE DataFlow(FROM Variable TO Parameter, FROM Parameter TO Parameter, FROM Field TO Parameter, FROM Variable TO Field, FROM Parameter TO Field, FROM Field TO Field, flowType STRING)");
266305

267306
Path tempDir = Files.createTempDirectory("ladybug_import");
268307

@@ -381,6 +420,60 @@ private void exportLadybug(Java2GraphConfig config, GraphContext context) {
381420
}
382421
}
383422
}
423+
424+
Set<String> paramIds = new HashSet<>();
425+
Set<String> varIds = new HashSet<>();
426+
427+
Path paramsCsv = tempDir.resolve("parameters.csv");
428+
try (FileWriter out = new FileWriter(paramsCsv.toFile());
429+
CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) {
430+
for (ParameterNode node : context.parameters.values()) {
431+
if (node.getId() != null && !node.getId().isBlank()) {
432+
printer.printRecord(node.getId(), node.getMethodFqn(), node.getName(), node.getTypeFqn(), node.getIndex());
433+
paramIds.add(node.getId());
434+
}
435+
}
436+
}
437+
438+
Path varsCsv = tempDir.resolve("variables.csv");
439+
try (FileWriter out = new FileWriter(varsCsv.toFile());
440+
CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) {
441+
for (VariableNode node : context.variables.values()) {
442+
if (node.getId() != null && !node.getId().isBlank()) {
443+
printer.printRecord(node.getId(), node.getMethodFqn(), node.getName(), node.getTypeFqn());
444+
varIds.add(node.getId());
445+
}
446+
}
447+
}
448+
449+
Path dfVP = tempDir.resolve("df_vp.csv");
450+
Path dfPP = tempDir.resolve("df_pp.csv");
451+
Path dfFP = tempDir.resolve("df_fp.csv");
452+
Path dfVF = tempDir.resolve("df_vf.csv");
453+
Path dfPF = tempDir.resolve("df_pf.csv");
454+
Path dfFF = tempDir.resolve("df_ff.csv");
455+
456+
try (
457+
FileWriter fwVP = new FileWriter(dfVP.toFile()); CSVPrinter pVP = new CSVPrinter(fwVP, CSVFormat.DEFAULT);
458+
FileWriter fwPP = new FileWriter(dfPP.toFile()); CSVPrinter pPP = new CSVPrinter(fwPP, CSVFormat.DEFAULT);
459+
FileWriter fwFP = new FileWriter(dfFP.toFile()); CSVPrinter pFP = new CSVPrinter(fwFP, CSVFormat.DEFAULT);
460+
FileWriter fwVF = new FileWriter(dfVF.toFile()); CSVPrinter pVF = new CSVPrinter(fwVF, CSVFormat.DEFAULT);
461+
FileWriter fwPF = new FileWriter(dfPF.toFile()); CSVPrinter pPF = new CSVPrinter(fwPF, CSVFormat.DEFAULT);
462+
FileWriter fwFF = new FileWriter(dfFF.toFile()); CSVPrinter pFF = new CSVPrinter(fwFF, CSVFormat.DEFAULT)
463+
) {
464+
for (DataFlowEdge edge : context.dataFlowEdges) {
465+
String src = edge.getSourceId();
466+
String tgt = edge.getTargetId();
467+
if (src != null && tgt != null) {
468+
if (varIds.contains(src) && paramIds.contains(tgt)) pVP.printRecord(src, tgt, edge.getFlowType());
469+
else if (paramIds.contains(src) && paramIds.contains(tgt)) pPP.printRecord(src, tgt, edge.getFlowType());
470+
else if (fieldIds.contains(src) && paramIds.contains(tgt)) pFP.printRecord(src, tgt, edge.getFlowType());
471+
else if (varIds.contains(src) && fieldIds.contains(tgt)) pVF.printRecord(src, tgt, edge.getFlowType());
472+
else if (paramIds.contains(src) && fieldIds.contains(tgt)) pPF.printRecord(src, tgt, edge.getFlowType());
473+
else if (fieldIds.contains(src) && fieldIds.contains(tgt)) pFF.printRecord(src, tgt, edge.getFlowType());
474+
}
475+
}
476+
}
384477

385478
logger.info("Executing bulk COPY commands...");
386479
executeOrThrow(conn,
@@ -397,6 +490,14 @@ private void exportLadybug(Java2GraphConfig config, GraphContext context) {
397490
executeOrThrow(conn, "COPY Field FROM '" + fieldsCsv.toAbsolutePath().toString() + "' (PARALLEL=FALSE)");
398491
executeOrThrow(conn, "COPY DependsOn FROM '" + dependsOnCsv.toAbsolutePath().toString() + "' (PARALLEL=FALSE)");
399492
executeOrThrow(conn, "COPY HasField FROM '" + hasFieldCsv.toAbsolutePath().toString() + "' (PARALLEL=FALSE)");
493+
executeOrThrow(conn, "COPY Parameter FROM '" + paramsCsv.toAbsolutePath().toString() + "' (PARALLEL=FALSE)");
494+
executeOrThrow(conn, "COPY Variable FROM '" + varsCsv.toAbsolutePath().toString() + "' (PARALLEL=FALSE)");
495+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfVP.toAbsolutePath().toString() + "' (FROM='Variable', TO='Parameter', PARALLEL=FALSE)");
496+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfPP.toAbsolutePath().toString() + "' (FROM='Parameter', TO='Parameter', PARALLEL=FALSE)");
497+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfFP.toAbsolutePath().toString() + "' (FROM='Field', TO='Parameter', PARALLEL=FALSE)");
498+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfVF.toAbsolutePath().toString() + "' (FROM='Variable', TO='Field', PARALLEL=FALSE)");
499+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfPF.toAbsolutePath().toString() + "' (FROM='Parameter', TO='Field', PARALLEL=FALSE)");
500+
executeOrThrow(conn, "COPY DataFlow FROM '" + dfFF.toAbsolutePath().toString() + "' (FROM='Field', TO='Field', PARALLEL=FALSE)");
400501
} else {
401502
logger.info("Performing high-performance incremental updates (Purge-then-Create)...");
402503

0 commit comments

Comments
 (0)