Skip to content

Conversation

@TimDiekmann
Copy link
Member

@TimDiekmann TimDiekmann commented Oct 30, 2025

🌟 What is the purpose of this PR?

This PR refactors the SQL query compiler to improve flexibility and type safety by introducing new type abstractions that make SQL construction more robust and maintainable.

The key improvement is the introduction of Identifier types that allow for flexible SQL identifier construction (table names, column names, etc.) instead of being hardcoded to specific enum variants. This makes the query compiler more adaptable to different use cases and future extensions.

Additionally, the add_join_statements function was completely rewritten to use a more robust alias numbering pattern that correctly handles complex scenarios with parallel query chains.

🔗 Related links

🔍 What does this change?

Core Refactoring

The main change is in libs/@local/graph/postgres-store/src/store/postgres/query/compile.rs:

Complete rewrite of add_join_statements:

  1. Uses TableReference with Cow<> for efficient borrowed/owned semantics
  2. Manually constructs JoinExpression with the new JoinFrom::Table variant
  3. Implements defensive max_number pattern for alias numbering
  4. Correctly recalculates JOIN conditions after alias number updates
  5. Consolidates reuse-check and alias-conflict detection into single efficient loop

This approach ensures JOIN conditions always reference the correct table aliases, even in complex scenarios with multiple parallel query chains requiring the same tables.

Type Safety Refactoring

Introduced new type abstractions to replace stringly-typed code:

  • Identifier<'name> (new file: expression/identifier.rs):
    • Represents a PostgreSQL identifier (table name, column name, schema, etc.)
    • Always quotes identifiers with proper escaping
    • Protects against SQL injection
    • Comprehensive test coverage for edge cases (quotes, unicode, special chars)
  • TableReference<'name> (new file: expression/table_reference.rs):
    • Replaces the old AliasedTable type
    • Properly structured: SchemaReferenceTableNameTableReference
    • Supports fully-qualified names: database.schema.table
    • Includes alias information directly in the type
  • ColumnReference<'name> (new file: expression/column_reference.rs):
    • Represents column references with optional table qualification
    • Separates column name from table correlation
    • Supports asterisk (*) as a special case
  • JoinFrom enum (updated expression/join_clause.rs):
    • Replaces inline pattern matching for join sources
    • Variants: Table { table, alias } and SelectStatement { statement, alias }
    • Encapsulates the logic for extracting table references from join sources

Code Quality Improvements

  1. Renamed Expression::ColumnReferenceExpression::AliasedColumn for clarity
    • The old name was confusing after introducing the new ColumnReference type
    • New name better reflects what it represents (a column with an alias)
  2. Consolidated duplicate loops: The old code had multiple passes over the joins array; now uses a single efficient iteration that tracks both exact matches and maximum alias numbers
  3. Improved condition handling: add_condition function now properly handles adding conditions to join statements vs. WHERE clause
  4. Better encapsulation: JoinFrom::reference_table() method provides clean access to the table being joined without exposing internal structure
  5. Removed unnecessary dependencies: Removed unused mem import and Condition from Hash derivation (since it contains expressions which aren't always hashable)

Files Changed

Core compiler logic (~350 lines modified):

  • compile.rs: Complete rewrite of add_join_statements, updates to use new types throughout

New type abstractions (~600 lines added):

  • expression/identifier.rs: PostgreSQL identifier with proper quoting
  • expression/table_reference.rs: Schema and table reference types
  • expression/column_reference.rs: Column reference types

Updated expression types:

  • expression/join_clause.rs: Introduced JoinFrom enum, restructured JoinExpression
  • expression/select_clause.rs: Use AliasedColumn instead of ColumnReference
  • expression/where_clause.rs: Type updates
  • expression/with_clause.rs: Type updates
  • expression/order_clause.rs: Type updates
  • expression/group_by_clause.rs: Type updates
  • expression/conditional.rs: Type updates

Statement updates:

  • statement/select.rs: Use TableReference instead of AliasedTable
  • statement/insert.rs: Type updates
  • statement/window.rs: Type updates
  • statement/mod.rs: Export new types

Supporting changes:

  • condition.rs: Removed Hash derivation (correctness fix)
  • table.rs: Added helper methods for new types
  • expression/mod.rs: Export new types

🛡 What tests cover this?

  • All existing query compilation tests pass (24 test cases in the query statement test suite)
  • New unit tests for type abstractions:
    • identifier.rs: 9 test cases covering quoting, escaping, keywords, unicode
    • table_reference.rs: 7 test cases covering qualified names and special characters
    • column_reference.rs: 8 test cases covering qualified columns and asterisk

The existing integration tests provide regression coverage for the bug fix. These tests exercise various query patterns including:

  • Parallel query chains requiring the same table
  • Complex JOIN scenarios with multiple depth levels
  • Entity traversal with temporal metadata filtering

@github-actions github-actions bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team labels Oct 30, 2025
@codecov
Copy link

codecov bot commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 90.45045% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.77%. Comparing base (de3ee86) to head (4857cc4).
⚠️ Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
...store/postgres/query/expression/table_reference.rs 87.40% 16 Missing and 1 partial ⚠️
.../src/store/postgres/query/expression/identifier.rs 83.82% 11 Missing ⚠️
...src/store/postgres/query/expression/join_clause.rs 79.06% 8 Missing and 1 partial ⚠️
...postgres-store/src/store/postgres/query/compile.rs 95.10% 3 Missing and 4 partials ⚠️
...tore/postgres/query/expression/column_reference.rs 95.34% 4 Missing ⚠️
...src/store/postgres/query/expression/conditional.rs 50.00% 2 Missing ⚠️
...h/postgres-store/src/store/postgres/query/table.rs 96.82% 2 Missing ⚠️
...store/src/store/postgres/query/statement/insert.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7951      +/-   ##
==========================================
+ Coverage   55.66%   55.77%   +0.10%     
==========================================
  Files        1112     1115       +3     
  Lines      101195   101510     +315     
  Branches     4690     4700      +10     
==========================================
+ Hits        56329    56615     +286     
- Misses      44205    44230      +25     
- Partials      661      665       +4     
Flag Coverage Δ
apps.hash-ai-worker-ts 1.32% <ø> (ø)
apps.hash-api 0.00% <ø> (ø)
local.hash-backend-utils 4.07% <ø> (ø)
local.hash-graph-sdk 10.88% <ø> (ø)
local.hash-isomorphic-utils 0.00% <ø> (ø)
rust.hash-graph-api 2.89% <ø> (ø)
rust.hash-graph-postgres-store 21.83% <90.45%> (+1.45%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@graphite-app graphite-app bot requested review from a team October 30, 2025 15:30
@graphite-app
Copy link
Contributor

graphite-app bot commented Oct 30, 2025

Graphite Automations

"Request backend reviewers once CI passes" took an action on this PR • (10/30/25)

1 reviewer was added to this PR based on Tim Diekmann's automation.

"Request Rust reviewers once CI passes" took an action on this PR • (10/30/25)

1 reviewer was added to this PR based on Tim Diekmann's automation.

"Request DevOps reviewers once CI passes" took an action on this PR • (11/01/25)

1 reviewer was added to this PR based on Tim Diekmann's automation.

Introduce comprehensive meta-skill for creating and managing Claude Code
skills in the HASH repository, following Anthropic best practices.

Features:
- Progressive disclosure with 6 detailed reference files
- HASH-specific patterns from .github/labeler.yml
- Complete trigger configuration guide
- Testing and troubleshooting documentation
- Pattern library with HASH repo structure

Structure follows Anthropic best practices:
- SKILL.md < 500 lines (453 lines)
- Lowercase kebab-case for resource files
- Comprehensive skill-rules.json configuration

Based on claude-code-infrastructure-showcase/skill-developer with
adaptations for HASH workspace structure and existing skills
(rust-error-stack, cargo-dependencies).
Restructure cargo-dependencies skill following Anthropic best practices.

Changes:
- Add YAML frontmatter with trigger-rich description
- Reduce SKILL.md from 236 to 163 lines (73 lines saved)
- Split content into 3 detailed resource files:
  - workspace-setup.md: Workspace root management
  - package-dependencies.md: 4-section structure details
  - examples-reference.md: Real HASH codebase examples
- Update to production-ready status

Structure now follows 500-line rule with progressive disclosure pattern.
All files use lowercase kebab-case naming convention.
Polish rust-error-stack skill following Anthropic best practices.

Changes:
- Enhance YAML frontmatter description with more trigger keywords
- Standardize resource links (remove ./ prefix for consistency)
- Add production-ready status footer
- Line count: 129 (well under 500-line rule)

All resource links now use consistent 'resources/' format without
leading './'. Trigger description now includes key terms: Report types,
change_context, attach, implementing Error trait.
Introduce comprehensive rust-documentation skill based on
.cursor/rules/rust-documentation.mdc (388 lines).

Features:
- Function documentation patterns (simple vs complex)
- Type documentation (structs, enums, traits)
- Error documentation with intra-doc links
- Examples and code snippets
- Emphasis on avoiding obvious/redundant docs

Structure:
- SKILL.md: 221 lines (concise overview)
- 4 resource files with detailed patterns:
  - function-documentation.md: Parameters, returns, async
  - type-documentation.md: Structs, enums, traits (avoid noise)
  - error-documentation.md: # Errors section format
  - examples-and-links.md: Writing examples, intra-doc links

Key principle: Document WHY, not WHAT. Skip obvious documentation
that just restates code (e.g., don't document "prints a line" for println).

Follows Anthropic best practices with progressive disclosure and
< 500 line rule per file.
Add trigger configurations for writing-skills and rust-documentation
skills to skill-rules.json.

Changes:
- writing-skills: Meta-skill triggers (priority: high)
  - Keywords: skill system, triggers, hooks, SKILL.md
  - Intent patterns: create/modify/explain skills
  - File triggers: .claude/skills/**/SKILL.md

- rust-documentation: Documentation practices (priority: high)
  - Keywords: rustdoc, doc comments, # Errors/Examples/Panics
  - Intent patterns: write/document rust code
  - File triggers: **/*.rs with doc comment patterns
  - Content patterns: detect existing doc comments

Both skills use "suggest" enforcement and follow domain skill pattern.
…rformance improvements

BREAKING: Removed fileTriggers (were unused dead code)

Infrastructure:
- Add path auto-detection for CLAUDE_PROJECT_DIR
- Add --validate flag for health checks
- Add SKILL_DEBUG=true for detailed matching logs
- Improve error messages with project directory context

Performance:
- Cache regex compilation (50% faster)
- Cache keyword toLowerCase() calls
- Remove continue bug that skipped intent pattern checks
- Extract getProjectDir() to eliminate code duplication

Validation:
- Validate regex patterns during --validate
- Show helpful error messages for invalid patterns
- Warn about missing promptTriggers
- Verify SKILL.md files exist

Configuration:
- Remove unused fileTriggers from all skills
- Add word boundaries to intent patterns (reduce false positives)
- Add German keywords (fehler, fehlerbehandlung, etc.)

Documentation:
- Clean up writing-skills SKILL.md
- Remove documentation for unimplemented features
- Mark future features clearly

Code Quality:
- Disable ESLint no-console for hooks directory
- Add proper error handling with stack traces
- Improve debug output formatting
Add comprehensive future-enhancements.md resource documenting:
- 14 potential skill system features
- Implementation complexity estimates
- Priority recommendations
- Clear distinction between implemented and future features

Organized into sections:
- Skill System Features (file triggers, guardrails, session tracking)
- Advanced Triggers (fuzzy matching, multi-language, context-aware)
- Performance Optimizations (regex cache, parallel checking)
- Developer Experience (templates, interactive builder)
- Analytics & Monitoring (usage stats, A/B testing)

Following progressive disclosure pattern - keeps main SKILL.md under 500 lines.
indietyp
indietyp previously approved these changes Oct 31, 2025
…matches

Previously matchType was hardcoded to 'keyword' even when matched via
intent pattern. Now properly tracks which trigger type matched:
- Keywords take priority and set matchType to 'keyword'
- Intent patterns only checked if no keyword match, sets 'intent'
- Ensures accurate match type reporting for debugging and analytics
…iority

Previously skipped intent pattern check if keyword matched, which meant:
- Debug logs wouldn't show intent pattern matches
- Couldn't validate that both trigger types work correctly

Now both are checked independently:
- Keywords set matchType to 'keyword'
- Intent patterns use nullish coalescing (??=) to set 'intent' if no keyword match
- Debug logs show all matches for better debugging
- Keywords take priority when both match (more specific than regex)

Also fixed shell script argument passing:
- --validate flag now properly passed to TypeScript script
- No longer tries to read stdin when using --validate flag
- Uses conditional logic to handle validate vs normal mode

Tested scenarios:
- Both keyword + intent match → matchType='keyword' ✓
- Only intent pattern match → matchType='intent' ✓
- Only keyword match → matchType='keyword' ✓
- Validation mode → all skills validated ✓
…ectly

Simplified skill hook architecture by removing unnecessary indirection:

Changes:
- Removed .claude/hooks/skill-activation-prompt.sh wrapper script
- Claude Code hook now calls yarn workspace directly from settings.json
- Renamed scripts to follow project conventions:
  - run:skill - executes skill activation (called by Claude Code hook)
  - lint:skill - validates skill configuration (called by CI & locally)
- Added [email protected] as devDependency to @local/claude-hooks
- Updated CI workflow to use yarn lint:skill
- Added yarn lint:skill to root package.json

Benefits:
- Simpler architecture - one less layer of indirection
- Consistent with project patterns (lint:*, run:* naming conventions)
- No shell script maintenance needed
- Clearer dependency management through package.json
- TypeScript script's getProjectDir() fallback handles project dir resolution
@github-actions
Copy link
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$28.6 \mathrm{ms} \pm 131 \mathrm{μs}\left({\color{gray}0.311 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.32 \mathrm{ms} \pm 15.7 \mathrm{μs}\left({\color{gray}0.915 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1001 $$13.5 \mathrm{ms} \pm 70.8 \mathrm{μs}\left({\color{gray}0.483 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$43.7 \mathrm{ms} \pm 346 \mathrm{μs}\left({\color{gray}-1.025 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.9 \mathrm{ms} \pm 90.7 \mathrm{μs}\left({\color{gray}-2.540 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1526 $$25.0 \mathrm{ms} \pm 145 \mathrm{μs}\left({\color{gray}-0.755 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$28.8 \mathrm{ms} \pm 190 \mathrm{μs}\left({\color{lightgreen}-37.933 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.76 \mathrm{ms} \pm 24.0 \mathrm{μs}\left({\color{lightgreen}-81.409 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$15.7 \mathrm{ms} \pm 87.7 \mathrm{μs}\left({\color{lightgreen}-49.747 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.66 \mathrm{ms} \pm 14.4 \mathrm{μs}\left({\color{gray}-2.386 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.82 \mathrm{ms} \pm 10.2 \mathrm{μs}\left({\color{gray}-2.217 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 51 $$3.22 \mathrm{ms} \pm 12.9 \mathrm{μs}\left({\color{gray}-1.646 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.21 \mathrm{ms} \pm 25.2 \mathrm{μs}\left({\color{gray}0.204 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.42 \mathrm{ms} \pm 13.9 \mathrm{μs}\left({\color{gray}-2.975 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 107 $$4.05 \mathrm{ms} \pm 23.8 \mathrm{μs}\left({\color{gray}-0.606 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.42 \mathrm{ms} \pm 27.2 \mathrm{μs}\left({\color{gray}0.215 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.38 \mathrm{ms} \pm 19.4 \mathrm{μs}\left({\color{gray}0.229 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$3.95 \mathrm{ms} \pm 26.1 \mathrm{μs}\left({\color{gray}-0.412 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.62 \mathrm{ms} \pm 32.2 \mathrm{μs}\left({\color{red}9.30 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.50 \mathrm{ms} \pm 11.3 \mathrm{μs}\left({\color{red}6.19 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1 $$2.60 \mathrm{ms} \pm 11.4 \mathrm{μs}\left({\color{red}5.05 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$2.78 \mathrm{ms} \pm 15.2 \mathrm{μs}\left({\color{gray}4.24 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.69 \mathrm{ms} \pm 14.3 \mathrm{μs}\left({\color{red}5.04 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$2.87 \mathrm{ms} \pm 12.7 \mathrm{μs}\left({\color{red}5.53 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$2.97 \mathrm{ms} \pm 13.8 \mathrm{μs}\left({\color{red}6.66 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.64 \mathrm{ms} \pm 11.8 \mathrm{μs}\left({\color{red}8.51 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 25 $$2.81 \mathrm{ms} \pm 12.6 \mathrm{μs}\left({\color{red}7.00 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.32 \mathrm{ms} \pm 19.9 \mathrm{μs}\left({\color{red}6.80 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$2.89 \mathrm{ms} \pm 11.9 \mathrm{μs}\left({\color{red}7.54 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 26 $$3.13 \mathrm{ms} \pm 18.0 \mathrm{μs}\left({\color{red}6.54 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.31 \mathrm{ms} \pm 18.3 \mathrm{μs}\left({\color{red}9.12 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.85 \mathrm{ms} \pm 11.7 \mathrm{μs}\left({\color{red}7.34 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.12 \mathrm{ms} \pm 15.5 \mathrm{μs}\left({\color{red}7.77 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$40.2 \mathrm{ms} \pm 157 \mathrm{μs}\left({\color{gray}-0.729 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$87.4 \mathrm{ms} \pm 418 \mathrm{μs}\left({\color{gray}-0.404 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$44.3 \mathrm{ms} \pm 182 \mathrm{μs}\left({\color{gray}-1.030 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$47.4 \mathrm{ms} \pm 222 \mathrm{μs}\left({\color{gray}1.42 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$55.3 \mathrm{ms} \pm 256 \mathrm{μs}\left({\color{lightgreen}-5.736 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$41.1 \mathrm{ms} \pm 201 \mathrm{μs}\left({\color{gray}-1.638 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$502 \mathrm{ms} \pm 861 \mathrm{μs}\left({\color{gray}0.990 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$101 \mathrm{ms} \pm 471 \mathrm{μs}\left({\color{gray}1.85 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$85.5 \mathrm{ms} \pm 361 \mathrm{μs}\left({\color{gray}0.872 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$325 \mathrm{ms} \pm 956 \mathrm{μs}\left({\color{red}11.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$15.3 \mathrm{ms} \pm 74.9 \mathrm{μs}\left({\color{gray}1.44 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$15.8 \mathrm{ms} \pm 67.2 \mathrm{μs}\left({\color{gray}4.95 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$16.1 \mathrm{ms} \pm 76.4 \mathrm{μs}\left({\color{red}5.18 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$15.3 \mathrm{ms} \pm 68.3 \mathrm{μs}\left({\color{gray}2.96 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$19.2 \mathrm{ms} \pm 95.6 \mathrm{μs}\left({\color{red}9.17 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$15.5 \mathrm{ms} \pm 66.8 \mathrm{μs}\left({\color{red}5.86 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$15.5 \mathrm{ms} \pm 81.1 \mathrm{μs}\left({\color{gray}4.20 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$15.5 \mathrm{ms} \pm 80.0 \mathrm{μs}\left({\color{gray}3.17 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$16.3 \mathrm{ms} \pm 74.5 \mathrm{μs}\left({\color{gray}4.70 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$23.5 \mathrm{ms} \pm 160 \mathrm{μs}\left({\color{gray}4.62 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$31.9 \mathrm{ms} \pm 329 \mathrm{μs}\left({\color{gray}2.01 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$31.5 \mathrm{ms} \pm 304 \mathrm{μs}\left({\color{red}7.76 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$30.4 \mathrm{ms} \pm 329 \mathrm{μs}\left({\color{gray}-4.434 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$30.9 \mathrm{ms} \pm 278 \mathrm{μs}\left({\color{gray}-2.640 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$30.7 \mathrm{ms} \pm 313 \mathrm{μs}\left({\color{gray}-2.362 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$30.5 \mathrm{ms} \pm 301 \mathrm{μs}\left({\color{gray}-0.544 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$32.0 \mathrm{ms} \pm 280 \mathrm{μs}\left({\color{gray}2.49 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$31.1 \mathrm{ms} \pm 308 \mathrm{μs}\left({\color{gray}-1.037 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$31.1 \mathrm{ms} \pm 265 \mathrm{μs}\left({\color{gray}-0.250 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$9.42 \mathrm{ms} \pm 52.6 \mathrm{μs}\left({\color{gray}3.17 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$59.5 \mathrm{ms} \pm 360 \mathrm{μs}\left({\color{gray}2.14 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$111 \mathrm{ms} \pm 439 \mathrm{μs}\left({\color{gray}-0.716 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$65.0 \mathrm{ms} \pm 329 \mathrm{μs}\left({\color{gray}1.25 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$74.3 \mathrm{ms} \pm 348 \mathrm{μs}\left({\color{gray}0.657 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$83.1 \mathrm{ms} \pm 420 \mathrm{μs}\left({\color{gray}0.450 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$90.4 \mathrm{ms} \pm 380 \mathrm{μs}\left({\color{gray}0.329 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$55.1 \mathrm{ms} \pm 296 \mathrm{μs}\left({\color{gray}3.64 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$82.8 \mathrm{ms} \pm 351 \mathrm{μs}\left({\color{gray}-0.215 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$62.1 \mathrm{ms} \pm 248 \mathrm{μs}\left({\color{gray}3.35 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$71.3 \mathrm{ms} \pm 282 \mathrm{μs}\left({\color{gray}3.45 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$72.0 \mathrm{ms} \pm 339 \mathrm{μs}\left({\color{gray}0.551 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$71.5 \mathrm{ms} \pm 293 \mathrm{μs}\left({\color{gray}0.129 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$144 \mathrm{ms} \pm 628 \mathrm{μs}\left({\color{red}9.63 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$144 \mathrm{ms} \pm 553 \mathrm{μs}\left({\color{red}6.65 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$43.1 \mathrm{ms} \pm 175 \mathrm{μs}\left({\color{lightgreen}-58.789 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$600 \mathrm{ms} \pm 1.17 \mathrm{ms}\left({\color{gray}-1.837 \mathrm{\%}}\right) $$ Flame Graph

@TimDiekmann TimDiekmann changed the base branch from main to graphite-base/7951 October 31, 2025 17:08
@TimDiekmann TimDiekmann force-pushed the t/be-187-introduce-tablereference-and-refactor-joinexpression branch from 4299928 to 4857cc4 Compare October 31, 2025 17:08
@github-actions github-actions bot dismissed indietyp’s stale review October 31, 2025 17:08

Your organization requires reapproval when changes are made, so Graphite has dismissed approvals. See the output of git range-diff at https://github.com/hashintel/hash/actions/runs/18979805178

@TimDiekmann TimDiekmann changed the base branch from graphite-base/7951 to t/h-5553-improve-claude-skill-system-and-add-more-skills October 31, 2025 17:08
Base automatically changed from t/h-5553-improve-claude-skill-system-and-add-more-skills to main November 1, 2025 19:04
@graphite-app graphite-app bot requested a review from a team November 1, 2025 19:04
@TimDiekmann TimDiekmann added this pull request to the merge queue Nov 1, 2025
Merged via the queue into main with commit 37c8768 Nov 1, 2025
103 of 119 checks passed
@TimDiekmann TimDiekmann deleted the t/be-187-introduce-tablereference-and-refactor-joinexpression branch November 1, 2025 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team

Development

Successfully merging this pull request may close these issues.

3 participants