Skip to content

Conversation

@xav-db
Copy link
Member

@xav-db xav-db commented Feb 6, 2026

Greptile Overview

Greptile Summary

  • Updates CLI/container naming logic and instance existence detection to use centralized hyphenated compose naming.
  • Refactors core upsert logic (nodes/edges/vectors) to use fallible serialization and (for edges) DB lookup by (from_node, label, to_node) rather than iterator content; adds extensive traversal upsert tests.
  • Extends HelixQL codegen + validation to support WHERE traversals with prefix steps before property access (issue bug (hql): WHERE(_::ToN::ID::EQ(...)) Causes Rust Codegen Failure #847) and maps Type::Count to I64.
  • Adds new hql-tests fixture for traversal property access WHERE regressions and bumps crate versions/lockfiles.

Important Files Changed

Filename Overview
Cargo.lock Lockfile updated due to crate version bumps; no reviewable logic changes.
helix-cli/Cargo.toml Bumps helix-cli version from 2.2.7 to 2.2.8.
helix-cli/src/commands/push.rs Updates displayed container name to hyphenated format; relies on DockerManager naming (OK).
helix-cli/src/docker.rs Aligns instance existence check with centralized naming by using container_name() and exact match.
helix-db/Cargo.toml Bumps helix-db version from 1.2.7 to 1.2.8.
helix-db/src/helix_engine/tests/traversal_tests/upsert_tests.rs Expands upsert traversal tests, including regression coverage for edge upsert ignoring iterator content.
helix-db/src/helix_engine/traversal_core/ops/util/upsert.rs Refactors upsert adapters to use fallible serialization and new edge lookup by (from,label,to); introduces new DuplicateKey mapping behavior reliance.
helix-db/src/helix_engine/types.rs Adds EncodeError and more granular heed error mapping, but removes KeyExist->DuplicateKey mapping (regression for unique index handling).
helix-db/src/helixc/analyzer/methods/traversal_validation.rs Adds validation mapping for Type::Count to I64 field type.
helix-db/src/helixc/generator/traversal_steps.rs Adds special-case codegen for WHERE traversals with prefix steps before property/reserved property access; needs care but addresses issue #847 tests.
hql-tests/Cargo.lock HQL tests lockfile updated; no direct logic changes.
hql-tests/tests/where_traversal_property_access/helix.toml Adds new hql-tests fixture configuration for traversal property access WHERE cases.
hql-tests/tests/where_traversal_property_access/queries.hx Adds regression queries for WHERE clauses with traversal prefix steps before property/reserved property access (issue #847).
hql-tests/tests/where_traversal_property_access/schema.hx Adds schema for new traversal property access WHERE test fixture.

Sequence Diagram

sequenceDiagram
    participant CLI as helix-cli
    participant Docker as DockerManager
    participant Engine as helix-db traversal engine
    participant LMDB as LMDB/heed

    CLI->>Docker: push/start local instance
    Docker->>Docker: compose_project_name() / container_name()
    Docker-->>CLI: container name used for status + display

    CLI->>Docker: instance_exists(instance)
    Docker->>Docker: get_project_status()
    Docker-->>CLI: true/false based on exact container name match

    CLI->>Engine: run traversal with UpsertE/UpsertN
    Engine->>LMDB: upsert_n: serialize props, update secondary indexes
    Engine->>LMDB: upsert_e: lookup existing edge by (from,label,to)
    alt edge exists
        Engine->>LMDB: update edge bytes in edges_db
    else new edge
        Engine->>LMDB: append edge + update out_edges_db/in_edges_db
    end

    Engine->>Engine: map heed errors -> GraphError
    note over Engine,LMDB: KeyExist should map to DuplicateKey for unique indexes
Loading

dependabot bot and others added 15 commits February 3, 2026 19:20
Bumps the cargo group with 1 update in the / directory: [bytes](https://github.com/tokio-rs/bytes).
Bumps the cargo group with 1 update in the /hql-tests directory: [bytes](https://github.com/tokio-rs/bytes).


Updates `bytes` from 1.10.0 to 1.11.1
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](tokio-rs/bytes@v1.10.0...v1.11.1)

Updates `bytes` from 1.10.1 to 1.11.1
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](tokio-rs/bytes@v1.10.0...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
  dependency-group: cargo
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <[email protected]>
UpsertE was incorrectly using the first edge from the source iterator
instead of looking up edges by the specified from_node/to_node parameters.

Changes:
- Modified upsert_e to query out_edges_db directly using from_node +
  to_node + label to find existing edges
- Source iterator content is now ignored for edge lookup
- Added regression tests for issue #850
Bumps the cargo group with 1 update in the / directory:
[bytes](https://github.com/tokio-rs/bytes).
Bumps the cargo group with 1 update in the /hql-tests directory:
[bytes](https://github.com/tokio-rs/bytes).

Updates `bytes` from 1.10.0 to 1.11.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/releases">bytes's
releases</a>.</em></p>
<blockquote>
<h2>Bytes v1.11.1</h2>
<h1>1.11.1 (February 3rd, 2026)</h1>
<ul>
<li>Fix integer overflow in <code>BytesMut::reserve</code></li>
</ul>
<h2>Bytes v1.11.0</h2>
<h1>1.11.0 (November 14th, 2025)</h1>
<ul>
<li>Bump MSRV to 1.57 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/788">#788</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li>Specialize <code>BytesMut::put::&lt;Bytes&gt;</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li>Reserve capacity in <code>BytesMut::put</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li>Change <code>BytesMut::remaining_mut</code> to use
<code>isize::MAX</code> instead of <code>usize::MAX</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
</ul>
<h3>Internal changes</h3>
<ul>
<li>Guarantee address in <code>slice()</code> for empty slices. (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/780">#780</a>)</li>
<li>Rename <code>Vtable::to_*</code> -&gt; <code>Vtable::into_*</code>
(<a
href="https://redirect.github.com/tokio-rs/bytes/issues/776">#776</a>)</li>
<li>Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Ignore <code>BytesMut::freeze</code> doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li>Move <code>drop_fn</code> of <code>from_owner</code> into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
</ul>
<h2>Bytes v1.10.1</h2>
<h1>1.10.1 (March 5th, 2025)</h1>
<h3>Fixed</h3>
<ul>
<li>Fix memory leak when using <code>to_vec</code> with
<code>Bytes::from_owner</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>:
<a
href="https://redirect.github.com/tokio-rs/bytes/pull/773">tokio-rs/bytes#773</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's
changelog</a>.</em></p>
<blockquote>
<h1>1.11.1 (February 3rd, 2026)</h1>
<ul>
<li>Fix integer overflow in <code>BytesMut::reserve</code></li>
</ul>
<h1>1.11.0 (November 14th, 2025)</h1>
<ul>
<li>Bump MSRV to 1.57 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/788">#788</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li>Specialize <code>BytesMut::put::&lt;Bytes&gt;</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li>Reserve capacity in <code>BytesMut::put</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li>Change <code>BytesMut::remaining_mut</code> to use
<code>isize::MAX</code> instead of <code>usize::MAX</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
</ul>
<h3>Internal changes</h3>
<ul>
<li>Guarantee address in <code>slice()</code> for empty slices. (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/780">#780</a>)</li>
<li>Rename <code>Vtable::to_*</code> -&gt; <code>Vtable::into_*</code>
(<a
href="https://redirect.github.com/tokio-rs/bytes/issues/776">#776</a>)</li>
<li>Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Ignore <code>BytesMut::freeze</code> doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li>Move <code>drop_fn</code> of <code>from_owner</code> into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
</ul>
<h1>1.10.1 (March 5th, 2025)</h1>
<h3>Fixed</h3>
<ul>
<li>Fix memory leak when using <code>to_vec</code> with
<code>Bytes::from_owner</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/bytes/commit/417dccdeff249e0c011327de7d92e0d6fbe7cc43"><code>417dccd</code></a>
Release bytes v1.11.1 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/820">#820</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/d0293b0e35838123c51ca5dfdf468ecafee4398f"><code>d0293b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/a7952fb4478f6dc226f623b217432fbc6f8dad24"><code>a7952fb</code></a>
chore: prepare bytes v1.11.0 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/804">#804</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/60cbb776f22e4ef2268c026e88a24d6ed75b3776"><code>60cbb77</code></a>
fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/7ce330f5192a322fb1efefe7ac9a3850b27162a1"><code>7ce330f</code></a>
Move drop_fn of from_owner into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/4b53a29eb26716592ef2f00f925ef58ccb182e61"><code>4b53a29</code></a>
Tweak BytesMut::remaining_mut (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/016fdbdc7a95f6764186dacfcaeef94d77e89cd1"><code>016fdbd</code></a>
Reserve capacity in BytesMut::put (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/ef7f25736cfe48db5b42f2aa3225cace4126d2ac"><code>ef7f257</code></a>
Specialize BytesMut::put::&lt;Bytes&gt; (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/8b4f54d0f317724bfeab29232f8a9333b3d8625e"><code>8b4f54d</code></a>
Ignore BytesMut::freeze doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/16132ad2593402aa7dbd882b0ce22a40bfacfd96"><code>16132ad</code></a>
Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/bytes/compare/v1.10.0...v1.11.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `bytes` from 1.10.1 to 1.11.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/releases">bytes's
releases</a>.</em></p>
<blockquote>
<h2>Bytes v1.11.1</h2>
<h1>1.11.1 (February 3rd, 2026)</h1>
<ul>
<li>Fix integer overflow in <code>BytesMut::reserve</code></li>
</ul>
<h2>Bytes v1.11.0</h2>
<h1>1.11.0 (November 14th, 2025)</h1>
<ul>
<li>Bump MSRV to 1.57 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/788">#788</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li>Specialize <code>BytesMut::put::&lt;Bytes&gt;</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li>Reserve capacity in <code>BytesMut::put</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li>Change <code>BytesMut::remaining_mut</code> to use
<code>isize::MAX</code> instead of <code>usize::MAX</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
</ul>
<h3>Internal changes</h3>
<ul>
<li>Guarantee address in <code>slice()</code> for empty slices. (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/780">#780</a>)</li>
<li>Rename <code>Vtable::to_*</code> -&gt; <code>Vtable::into_*</code>
(<a
href="https://redirect.github.com/tokio-rs/bytes/issues/776">#776</a>)</li>
<li>Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Ignore <code>BytesMut::freeze</code> doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li>Move <code>drop_fn</code> of <code>from_owner</code> into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
</ul>
<h2>Bytes v1.10.1</h2>
<h1>1.10.1 (March 5th, 2025)</h1>
<h3>Fixed</h3>
<ul>
<li>Fix memory leak when using <code>to_vec</code> with
<code>Bytes::from_owner</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>:
<a
href="https://redirect.github.com/tokio-rs/bytes/pull/773">tokio-rs/bytes#773</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's
changelog</a>.</em></p>
<blockquote>
<h1>1.11.1 (February 3rd, 2026)</h1>
<ul>
<li>Fix integer overflow in <code>BytesMut::reserve</code></li>
</ul>
<h1>1.11.0 (November 14th, 2025)</h1>
<ul>
<li>Bump MSRV to 1.57 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/788">#788</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li>Specialize <code>BytesMut::put::&lt;Bytes&gt;</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li>Reserve capacity in <code>BytesMut::put</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li>Change <code>BytesMut::remaining_mut</code> to use
<code>isize::MAX</code> instead of <code>usize::MAX</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
</ul>
<h3>Internal changes</h3>
<ul>
<li>Guarantee address in <code>slice()</code> for empty slices. (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/780">#780</a>)</li>
<li>Rename <code>Vtable::to_*</code> -&gt; <code>Vtable::into_*</code>
(<a
href="https://redirect.github.com/tokio-rs/bytes/issues/776">#776</a>)</li>
<li>Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Ignore <code>BytesMut::freeze</code> doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li>Move <code>drop_fn</code> of <code>from_owner</code> into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
</ul>
<h1>1.10.1 (March 5th, 2025)</h1>
<h3>Fixed</h3>
<ul>
<li>Fix memory leak when using <code>to_vec</code> with
<code>Bytes::from_owner</code> (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/773">#773</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/bytes/commit/417dccdeff249e0c011327de7d92e0d6fbe7cc43"><code>417dccd</code></a>
Release bytes v1.11.1 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/820">#820</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/d0293b0e35838123c51ca5dfdf468ecafee4398f"><code>d0293b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/a7952fb4478f6dc226f623b217432fbc6f8dad24"><code>a7952fb</code></a>
chore: prepare bytes v1.11.0 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/804">#804</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/60cbb776f22e4ef2268c026e88a24d6ed75b3776"><code>60cbb77</code></a>
fix: <code>BytesMut</code> only reuse if src has remaining (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/803">#803</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/7ce330f5192a322fb1efefe7ac9a3850b27162a1"><code>7ce330f</code></a>
Move drop_fn of from_owner into vtable (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/801">#801</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/4b53a29eb26716592ef2f00f925ef58ccb182e61"><code>4b53a29</code></a>
Tweak BytesMut::remaining_mut (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/795">#795</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/016fdbdc7a95f6764186dacfcaeef94d77e89cd1"><code>016fdbd</code></a>
Reserve capacity in BytesMut::put (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/794">#794</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/ef7f25736cfe48db5b42f2aa3225cace4126d2ac"><code>ef7f257</code></a>
Specialize BytesMut::put::&lt;Bytes&gt; (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/793">#793</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/8b4f54d0f317724bfeab29232f8a9333b3d8625e"><code>8b4f54d</code></a>
Ignore BytesMut::freeze doctest on wasm (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/790">#790</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/16132ad2593402aa7dbd882b0ce22a40bfacfd96"><code>16132ad</code></a>
Fix latest clippy warnings (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/787">#787</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/bytes/compare/v1.10.0...v1.11.1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/HelixDB/helix-db/network/alerts).

</details>
Fixes #847

<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

Fixes Rust codegen failure for WHERE clauses with multi-step traversals
before property access (e.g., `_::ToN::ID::EQ(id)`).

The existing code generation only handled 2-step patterns (property
access + boolean operation), causing compilation failures when traversal
steps like `ToN` or `FromN` preceded property access. This PR extends
the pattern matching to handle 3+ step traversals by:

- Detecting patterns with traversal prefix steps before property access
and boolean operations
- Generating `filter_ref` closures that use `G::from_iter` to execute
the traversal chain before property evaluation
- Supporting both `ReservedPropertyAccess` (ID, Label) and
`PropertyFetch` (custom properties)
- Preserving backwards compatibility with existing 2-step patterns
through explicit length checks

The fix includes comprehensive test coverage for `ToN`, `FromN`
traversals with various property types and regression tests for simple
cases.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| helix-db/src/helixc/generator/traversal_steps.rs | Added code
generation support for multi-step traversal patterns with property
access (e.g., `_::ToN::ID::EQ(id)`), extending existing 2-step pattern
handling to 3+ steps |
| hql-tests/tests/where_traversal_property_access/queries.hx |
Comprehensive test coverage for the fix including `ToN`, `FromN`
traversals with both reserved properties (ID) and custom properties,
plus regression tests |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant HQL as HQL Query Parser
    participant TGen as Traversal Code Generator
    participant WhereRef as WhereRef Display
    participant RustCode as Generated Rust Code
    
    Note over HQL,RustCode: Example: WHERE(_::ToN::ID::EQ(id))
    
    HQL->>TGen: Parse traversal steps<br/>[_, ToN, ID, EQ(id)]
    TGen->>WhereRef: Display WhereRef with traversal
    
    alt 2-step pattern (existing)
        Note over WhereRef: Pattern: _::ID::EQ(id)
        WhereRef->>WhereRef: Check traversal.steps.len() == 2
        WhereRef->>WhereRef: Extract ReservedPropertyAccess + BoolOp
        WhereRef->>RustCode: Generate filter_ref with direct val access
    else 3+ step pattern (NEW FIX)
        Note over WhereRef: Pattern: _::ToN::ID::EQ(id)
        WhereRef->>WhereRef: Check traversal.steps.len() > 2
        WhereRef->>WhereRef: Extract last step (BoolOp)
        WhereRef->>WhereRef: Extract second-last step (PropertyAccess/ReservedProp)
        WhereRef->>WhereRef: Extract prefix steps ([_, ToN])
        alt ReservedPropertyAccess (ID/Label)
            WhereRef->>RustCode: Generate filter_ref with:<br/>1. G::from_iter for traversal<br/>2. node.id()/label() access<br/>3. Boolean comparison
        else PropertyFetch ({property})
            WhereRef->>RustCode: Generate filter_ref with:<br/>1. G::from_iter for traversal<br/>2. node.get_property() access<br/>3. Boolean expression
        end
    else Fallback
        WhereRef->>RustCode: Generate unoptimized filter_ref
    end
    
    RustCode->>RustCode: Compile generated Rust code
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

Fixed container name display format and improved container existence
checking in the CLI, and resolved HQL codegen failure for WHERE clauses
with traversal steps before property access.

## Key Changes

- **CLI Container Naming**: Updated display format from
`helix_{project}_{instance}` to `helix-{project}-{instance}` to match
actual Docker container naming convention (hyphens instead of
underscores)
- **Container Check Improvement**: Refactored `instance_exists` to use
centralized `container_name` method and exact string matching instead of
`contains`, improving accuracy
- **HQL Codegen Fix (#847)**: Added support for WHERE clauses with
multi-step traversal patterns like `_::ToN::ID::EQ(id)` and
`_::ToN::{age}::EQ(age)` that previously caused Rust codegen failures
- **Test Coverage**: Added comprehensive test suite for the new
traversal property access patterns with 6 test queries covering various
edge cases

The changes are well-structured and include proper test coverage for the
codegen fix.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| helix-cli/src/commands/push.rs | Fixed container name display format
from underscores to hyphens to match actual naming scheme |
| helix-cli/src/docker.rs | Improved container existence check to use
centralized container_name method and exact match instead of contains |
| helix-db/src/helixc/generator/traversal_steps.rs | Added codegen
support for WHERE clauses with traversal steps before property access
(fixes #847) |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant User
    participant CLI as Helix CLI
    participant Docker as Docker/Podman
    participant Compiler as HelixC Codegen
    
    Note over User,Compiler: CLI Container Naming Fix
    User->>CLI: helix push
    CLI->>CLI: compose_project_name(instance_name)
    Note right of CLI: Returns "helix-{project}-{instance}"
    CLI->>CLI: container_name(instance_name)
    Note right of CLI: Returns "helix-{project}-{instance}_app"
    CLI->>Docker: Check container exists
    Docker-->>CLI: Container status
    CLI->>CLI: Display container info
    Note right of CLI: Now shows "helix-{project}-{instance}" (fixed from "helix_{project}_{instance}")
    
    Note over User,Compiler: HQL Traversal Property Access Fix (#847)
    User->>Compiler: Compile WHERE(_::ToN::ID::EQ(id))
    Compiler->>Compiler: Parse traversal steps
    Note right of Compiler: Detects pattern: [ToN] + [ID] + [EQ]
    Compiler->>Compiler: Generate optimized filter_ref
    Note right of Compiler: Creates traversal chain + property access
    Compiler-->>User: Valid Rust code generated
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

Fixed type checking for `Count` type in boolean expressions and added
code generation support for WHERE clauses with multi-step traversals
before property access (fixes #847).

**Key Changes:**
- **Type Analyzer**: Added `Type::Count` case mapping to
`FieldType::I64` in `traversal_validation.rs:888`
- **Code Generator**: Implemented pattern matching for traversals with
3+ steps ending in PropertyFetch/ReservedPropertyAccess + BoolOp in
`traversal_steps.rs:837-937`
- **Test Coverage**: Added comprehensive test suite covering
`ToN`/`FromN` with `ID` access and property fetches

**Implementation Details:**
The new codegen handles patterns like `_::ToN::ID::EQ(id)` by:
1. Extracting prefix traversal steps (e.g., `_::ToN`)
2. Generating `G::from_iter` to execute the traversal chain
3. Applying property access and boolean comparison on the resulting node

The code properly handles both reserved properties (`ID`, `Label`) and
user-defined properties with appropriate getter methods.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| helix-db/src/helixc/analyzer/methods/traversal_validation.rs | Added
`Type::Count` case to map to `FieldType::I64` in boolean expression type
checking |
| helix-db/src/helixc/generator/traversal_steps.rs | Added code
generation for WHERE clauses with traversal steps before property access
(fixes issue #847) |
| hql-tests/tests/where_traversal_property_access/queries.hx | New test
queries covering traversal property access patterns including `ToN`,
`FromN` with `ID` and property fetches |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant User as Query Code
    participant Parser as HQL Parser
    participant Analyzer as Type Analyzer
    participant Generator as Code Generator
    participant Runtime as Generated Rust Code

    User->>Parser: Parse WHERE clause with traversal
    Note over Parser: WHERE(_::ToN::ID::EQ(id))
    Parser->>Analyzer: Validate traversal steps
    
    alt Type::Count in boolean expression
        Analyzer->>Analyzer: Check expression type
        Note over Analyzer: (Type::Count, _) => FieldType::I64
        Analyzer->>Generator: Type validated as I64
    else Type::Boolean in boolean expression
        Analyzer->>Analyzer: Map to FieldType::Boolean
        Analyzer->>Generator: Type validated as Boolean
    else Type::Scalar in boolean expression
        Analyzer->>Analyzer: Use existing FieldType
        Analyzer->>Generator: Type validated
    end

    Generator->>Generator: Check pattern: steps > 2?
    alt Pattern: [...] + PropertyAccess + BoolOp
        Generator->>Generator: Extract prefix steps
        Generator->>Generator: Build traversal chain
        
        alt Case: ReservedPropertyAccess (ID/Label)
            Generator->>Runtime: Generate filter_ref with G::from_iter
            Note over Runtime: Access node.id() or node.label()
        else Case: PropertyFetch
            Generator->>Runtime: Generate filter_ref with get_property
            Note over Runtime: Access node.get_property(name)
        end
    else Simple 2-step pattern
        Generator->>Runtime: Use optimized short path
    end

    Runtime->>User: Return filtered results
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
UpsertE was incorrectly using the first edge from the source iterator
instead of looking up edges by the specified from_node/to_node
parameters.

Fixes #850

<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

Fixed a critical bug in `UpsertE` where it incorrectly used the first
edge from the source iterator instead of looking up edges by the
specified `from_node`/`to_node`/`label` parameters.

**Key Changes:**
- Refactored `upsert_e()` in `upsert.rs:353-520` to query the database
directly using edge endpoints rather than relying on iterator content
- Added database lookup logic that searches `out_edges_db` by
`from_node` + `label_hash`, then filters by matching `to_node`
- Removed the `mut` modifier from `self` parameter since the iterator is
no longer consumed
- Updated `test_upsert_e_ignores_iterator_content()` to reflect the new
behavior where iterator content is completely ignored
- Added two comprehensive regression tests
(`test_upsert_e_creates_edge_between_correct_nodes_issue_850` and
`test_upsert_e_updates_correct_edge_when_multiple_edges_exist_issue_850`)
that verify the fix

**Impact:**
This fix ensures that `UpsertE` operations target the correct edges
based on their endpoints, preventing accidental updates to unrelated
edges. The change makes the behavior more predictable and aligns with
the semantic meaning of the `from_node` and `to_node` parameters.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| helix-db/src/helix_engine/traversal_core/ops/util/upsert.rs | Fixed
`upsert_e` to lookup edges by `from_node`/`to_node`/`label` instead of
using source iterator, resolving Issue #850 |
| helix-db/src/helix_engine/tests/traversal_tests/upsert_tests.rs |
Added regression tests for Issue #850 and updated existing test to
reflect new behavior of ignoring iterator content |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant Client
    participant UpsertE as upsert_e()
    participant Storage as HelixGraphStorage
    participant OutEdgesDB as out_edges_db
    participant EdgesDB as edges_db
    participant InEdgesDB as in_edges_db

    Note over Client,InEdgesDB: Before Fix (Issue #850)
    Client->>UpsertE: upsert_e(label, from_node, to_node, props)
    UpsertE->>UpsertE: Get first edge from iterator
    Note over UpsertE: ❌ Ignores from_node/to_node parameters!
    UpsertE->>EdgesDB: Update wrong edge
    UpsertE-->>Client: Return incorrect edge

    Note over Client,InEdgesDB: After Fix (Current)
    Client->>UpsertE: upsert_e(label, from_node, to_node, props)
    Note over UpsertE: ✓ Ignores iterator content
    UpsertE->>UpsertE: hash_label(label)
    UpsertE->>OutEdgesDB: get_duplicates(from_node + label_hash)
    OutEdgesDB-->>UpsertE: Iterator of edges
    UpsertE->>UpsertE: Filter by to_node match
    alt Edge exists
        UpsertE->>Storage: get_edge(edge_id)
        Storage-->>UpsertE: existing_edge
        UpsertE->>UpsertE: Merge properties
        UpsertE->>EdgesDB: put(updated_edge)
        UpsertE-->>Client: Return updated edge
    else Edge does not exist
        UpsertE->>UpsertE: Create new edge
        UpsertE->>EdgesDB: put(new_edge)
        UpsertE->>OutEdgesDB: put(from_node mapping)
        UpsertE->>InEdgesDB: put(to_node mapping)
        UpsertE-->>Client: Return new edge
    end
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
… upsets (#856)

<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

- Refactors `UpsertAdapter` implementations for nodes/edges/vectors to
use early-return `Result` flow and reduce nested error handling.
- Fixes edge upsert correctness by looking up existing edges via
`(from_node, to_node, label)` in adjacency DBs instead of trusting the
source iterator.
- Expands traversal upsert test coverage, adding persistence and
adjacency assertions across nodes/edges/vectors.
- Updates `GraphError` to split heed encoding/decoding into dedicated
error variants.

<details><summary><h3>Important Files Changed</h3></summary>




| Filename | Overview |
|----------|----------|
| helix-db/src/helix_engine/tests/traversal_tests/upsert_tests.rs | Adds
extensive upsert persistence/adjacency tests and imports. No obvious
test logic bugs found, but several assertions allow either Ok or Err
outcomes (non-deterministic expectations). |
| helix-db/src/helix_engine/traversal_core/ops/util/upsert.rs |
Refactors upsert_n/e/v to use early-return Result flow and improves edge
lookup by endpoints. Potential issue: unique-index insert maps any LMDB
error to DuplicateKey, masking real storage errors. |
| helix-db/src/helix_engine/types.rs | Adds GraphError::EncodeError and
changes From<heed3::Error> mapping. Risk: Duplicate is no longer
produced from heed KeyExist, and several error variants are now
collapsed into StorageError strings. |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant C as Caller
    participant U as UpsertAdapter
    participant O as out_edges_db
    participant E as edges_db
    participant OUT as out_edges_db (adj)
    participant IN as in_edges_db (adj)

    C->>U: upsert_e(label, from, to, props)
    U->>O: get_duplicates(out_edge_key(from,label_hash))
    alt match to_node
        O-->>U: edge_id
        U->>E: get_edge(edge_id)
        U->>E: put(edge_key(edge_id), updated_edge_bytes)
        U-->>C: TraversalValue::Edge(existing)
    else no match
        O-->>U: no existing
        U->>E: put_with_flags(APPEND, edge_key(new_id), edge_bytes)
        U->>OUT: put_with_flags(APPEND_DUP, out_edge_key(from,label_hash), pack(new_id,to))
        U->>IN: put_with_flags(APPEND_DUP, in_edge_key(to,label_hash), pack(new_id,from))
        U-->>C: TraversalValue::Edge(new)
    end
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 6, 2026

Additional Comments (1)

helix-cli/src/commands/start.rs
Container name mismatch

This prints helix_{project_name}_{instance_name} but the CLI now uses hyphenated compose/project naming (helix-{project}-{instance}) elsewhere (e.g. DockerManager::compose_project_name and push.rs). This will display the wrong container name to users.

                &format!("helix-{project_name}-{instance_name}"),

@xav-db xav-db changed the title fix (cli + core + hql): fix (cli + core + hql): fixing helix push, upserts, property access, count type checking Feb 6, 2026
@xav-db xav-db merged commit eaa9a48 into main Feb 6, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant