From 3e0189ffdc061212fe5fbbb1307f640ef2deb7c7 Mon Sep 17 00:00:00 2001 From: Julissa Hernandez Date: Wed, 6 Aug 2025 13:47:39 -0700 Subject: [PATCH 1/5] Added more description and included example graph and query and updated example code --- README.md | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3b81e29..5f6b671 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Graphviz is a commonly used open source graph visualization library that we can + ## Local Build *** **Pre-requisite:** @@ -25,6 +26,15 @@ $ git clone https://github.com/partiql/partiql-graphviz-java.git ## Usage *** +The PartiQL Graphviz visualization tool allows you to easily convert PartiQL queries into visual graph representations. +To use this functionality, first create an instance of the AstToGraph class. You can then convert a PartiQL query string directly to a graph using convertQueryToGraph(String query), +or if you already have a parsed AST statement, use convertAstToGraph(Statement statement). Once you have the graph, you can export it in various formats: save it as a DOT file with convertGraphToDot(graph, filePath), +render it as a PNG image using convertDotToPng(graph, filePath, scale), or create an SVG with convertDotToSvg(graph, filePath, scale). The scale parameter allows you to adjust the size of the output image. +This visualization capability is particularly useful for understanding complex query structures, debugging query issues, or educational purposes to demonstrate how PartiQL parses different query constructs. +The generated visual representation clearly shows the hierarchical structure of the query, including SELECT clauses, FROM sources, WHERE conditions, and other query components with their relationships. + + + ### Creating and Visualizing Graphs NOTE: All the example code is written in java ```java @@ -41,10 +51,12 @@ public class Query { // Define output file paths String dotFilePath = "ast_graph.dot"; String pngFilePath = "ast_graph.png"; + String svgFilePath = "ast_graph.svg"; - // Save the graph in DOT and PNG formats + // Save the graph in DOT, PNG and SVG formats astToGraph.convertGraphToDot(graph, dotFilePath); - astToGraph.convertDotToPng(graph, pngFilePath); + astToGraph.convertDotToPng(graph, pngFilePath, 2.0); + astToGraph.convertDotToSvg(graph, svgFilePath, 2.0); } } ``` @@ -56,17 +68,36 @@ import org.partiql.parser.PartiQLParser; import org.partiql.ast.Statement; // Parse a query to get the AST -PartiQLParser parser = PartiQLParser.standard(); -PartiQLParser.Result parseResult = parser.parse(query); -Statement statement = parseResult.statements.get(0); + PartiQLParser parser = PartiQLParser.standard(); + PartiQLParser.Result parseResult = parser.parse(query); + Statement statement = parseResult.statements.get(0); // Convert the AST to a graph Graph graph = astToGraph.convertAstToGraph(statement); ``` +### Example Query + +``` +Query: SELECT abc FROM t WHERE d +``` + +### Example Graph + +img_1.png = 70x70 +### Future Enhancements +*** + +TODO: +- Implement remaining AST nodes that are currently not handled by the visualization system +- Extend AST visualization to PartiQL plan +- Introduce additional customization options for node appearance, edge styles, and color schemes +- Provide configuration parameters to control visualization verbosity, allowing for more compact graph representations when desired +- Integrate the PartiQL logo into generated visualizations + ## Contributing *** From ea8623c947a1c7b60418f80d6bb20382750be9e9 Mon Sep 17 00:00:00 2001 From: Julissa Hernandez Date: Wed, 6 Aug 2025 14:00:04 -0700 Subject: [PATCH 2/5] Updated Example query to show proper graph --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f6b671..eee558c 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Graph graph = astToGraph.convertAstToGraph(statement); ### Example Query ``` -Query: SELECT abc FROM t WHERE d +Query: SELECT a,b,c FROM t WHERE d ``` ### Example Graph From 923f53c4616e78385feabb82144d2eb12d277930 Mon Sep 17 00:00:00 2001 From: Julissa Hernandez Date: Thu, 7 Aug 2025 12:06:19 -0700 Subject: [PATCH 3/5] Fixed example image and added line breaks and backtiks abd updated TODO and example code to suggesteed changes --- README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index eee558c..74ba95d 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,20 @@ $ git clone https://github.com/partiql/partiql-graphviz-java.git ## Usage *** -The PartiQL Graphviz visualization tool allows you to easily convert PartiQL queries into visual graph representations. -To use this functionality, first create an instance of the AstToGraph class. You can then convert a PartiQL query string directly to a graph using convertQueryToGraph(String query), -or if you already have a parsed AST statement, use convertAstToGraph(Statement statement). Once you have the graph, you can export it in various formats: save it as a DOT file with convertGraphToDot(graph, filePath), -render it as a PNG image using convertDotToPng(graph, filePath, scale), or create an SVG with convertDotToSvg(graph, filePath, scale). The scale parameter allows you to adjust the size of the output image. +The PartiQL Graphviz visualization tool allows you to easily convert PartiQL queries into visual graph representations. + +To use this functionality, first create an instance of the `AstToGraph` class. +You can then convert a PartiQL query string directly to a graph using `convertQueryToGraph(String query)`, +or if you already have a parsed AST statement, use `convertAstToGraph(Statement statement)`. + +Once you have the graph, you can export it in various formats: +- Save it as a DOT file with `convertGraphToDot(graph, filePath)` +- Render it as a PNG image using `convertDotToPng(graph, filePath, scale)` +- Create an SVG with `convertDotToSvg(graph, filePath, scale)` + +The `scale` parameter allows you to adjust the size of the output image. + + This visualization capability is particularly useful for understanding complex query structures, debugging query issues, or educational purposes to demonstrate how PartiQL parses different query constructs. The generated visual representation clearly shows the hierarchical structure of the query, including SELECT clauses, FROM sources, WHERE conditions, and other query components with their relationships. @@ -68,9 +78,9 @@ import org.partiql.parser.PartiQLParser; import org.partiql.ast.Statement; // Parse a query to get the AST - PartiQLParser parser = PartiQLParser.standard(); - PartiQLParser.Result parseResult = parser.parse(query); - Statement statement = parseResult.statements.get(0); +PartiQLParser parser = PartiQLParser.standard(); +PartiQLParser.Result parseResult = parser.parse(query); +Statement statement = parseResult.statements.get(0); // Convert the AST to a graph Graph graph = astToGraph.convertAstToGraph(statement); @@ -83,8 +93,7 @@ Query: SELECT a,b,c FROM t WHERE d ``` ### Example Graph - -img_1.png = 70x70 +![img_2.png](img_2.png) @@ -93,7 +102,7 @@ Query: SELECT a,b,c FROM t WHERE d TODO: - Implement remaining AST nodes that are currently not handled by the visualization system -- Extend AST visualization to PartiQL plan +- Visualization of the PartiQL plan - Introduce additional customization options for node appearance, edge styles, and color schemes - Provide configuration parameters to control visualization verbosity, allowing for more compact graph representations when desired - Integrate the PartiQL logo into generated visualizations From 715e172b71dfc8f2ae3e9a38a7a73fccc2a17d26 Mon Sep 17 00:00:00 2001 From: Julissa Hernandez Date: Thu, 7 Aug 2025 13:23:01 -0700 Subject: [PATCH 4/5] Created Maintenance guide --- LIBRARY_GUIDE.md | 173 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 LIBRARY_GUIDE.md diff --git a/LIBRARY_GUIDE.md b/LIBRARY_GUIDE.md new file mode 100644 index 0000000..9738f23 --- /dev/null +++ b/LIBRARY_GUIDE.md @@ -0,0 +1,173 @@ +# PartiQL Graphviz Visualization Library Maintenance Guide + +This guide provides information for the PartiQL team on how to maintain and extend the PartiQL Graphviz visualization library. + +## How to Add New Nodes + +When adding support for new AST node types, follow these steps: + +1. **Identify the node type**: Determine which PartiQL AST node type you need to add support for. + +2. **Create a conversion method**: Add a new method following the naming pattern `convert[NodeType]ToNode()`. For example: + + ```java + private Node convert[NewNodeType]ToNode([NewNodeType] newNode) { + Node newNodeNode = createNode(newNode).with(label("[NewNodeType]")); + + // Add links to child nodes + // For each child node or property that should be visualized: + newNodeNode = newNodeNode.link(to(convertChildToNode(newNode.getChild())).with(Label.of("childName"))); + + return newNodeNode; + } + ``` + +3. **Update the parent method**: Add a new case to the appropriate switch statement in the parent method that handles this type of node. For example, if adding a new expression type: + + ```java + private Node convertExprToNode(Expr expr) { + return switch (expr) { + // Existing cases... + case [NewExprType] newExprType -> convert[NewExprType]ToNode(newExprType); + default -> throw new IllegalArgumentException("Unsupported expression: " + expr); + }; + } + ``` + +4. **Test the visualization**: Create a test query that uses the new node type and verify that it renders correctly. + +## How to Debug + +When debugging visualization issues: + +1. **Start with simple queries**: Begin with minimal queries that use the specific node type you're working with. + +2. **Use the debugger**: Step through the code using your IDE's debugger to inspect the structure of both the AST and the resulting Graphviz graph. + +3. **Set breakpoints**: Place breakpoints in key methods like `convertQueryToGraph()` to examine how nodes are being processed. + +4. **Inspect object structures**: Use the debugger's variable inspection features to examine the properties of AST nodes and the corresponding Graphviz nodes being created. + +5. **Watch the graph construction**: Step through the code to see how nodes are connected with edges and how the graph is built incrementally. + +6. **Start with simple queries**: Begin with minimal queries that use the specific node type you're working with. + +7. **Incremental testing**: Add complexity to your test queries gradually to isolate issues. + +8. **Add debug labels**: Temporarily add more detailed labels to nodes to show internal state: + + ```java + // Instead of just the node type + Node node = createNode(expr).with(label("ExprOperator: " + expr.getSymbol() + " [details: " + additionalInfo + "]")); + ``` + + + +## How to Think About Visualizing Nodes + +When designing visualizations for AST nodes: + +1. **Hierarchical structure**: Visualize the AST as a top-down hierarchy, with the root node at the top. + +2. **Node labeling**: Use clear, concise labels that convey the node's type and essential information. + +3. **Edge labeling**: Label edges to show the relationship between nodes (e.g., "lhs", "rhs", "condition"). + +4. **Visual consistency**: Maintain consistent styling for similar node types. + +5. **Information density**: Balance between showing enough information and avoiding visual clutter. + +6. **Node grouping**: Consider grouping related nodes (e.g., all items in a SELECT list) under a common parent. + +7. **Special characters**: Remember to escape special characters in labels using the `escapeGraphvizLabel()` method. + +## Common Graphviz Classes and Functions + +### Core Classes + +- **`Graph`**: Represents the entire graph structure. + ```java + Graph g = graph("Ast Graph").directed(); + ``` + +- **`Node`**: Represents a node in the graph. + ```java + Node node = node("nodeName").with(label("Node Label")); + ``` + +### Node Creation and Styling + +- **`createNode(AstNode ast)`**: Creates a node with a unique identifier based on the AST node's class name. + ```java + Node node = createNode(astNode); + ``` + +- **`label(String text)`**: Sets the display label for a node. + ```java + node.with(label("Label Text")); + ``` + +- **`Color`**: Defines colors for nodes and edges. + ```java + node.with(Color.RED); + ``` + +- **`Style`**: Sets styling attributes for nodes. + ```java + node.with(Style.FILLED, Style.lineWidth(2)); + ``` + +### Edge Creation and Styling + +- **`link(Node target)`**: Creates an edge from one node to another. + ```java + sourceNode.link(targetNode); + ``` + +- **`to(Node target)`**: Used with `link()` to create edges with labels. + ```java + sourceNode.link(to(targetNode).with(Label.of("edgeLabel"))); + ``` + +### Graph Rendering + +- **`convertGraphToDot(Graph graph, String path)`**: Saves the graph as a DOT file. + ```java + astToGraph.convertGraphToDot(graph, "output.dot"); + ``` + +- **`convertDotToPng(Graph graph, String path, double scale)`**: Renders the graph as a PNG image. + ```java + astToGraph.convertDotToPng(graph, "output.png", 2.0); + ``` + +- **`convertDotToSvg(Graph graph, String path, double scale)`**: Renders the graph as an SVG image. + ```java + astToGraph.convertDotToSvg(graph, "output.svg", 2.0); + ``` + +### Utility Functions + +- **`escapeGraphvizLabel(String text)`**: Escapes special characters in labels. + ```java + String safeLabel = escapeGraphvizLabel("label"); + ``` + +- **`getIdentifierString(Identifier.Simple simple)`**: Formats identifiers with appropriate quoting. + ```java + String idStr = getIdentifierString(identifier); + ``` + +## Best Practices + +1. **Maintain consistent styling**: Use the predefined color and style constants. + +2. **Handle all node types**: Ensure switch statements have cases for all possible node types. + +3. **Add detailed documentation**: Document new methods with JavaDoc comments. + +4. **Test with complex queries**: Verify that visualizations work correctly with complex, nested queries. + +5. **Consider performance**: For very large ASTs, consider optimizations to improve rendering speed. + +6. **Update tests**: When adding new node types, add corresponding test cases. From 63a8ede4a3c641b6e2625fa8f07adf4014ca51be Mon Sep 17 00:00:00 2001 From: Julissa Hernandez Date: Thu, 7 Aug 2025 16:59:53 -0700 Subject: [PATCH 5/5] Added refernce for Testing and removed best practices and added rational for escape characters --- LIBRARY_GUIDE.md | 50 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/LIBRARY_GUIDE.md b/LIBRARY_GUIDE.md index 9738f23..bc58e35 100644 --- a/LIBRARY_GUIDE.md +++ b/LIBRARY_GUIDE.md @@ -36,6 +36,33 @@ When adding support for new AST node types, follow these steps: 4. **Test the visualization**: Create a test query that uses the new node type and verify that it renders correctly. +### How to Work with Snapshot Testing + +The library uses the [java-snapshot-testing](https://github.com/origin-energy/java-snapshot-testing) framework to perform snapshot testing. This approach allows you to: + +1. Generate a visual representation of a PartiQL query +2. Compare it against a previously saved "snapshot" to detect any changes + +#### Setting Up Snapshot Tests + +1. **Add the JUnit 5 extension**: + ```java + @ExtendWith({SnapshotExtension.class}) + public class AstToQueryTest { + private Expect expect; + // Tests go here + } + ``` + +2. **Create a test method**: + ```java + @Test + public void testIntLiteral() { + Graph graph = new AstToGraph().convertQueryToGraph("12345"); + expect.toMatchSnapshot(graph); + } + ``` + ## How to Debug When debugging visualization issues: @@ -148,7 +175,15 @@ When designing visualizations for AST nodes: ### Utility Functions -- **`escapeGraphvizLabel(String text)`**: Escapes special characters in labels. +- **`escapeGraphvizLabel(String text)`**: Graphviz uses the DOT language to define graphs, which has its own syntax and special characters. + When including text in node or edge labels, certain characters must be escaped to prevent them from being + interpreted as part of the DOT language syntax rather than as literal characters in the label text. + +Use the `escapeGraphvizLabel()` method for any text that might contain special characters, especially when displaying: + +- Operator symbols (`>`, `<`, `=`, etc.) +- User-defined identifiers that might contain special characters + ```java String safeLabel = escapeGraphvizLabel("label"); ``` @@ -158,16 +193,3 @@ When designing visualizations for AST nodes: String idStr = getIdentifierString(identifier); ``` -## Best Practices - -1. **Maintain consistent styling**: Use the predefined color and style constants. - -2. **Handle all node types**: Ensure switch statements have cases for all possible node types. - -3. **Add detailed documentation**: Document new methods with JavaDoc comments. - -4. **Test with complex queries**: Verify that visualizations work correctly with complex, nested queries. - -5. **Consider performance**: For very large ASTs, consider optimizations to improve rendering speed. - -6. **Update tests**: When adding new node types, add corresponding test cases.