Merged
Conversation
- Add tokio-tungstenite and futures-util dependencies - Implement WebSocketBoltAdapter with AsyncRead/AsyncWrite - Add protocol detection (HTTP GET vs Bolt magic preamble) - Route connections: WebSocket or TCP based on first 4 bytes - Enables Neo4j Browser, Neodash, and other browser tools - Reuses existing Bolt protocol handler for both transports
- Wait up to 120 seconds for cargo run to compile and start - Poll health endpoint every 2 seconds - Show progress updates every 10 seconds - Exit early if process dies or times out
- Add is_procedure_union_query() detection function - Add execute_procedure_union() execution function - Extract procedure names before async calls to avoid Send issues - Export functions from procedures module Part of WebSocket Bolt + Neo4j Browser integration. Enables Neo4j Browser schema sidebar to populate.
- Changes signature from &CypherStatement<'a> to &str - Parses internally before extracting procedure names - Avoids Send trait issues with Rc<RefCell<>> in AST - Drops AST before any async calls This enables the function to be called from async contexts without lifetime/Send conflicts.
…eCall The parser was treating 'CALL ... UNION ALL CALL ...' as a standalone ProcedureCall, which prevented UNION support. Now it looks ahead for UNION keyword and treats it as Query if present. Also added comprehensive debug logging and completed HTTP handler integration for procedure UNION execution. Tests: - CALL db.labels() → 4 records ✓ - CALL db.labels() UNION ALL CALL db.relationshipTypes() → 10 records ✓ - 3-procedure UNION → 22 records ✓ - All 923 unit tests passing ✓
Integrated UNION ALL support into Bolt handler, matching HTTP implementation. Uses same pattern: detect UNION, extract procedure names synchronously, then execute async without lifetimes. Tests via neo4j-driver: - CALL db.labels() → 2 records ✓ - 2-procedure UNION → 4 records ✓ - 3-procedure UNION → 6 records ✓ Both HTTP and Bolt now fully support procedure UNION queries needed for Neo4j Browser schema sidebar!
Neo4j Browser requires several dbms.* procedures during initialization: - dbms.clientConfig() - Returns empty config - dbms.security.showCurrentUser() - Returns stub user - dbms.procedures() - Lists all available procedures - dbms.functions() - Returns empty list (functions not supported) Without these, Browser fails during connection handshake and never displays the schema sidebar, even though db.labels() and db.relationshipTypes() work. Tests: - All 8 procedures callable via Bolt ✓ - db.labels() returns 6 labels ✓ - db.relationshipTypes() returns 10 types ✓ - dbms procedures return stub/empty results ✓
Changed two parse_query() calls to parse_cypher_statement() to properly handle UNION ALL queries. The old parse_query() didn't support UNION syntax. Now UNION queries parse correctly, but still fail at planning stage if they contain unlabeled nodes/relationships (MATCH (n) or MATCH ()-[]->()). This fixes the 'Unexpected tokens after query: UNION ALL' errors but reveals the underlying limitation that we need labeled patterns to determine which tables to query. Progress: - ✅ UNION parsing works - ✅ Procedure calls work (db.labels, db.relationshipTypes, dbms.*) - ❌ Unlabeled MATCH patterns still not supported (separate issue)
Parser now checks for RETURN keyword (in addition to UNION) to route
CALL...YIELD...RETURN queries to the Query parser instead of ProcedureCall.
Also updated get_query_type() to classify CALL with RETURN as Read query.
CALL without RETURN is still QueryType::Call.
Neo4j Browser sends: CALL db.labels() YIELD label RETURN {...} UNION ALL ...
This needs to be treated as a read query, not a procedure call.
Status: Code changes complete but not yet verified working. Next step is to
confirm query type classification with debug logging and verify Browser
sidebar populates.
Related: Need to implement proper read-only procedure checking instead of
assuming CALL with RETURN is always read-only.
- generate_scan() creates Union of all node types when no label specified - Add multi-label scan detection in plan_builder with recursive unwrapping - Add is_multi_label_scan flag to RenderPlan to preserve special columns - Use json_builder for uniform _label, _id, _properties columns in UNION - Add deduplication in json_builder to avoid duplicate node types Enables MATCH (n) RETURN n queries that return heterogeneous nodes.
- Add try_transform_multi_label_row() to detect and transform special columns - Fix find_final_projection() to handle Union plans - Generate proper Neo4j elementId format (Label:id) - Derive legacy id field from actual ID property values Enables proper Neo4j Browser visualization of heterogeneous node results.
- Add return_evaluator.rs for evaluating RETURN clauses on procedure results
- Support aggregation functions: COLLECT, COUNT with distinct
- Support array slicing: [..1000], [5..], [2..10]
- Support map literals and list construction
- Handle Neo4j Browser schema sidebar queries with UNION ALL
Enables Browser queries like:
CALL db.labels() YIELD label RETURN {name:'labels', data:COLLECT(label)[..1000]}
- Fix pattern_comp_users property mapping (name: name, not name: full_name) - Minor handler improvements for query processing
- Document label-less node queries feature - Document RETURN clause evaluation for procedures - Update test statistics
The posts_bench table uses user_id, not author_id. Also fixed property mapping (post_date -> created_at).
- Modified to_render_plan_with_ctx to pass plan_ctx through for
TypedVariable lookup (fixes path variable recognition)
- Added contains_graph_joins() helper to detect GraphJoins wrapped in
Limit/Skip/OrderBy nodes
- Enhanced expand_path_variable() to differentiate VLP vs fixed-hop:
- VLP paths use CTE columns (path_nodes, path_edges, etc.)
- Fixed-hop paths produce tuple('path', start, end, rel)
- Use plan_builder_utils::extract_limit/skip for proper LIMIT handling
Query: MATCH p=()-[r:AUTHORED]->() RETURN p LIMIT 1
Now generates valid SQL instead of 'Unknown identifier p' error
- Add Path struct methods: new(), single_hop(), to_packstream() - Add to_unbound_packstream() for Relationship in Path encoding - Enhance ReturnItemType::Path with component aliases (start, end, rel) - Implement transform_to_path() for fixed-hop paths - Add helper functions: find_node_in_row(), find_relationship_in_row() - Create placeholder nodes/relationships when data unavailable This enables Neo4j Browser to visualize path queries like: MATCH p=()-[r:TYPE]->() RETURN p
- Extract relationship type from composite keys (AUTHORED::User::Post -> AUTHORED) - Infer node labels from composite key components - Fix elementId format for relationships (simpler ID-based format) - Add detailed logging for path transformation debugging Now paths show correct labels (User, Post) and relationship type (AUTHORED) instead of placeholder values. Properties still need schema-based expansion (complex due to denormalized tables).
When RETURN p (path), now automatically expands properties for: - Start node (all schema-mapped properties) - End node (all schema-mapped properties) - Relationship (all schema-mapped properties) This enables full Neo4j Browser visualization with property panels. Implementation: - expand_path_variable() now calls expand_base_table_entity() or expand_cte_entity() for each path component - Properties appear as u.name, u.email, r.post_date in SELECT - Bolt transformer extracts these via transform_to_node/relationship HTTP test shows properties now included in result. Next: Test in Neo4j Browser to verify Bolt path encoding.
- Added comprehensive debug logging in transform_row and find_node_in_row_with_label - Fixed LIKED edge schema: like_date -> liked_at column mapping - Fixed FRIENDS_WITH edge schema: user1_id/user2_id -> user_id_1/user_id_2, since_date -> since Schema mappings now match actual ClickHouse table columns. Issue: Path node properties still not showing in Neo4j Browser. HTTP endpoint shows properties correctly, but Bolt transformer not extracting them. Need to investigate row format discrepancy between HTTP and Bolt responses.
Path queries like MATCH p=(u)-[r]->(po) RETURN p now work and display in Neo4j Browser with correct: - Node labels (User, Post) - Relationship types (AUTHORED) - Graph structure and visualization Known limitation: Node/relationship properties not included in paths yet. Root cause: GraphRel SQL rendering only includes relationship + end node in FROM clause, omitting start node table. Properties would require: 1. Fixing anchor table selection for path queries, OR 2. Adding CTEs to fetch node properties separately, OR 3. Client-side lazy loading (fetch properties on click) For direct node/relationship returns (RETURN n, RETURN r), properties work correctly. Issue only affects path variable returns (RETURN p). This is sufficient for basic Neo4j Browser visualization. Properties can be added in follow-up work.
- Path queries with path variables now prevent SingleTableScan optimization - FK-edge patterns no longer create duplicate JOINs for relationship alias - Start node table correctly included in FROM clause for path queries - Fixes: MATCH p=(u)-[r]->(po) RETURN p now generates correct SQL
… denormalization - Re-enabled property expansion in expand_path_variable() for fixed-hop paths - Added denormalized alias registration for FK-edge patterns in FkEdgeJoin handler - Properties now included in SELECT: u.*, po.*, r.* - Still needs: FK-edge property resolution (r.* should map to po.* columns)
- Modified expand_base_table_entity() to check plan_ctx for FK-edge denormalization - FK-edge relationships now select properties from anchor node table - Example: r.content selects from po.content when r is on po table - Correctly handles task-local QueryContext vs plan_ctx denormalization - Query executes successfully: MATCH p=(u)-[r:AUTHORED]->(po) RETURN p
- Fixed is_path_variable() heuristic to exclude anonymous node aliases (t1, t2, etc) - Anonymous nodes are now correctly registered as Node variables instead of Path - Property expansion now works for all path components (named and anonymous) - Fixed PATTERN_COMP_FOLLOWS schema mapping (removed non-existent follow_date) Result: Path queries like MATCH p=()-[r]->() RETURN p now return all node and relationship properties, enabling full visualization in Neo4j Browser. All 939 unit tests passing.
- Relationships now get unique identity values based on (start_id << 20) | end_id - Previously all relationships had identity=0, causing Neo4j Browser to deduplicate - Now properly displays all relationships in path queries (e.g., 4 edges among 7 nodes) Result: MATCH p=()-[r:AUTHORED]->() RETURN p now visualizes correctly with all unique relationships visible, not collapsed into a single edge.
- Enhanced parse_outgoing() to detect both -> and --> patterns - Enhanced parse_incoming() to detect both <- and <-- patterns - Added parse_double_dash() to detect -- (undirected) patterns - Updated is_start_of_a_relationship() to use all detectors This fixes parser to correctly recognize ()-->() patterns used by Neo4j Browser's 'dot' feature for exploring all relationships. Parser now successfully parses MATCH p=()-->() RETURN p, but planner still needs work to expand to UNION of relationship types.
…patterns The comment stripper was treating '-->' as a line comment (-- followed by >), which caused MATCH p=()-->() RETURN p to be stripped to just MATCH p=(). Fix: - Check for '-->' pattern and treat as relationship, not comment - Check for '<--' pattern by looking at previous character - Add comprehensive tests for relationship patterns This fixes the AST transformation issue where ConnectedPattern was being lost during comment stripping phase. Impact: - Parser now correctly receives ()-->() as ConnectedPattern - Relationship type inference triggered: 'Both nodes untyped, expanding to all 10 relationship types' - However, VLP infrastructure needs label-less node support (next step) Related: Neo4j Browser dot query support
- Handles patterns like ()-->() where both nodes are untyped and multiple relationship types exist - Generates UNION ALL with one branch per relationship type, each processed as typed pattern - Each branch gets unique aliases (a_0, b_0) to avoid plan_ctx conflicts - Registers original aliases (a, b) and branch aliases for proper SQL generation - Path variables (p=()-->()) registered but NOT YET IMPLEMENTED (SQL generation missing) - Works perfectly for queries like: MATCH ()-->() RETURN count(*) - Tested: Returns 26 results across all relationship types Known Limitations: - Path variable support (p=()-->()) requires implementation in SQL generator - Path expansion only works for VLP queries with recursive CTEs currently - Single-hop path variables need inline array construction in SELECT clause TODO: - Implement path variable SQL generation for non-VLP patterns - Refactor to extract common 'disconnected pattern' logic (reduce duplication)
- Added contains_union() helper to detect Union in plan tree - Added Union detection in to_render_plan_with_ctx() - Issue: Union branches are rendered via extract_union() which calls to_render_plan() without plan_ctx - Root cause: extract_union() at line 639 renders Union without plan_ctx - Need different approach: Either add plan_ctx param to extract_union(), or handle Union rendering entirely in to_render_plan_with_ctx() Current status: MATCH p=()-->() RETURN p still fails with 'Unknown identifier p'
Added infrastructure to pass plan_ctx through Union branch rendering:
- Created extract_union_with_ctx() method to bridge plan_ctx
- Added Union handler in to_render_plan_with_ctx() for direct Union nodes
- Updated GraphJoins handler to use extract_union_with_ctx()
Status: Infrastructure complete, but path variables still not working
- Typed patterns: SELECT tuple('fixed_path', 'a', 'b', 't4') AS p ✅
- UNION patterns: SELECT p AS p ❌ (no expansion)
Root cause: Path variable registered in plan_ctx with ORIGINAL aliases (a, b, t3)
but UNION branches use BRANCH aliases (t1_0, t2_0, t3). The tuple expansion
needs to use branch-specific aliases, not original ones.
Next step: Modify path variable expansion in select_builder.rs to detect
UNION context and use branch-specific aliases for tuple construction.
Test:
- MATCH p=(a:User)-[:FOLLOWS]->(b:User) RETURN p → Works ✅
- MATCH p=()-->() RETURN p → Fails (Unknown identifier p) ❌
Added find_graph_rel_for_path() to find actual GraphRel in plan tree and use its connection aliases for path tuple construction. This is critical for UNION branches which use branch-specific aliases (t1_0, t2_0) instead of registered aliases (a, b). Changes: - Added find_graph_rel_for_path() helper in select_builder.rs - Modified expand_path_variable() to try GraphRel lookup first - Falls back to registered aliases if GraphRel not found - Uses String instead of &str for aliases to support both paths Status: Infrastructure complete but path still not expanding - Typed: MATCH p=(a:User)-[:FOLLOWS]->(b:User) RETURN p ✅ Works - UNION: MATCH p=()-->() RETURN p ❌ Still fails Next: Debug why path registration or expansion isn't happening for UNION
Added fallback logic to detect path variables by finding GraphRel in plan tree when path is not registered in plan_ctx. This is needed for UNION patterns where fully untyped patterns (()-->()) don't go through the multi-type UNION expansion that registers path variables. Changes: - Added GraphRel fallback in TableAlias expansion (both with and without plan_ctx) - Simplified path registration in traversal.rs (removed nested conditions) - Creates TypedVariable on-the-fly from GraphRel metadata Status: Still failing - path not being expanded in UNION branches - Log messages not appearing, so code paths aren't being reached - UNION branches show 'SELECT p AS p' instead of tuple expansion - Needs further investigation of rendering flow Next: Debug why fallback code isn't executing despite being in place
THE FIX: Each UNION branch now wraps its GraphRel in a Projection that includes
the path variable in the SELECT list. This makes UNION branches work exactly like
typed patterns.
Root cause analysis:
- Typed patterns: GraphRel → (continues processing) → outer Projection adds path
- UNION patterns: Creates Union(GraphRel branches) → returns early with 'continue'
- Problem: UNION branches were bare GraphRel nodes without Projection
- Solution: Wrap each branch in Projection(GraphRel) with path variable item
Changes in traversal.rs:
- Lines 429-451: Wrap GraphRel in Projection when path_variable is present
- Each branch gets: Projection { items: [TableAlias(p)], input: GraphRel(...) }
- Leverages existing path expansion infrastructure in select_builder.rs
Test results:
- MATCH p=()-->() RETURN p LIMIT 1 → {"p":["fixed_path","t1_3","t2_3","t3"]} ✅
- MATCH p=(a:User)-[:FOLLOWS]->(b:User) RETURN p → Works ✅
- Path variable expansion uses branch-specific aliases (t1_0, t2_0, t3)
This fix leverages the existing standard flow as requested - each UNION branch
now goes through the same Projection→path expansion flow as typed patterns.
Added comprehensive Neo4j Browser setup guide and test script. New files: - NEO4J_BROWSER_SETUP.md: Complete guide for connecting Neo4j Browser to ClickGraph - scripts/test/test_bolt_path_variables.py: Automated test for path variables via Bolt Test results via Bolt protocol: ✅ MATCH p=()-->() RETURN p → Works! Returns proper Path objects ✅ MATCH p=(a:User)-[:FOLLOWS]->(b:User) RETURN p → Works! ✅ Count queries and all basic operations working Neo4j Browser connection: - URL: bolt://localhost:7687 - Auth: None required - Ready for production use! This confirms the path variable fix works end-to-end through the full stack: Query → Planning → Rendering → SQL → Results → Bolt Protocol → Neo4j Browser
…able property expansion - Added Projection handler in plan_builder.rs to pass plan_ctx through when rendering - This enables path variable property expansion in UNION branches - Added diagnostic logging to trace plan rendering flow - Issue: Handler not being invoked as expected - needs debugging of query plan structure - Union may not be nested in GraphJoins.input as expected
… separate query MAJOR REFACTORING to leverage existing standard flow instead of custom logic: Key Insight (from user): Each UNION branch is logically a separate query with its own RETURN. So instead of trying to propagate properties from outer Projection, each branch should have its own Projection that independently expands RETURN p. Changes: - Each UNION branch wrapped in Projection (like separate 'MATCH...RETURN p' queries) - Added Projection handler to to_render_plan_with_ctx() that passes plan_ctx - Enhanced extract_union_with_ctx() with detailed logging to trace Union discovery - Union branches rendered via to_render_plan_with_ctx() to ensure plan_ctx availability Architecture: Union → [Projection(RETURN p) → GraphRel, Projection(RETURN p) → GraphRel, ...] Each Projection independently expands path variable using standard flow. Status: Path tuple returns correctly, but properties still not expanding. Next: Debug why Projection handler with plan_ctx isn't triggering property expansion.
Added WARN-level logging throughout select_builder.rs and plan_builder.rs to trace: - When expand_path_variable() is called - When TableAlias is processed in Projection - Plan_ctx availability at each step - Union rendering flow Key Finding: - Typed patterns: expand_path_variable IS called with plan_ctx ✓ - UNION patterns: expand_path_variable NOT called at all ✗ Root Cause Identified: UNION branches are rendered via standard to_render_plan() (no plan_ctx), not to_render_plan_with_ctx(). This happens because: 1. Query plan: Limit → Union → [Projection branches] 2. Limit.to_render_plan() calls Union.to_render_plan() (no plan_ctx) 3. Union.to_render_plan() calls branch.to_render_plan() (no plan_ctx) 4. Projection.to_render_plan() calls extract_select_items(self, None) ← NO PLAN_CTX! Next: Need different approach that doesn't rely on plan_ctx flow through rendering.
Simplest possible approach: - GraphRel.extract_select_items() adds path tuple if path_variable exists - No plan_ctx needed, no complex expansion logic Implementation: - Modified select_builder.rs GraphRel handler to add path tuple - Removed Projection wrapping from UNION branches in traversal.rs - Added extensive logging to trace execution flow Key Discovery: UNION branch structure: GraphJoins -> Projection -> GraphRel - GraphJoins delegates to Projection.extract_select_items() - Projection processes its own items (just TableAlias(p)) - GraphRel.extract_select_items() is NOT called for branches! Next: Need to make Projection recognize when it should delegate to GraphRel for path variables, or make the path tuple logic work at the Projection level instead.
- Add JSON format for path UNION branches (consistent 4-column schema) - Fix denormalized relationship property expansion via schema lookup - Add unique prefixes (_s_, _e_, _r_) for ClickHouse alias collision - Strip prefixes in Bolt transformer for clean Neo4j Browser display - Support MATCH p=()-->() RETURN p with all relationship types Files modified: - render_plan/plan_builder.rs: Path UNION detection, JSON conversion - render_plan/plan_builder_helpers.rs: convert_path_branches_to_json() - render_plan/select_builder.rs: Denormalized relationship properties - server/bolt_protocol/result_transformer.rs: JSON parsing, prefix stripping
- Add Path UNION query support (Neo4j Browser dot feature) - Update test status (936/936 passing) - Mark feature as complete with full architectural details
There was a problem hiding this comment.
Pull request overview
This PR targets improved Neo4j Browser compatibility (especially Bolt/WebSocket transport and Neo4j “dot” exploration queries), expands path/node query support via UNION-based planning/rendering, and adds procedure RETURN-clause evaluation so Neo4j Browser metadata queries work.
Changes:
- Add WebSocket transport detection on the Bolt port and a WebSocket→AsyncRead/AsyncWrite adapter for Bolt.
- Expand support for untyped node/path exploration queries using UNION rendering and JSON/property formatting for Neo4j Browser.
- Add procedure-only query handling improvements (including UNION of procedures) and a RETURN-clause evaluator for procedure results; update docs/scripts/deps accordingly.
Reviewed changes
Copilot reviewed 42 out of 44 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/server/mod.rs | Detects WebSocket vs raw TCP on the Bolt listener and routes to the appropriate transport handler. |
| src/server/handlers.rs | Adds procedure-only UNION routing for HTTP query handler. |
| src/server/bolt_protocol/websocket.rs | New WebSocket transport adapter implementing AsyncRead/AsyncWrite for Bolt over WebSocket. |
| src/server/bolt_protocol/result_transformer.rs | Adds Path transformation and multi-label row handling for Neo4j-compatible Bolt results. |
| src/server/bolt_protocol/mod.rs | Exposes the new websocket module. |
| src/server/bolt_protocol/handler.rs | Adds procedure-only UNION/RETURN evaluation support in Bolt execution path. |
| src/server/bolt_protocol/graph_objects.rs | Adds Packstream encoding support for Path and unbound relationships. |
| src/render_plan/select_builder.rs | Extends SELECT extraction for path variables and denormalized/FK-edge property expansion. |
| src/render_plan/plan_builder_utils.rs | Adds/threads is_multi_label_scan flag default in a render-plan builder path. |
| src/render_plan/plan_builder_helpers.rs | Adds helper to normalize path-UNION branches into consistent JSON columns. |
| src/render_plan/plan_builder.rs | Adds multi-label scan + path-UNION special-case rendering and introduces ctx-aware UNION rendering. |
| src/render_plan/mod.rs | Extends RenderPlan with is_multi_label_scan marker to preserve special SELECT columns. |
| src/render_plan/join_builder.rs | Avoids duplicate JOIN emission for FK-edge/denormalized relationship patterns. |
| src/query_planner/plan_ctx/table_ctx.rs | Refines heuristic detection for path variables vs anonymous node aliases. |
| src/query_planner/plan_ctx/mod.rs | Adds logging and path-variable heuristic registration in PlanCtx insertion. |
| src/query_planner/mod.rs | Adjusts query-type classification for CALL with/without RETURN. |
| src/query_planner/logical_plan/plan_builder.rs | Adds additional logging around MATCH/path patterns. |
| src/query_planner/logical_plan/match_clause/view_scan.rs | Marks relationships as denormalized when relationship table matches a node table. |
| src/query_planner/logical_plan/match_clause/traversal.rs | Adds UNION expansion for fully-untyped multi-type relationships and supports anonymous nodes. |
| src/query_planner/logical_plan/match_clause/helpers.rs | Generates a UNION of ViewScans for label-less node scans (MATCH (n) RETURN n). |
| src/query_planner/analyzer/match_type_inference.rs | Expands relationship inference for both-untyped nodes to all relationship types (UNION ALL). |
| src/query_planner/analyzer/graph_join/inference.rs | Registers denormalized aliases for FK-edges and disables SingleTableScan optimization when returning paths. |
| src/procedures/return_evaluator.rs | New module to evaluate RETURN clauses over procedure results (aggregation/slicing). |
| src/procedures/mod.rs | Registers dbms.* stubs and re-exports procedure helpers/return evaluator. |
| src/procedures/executor.rs | Adds helpers for procedure-only statement detection, UNION execution, and RETURN evaluation. |
| src/procedures/dbms_stubs.rs | Adds stub implementations required by Neo4j Browser. |
| src/procedures/db_relationship_types.rs | Deduplicates/normalizes relationship type names (handles composite keys). |
| src/procedures/db_labels.rs | Deduplicates/normalizes label names (handles qualified keys). |
| src/open_cypher_parser/path_pattern.rs | Adds parsing support for --, <--, --> relationship patterns. |
| src/open_cypher_parser/mod.rs | Adjusts statement parsing to distinguish standalone CALL vs CALL-with-RETURN/UNION. |
| src/open_cypher_parser/common.rs | Updates comment stripping to avoid treating some relationship patterns as comments. |
| src/open_cypher_parser/call_clause.rs | Adds parsing support for YIELD in CALL clauses. |
| src/open_cypher_parser/ast.rs | Extends CallClause AST to include optional YIELD items. |
| src/clickhouse_query_generator/multi_type_vlp_joins.rs | Switches JSON property serialization to type-preserving JSON builder helper. |
| src/clickhouse_query_generator/mod.rs | Exposes new json_builder utilities. |
| src/clickhouse_query_generator/json_builder.rs | New helper for generating type-preserving JSON SQL and multi-type UNION SQL. |
| scripts/test/test_bolt_path_variables.py | Adds a manual Bolt test for path-variable queries via neo4j-driver. |
| scripts/test/quick_neo4j_test.sh | Adds a quick end-to-end script to run ClickGraph + Neo4j Browser smoke checks. |
| scripts/server/start_server_background.sh | Adds a Linux background server launcher script with configurable env. |
| benchmarks/social_network/schemas/social_benchmark.yaml | Updates benchmark schema mappings for certain relationships/properties. |
| STATUS.md | Updates project status and highlights new Neo4j compatibility features. |
| Cargo.toml | Adds tokio-tungstenite and futures-util dependencies. |
| Cargo.lock | Locks new dependency graph for WebSocket support. |
| CHANGELOG.md | Documents Neo4j Browser compatibility features and procedure RETURN evaluation. |
Comments suppressed due to low confidence (1)
src/open_cypher_parser/common.rs:94
strip_commentsstill treats plain--as a line comment unless it’s-->or<--. With the new parser support for undirected patterns (--), queries likeMATCH p=()--() RETURN pwill be truncated as a comment (--(). Consider also exempting--when it’s followed by a relationship continuation (e.g., next non-whitespace char is(or[), or drop--comment support in favor of Cypher’s//and/* */to avoid ambiguity.
// Check for line comment (-- or //)
// BUT: `-->` and `<--` are NOT comments (they're Cypher relationship patterns!)
if ch == '-' && chars.peek() == Some(&'-') {
// Peek ahead to check if this is `-->` or part of `<--` (relationship patterns, not comments)
let mut lookahead = chars.clone();
lookahead.next(); // skip second '-'
// Check for `-->` (outgoing relationship)
if lookahead.peek() == Some(&'>') {
result.push(ch);
continue;
}
// Check if previous character was `<` (making this `<--` incoming relationship)
// We already pushed the `<`, so check the last char in result
if result.chars().last() == Some('<') {
result.push(ch);
continue;
}
// It's actually a `--` comment
chars.next(); // consume second '-'
// Skip until newline
for c in chars.by_ref() {
if c == '\n' {
result.push('\n'); // preserve newline
break;
}
}
continue;
}
- WebSocket Close frame returns EOF for graceful disconnect (websocket.rs) - Downgrade info/warn logs to trace/debug in hot paths (result_transformer.rs, select_builder.rs) - Fix AUTHORED from_id: user_id -> author_id (social_benchmark.yaml) - Fix LIKED like_date mapping (social_benchmark.yaml) - Update tests for new untyped pattern behavior
genezhang
added a commit
that referenced
this pull request
Feb 5, 2026
- AUTHORED: from_id author_id -> user_id (matches actual ClickHouse column) - LIKED: property like_date -> liked_at (matches actual column name) These schema mismatches were causing 'Identifier cannot be resolved' errors in path queries. Schema was previously fixed in 55c0790 but accidentally reverted in PR #64 (websocket bolt support).
genezhang
added a commit
that referenced
this pull request
Feb 17, 2026
Issue #1 (Neo4j Desktop WebSocket connection) was fixed on Feb 2, 2026 in PR #64 which added full WebSocket Bolt transport support. Active issues: 2 (was 3) - Shortest path performance on dense graphs - Aggregation semantics on empty results Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces major new features and compatibility improvements for Neo4j Browser integration, especially around path and node queries, as well as enhanced RETURN clause support for procedures. It also updates test scripts, dependency management, and social network benchmark schemas for better accuracy and reliability. The most important changes are summarized below:
Neo4j Browser Compatibility & Query Features:
MATCH p=()-->() RETURN pto work in Neo4j Browser by generating a UNION ALL across all relationship types with consistent JSON property formatting. This ensures visualization of all connected edges with properties in the Browser. [1] [2]MATCH (n) RETURN nto return all node types via UNION ALL, making the Neo4j Browser "dot" exploration feature fully functional. [1] [2]Testing & Developer Tooling:
scripts/test/quick_neo4j_test.sh) to automate setup, execution, and validation of Neo4j Browser compatibility with ClickGraph, including health checks, data setup, and container orchestration.scripts/test/test_bolt_path_variables.py) to validate Bolt protocol support for path variable queries, ensuring correct operation of UNION path and typed path queries through Neo4j Browser.Benchmark & Schema Corrections:
name,created_at,liked_at, composite keys, and property names). [1] [2] [3] [4]Dependency Management:
tokio-tungsteniteandfutures-utilas dependencies to support async WebSocket/Bolt protocol features.Documentation & Status Updates:
STATUS.mdandCHANGELOG.mdto reflect new features, improved test pass rates, and removal of regression warnings, providing a clear summary of current capabilities and recent progress. [1] [2]These changes collectively ensure robust Neo4j Browser compatibility, improve developer experience, and enhance test coverage and schema correctness.