Skip to content

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Nov 10, 2025

https://linear.app/discourse-graphs/issue/ENG-1044/experiments-with-different-datalog-query-modalities

Summary by CodeRabbit

  • New Features
    • Added optional local mode for queries, enabling optimized query processing based on context requirements.

@linear
Copy link

linear bot commented Nov 10, 2025

@supabase
Copy link

supabase bot commented Nov 10, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@maparent maparent marked this pull request as draft November 10, 2025 02:22
@maparent
Copy link
Collaborator Author

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

📝 Walkthrough

Walkthrough

Added a local flag to FireQueryArgs enabling an alternative query execution path that uses Roam's local data APIs with automatic property name remapping to resolve naming conflicts between namespaced and non-namespaced properties.

Changes

Cohort / File(s) Summary
Local query flag and execution logic
apps/roam/src/utils/fireQuery.ts
Added optional local?: boolean field to FireQueryArgs type; introduced PROP_NAME_RE regex constant; imported json type from getBlockProps; implemented conditional local query flow that detects property names, builds rename mappings, and routes between async.q and fast.q paths based on naming-conflict detection; preserved existing behavior in non-local path

Sequence Diagram

sequenceDiagram
    participant Caller
    participant fireQuery
    participant PropDetection as Prop Detection<br/>(PROP_NAME_RE)
    participant ConflictCheck as Conflict<br/>Check
    participant AsyncPath as async.q Path
    participant FastPath as fast.q Path
    participant Remapping as Remapping

    Caller->>fireQuery: fireQuery(query, local: true)
    rect rgb(200, 220, 240)
        Note over fireQuery,PropDetection: Local Mode Enabled
        fireQuery->>PropDetection: Detect prop names in query
        PropDetection->>fireQuery: Return property mapping
        fireQuery->>ConflictCheck: Check for naming conflicts
    end
    
    alt No Conflicts Found
        ConflictCheck->>AsyncPath: Use async.q (faster)
        AsyncPath->>Remapping: Execute and get results
        Remapping->>fireQuery: Rename props back to original
    else Conflicts Detected
        ConflictCheck->>FastPath: Use fast.q (safer)
        FastPath->>fireQuery: Return results
    end
    
    fireQuery->>Caller: Return processed query results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • PROP_NAME_RE regex pattern: Verify correctness of property name detection and ensure it handles edge cases (special characters, nested properties, etc.)
  • Property name remapping logic: Confirm the mapping construction and application correctly handles both namespaced and non-namespaced properties
  • Conflict detection semantics: Ensure the naming-conflict check correctly identifies when to use async.q versus fast.q and that the fallback logic is sound
  • API compatibility: Verify async.q and fast.q are used appropriately for local data querying and that results are compatible with existing calling code

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ENG-1044 Experiments with different datalog query modalities' directly aligns with the PR's objective and the main changes, which introduce a local query mode option to handle different datalog query modalities (async.q vs fast.q).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
apps/roam/src/utils/fireQuery.ts (4)

34-34: Add documentation for the new local flag.

Consider adding a JSDoc comment to explain what the local flag does and how it changes query execution behavior (e.g., uses Roam's local async/fast APIs instead of backend API, with automatic property name remapping).


308-308: Simplify the RegExp declaration.

The RegExp constructor is redundant when using a regex literal.

Apply this diff:

-const PROP_NAME_RE = new RegExp(/\:\w+\/\w+\b/, "g");
+const PROP_NAME_RE = /\:\w+\/\w+\b/g;

353-353: Verify the naming conflict detection logic.

The conflict detection checks if the number of unique short names equals the number of namespaced properties: Object.keys(propNamesSub).length === propNames.size. This assumes that if all short names are unique (no hash collisions), it's safe to use async.q with property renaming.

However, consider these edge cases:

  1. Multiple properties with the same namespace could have the same short name: :ns1/prop and :ns2/prop both map to "prop"
  2. The current logic would correctly detect this as a conflict, but ensure this is the intended behavior

The logic appears correct, but it would benefit from a comment explaining the conflict detection strategy.


357-370: Consider extracting renameProps as a module-level helper function.

The renameProps function is defined inline within the query execution logic. Extracting it would improve:

  • Testability: The recursive property renaming logic could be unit tested independently
  • Maintainability: The function could be reused if needed elsewhere
  • Readability: Reduces nesting in the already complex query execution flow

Example extraction:

const renamePropsInResult = (
  result: json | null,
  mapping: Record<string, string>
): json | null => {
  const rename = (x: json | null): json | null => {
    if (Array.isArray(x)) return x.map(rename);
    if (x === null || x === undefined) return x;
    if (typeof x === "object") {
      return Object.fromEntries(
        Object.entries(x as object).map(([k, v]) => [
          mapping[k] || k,
          rename(v),
        ]),
      );
    }
    return x;
  };
  return rename(result);
};

Then use it as: queryResults = renamePropsInResult(queryResults as json, propNamesSub) as unknown[][];

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08113a9 and 0c8157c.

📒 Files selected for processing (1)
  • apps/roam/src/utils/fireQuery.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx}: Prefer type over interface
Use explicit return types for functions
Avoid any types when possible

Files:

  • apps/roam/src/utils/fireQuery.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx,js,jsx}: Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use Prettier with the project's configuration
Maintain consistent naming conventions: PascalCase for components and types
Maintain consistent naming conventions: camelCase for variables and functions
Maintain consistent naming conventions: UPPERCASE for constants

Files:

  • apps/roam/src/utils/fireQuery.ts
apps/roam/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

apps/roam/**/*.{js,jsx,ts,tsx}: Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension
Use the roamAlphaApi documentation from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when working with the Roam API
Use Roam Depot/Extension API documentation from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when working with the Roam Extension API

Files:

  • apps/roam/src/utils/fireQuery.ts
🧠 Learnings (1)
📚 Learning: 2025-06-22T10:40:52.752Z
Learnt from: sid597
Repo: DiscourseGraphs/discourse-graph PR: 232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:18-31
Timestamp: 2025-06-22T10:40:52.752Z
Learning: In apps/roam/src/utils/getAllDiscourseNodesSince.ts, the user confirmed that querying for `?title` with `:node/title` and mapping it to the `text` field in the DiscourseGraphContent type is the correct implementation for retrieving discourse node content from Roam Research, despite it appearing to query page titles rather than block text content.

Applied to files:

  • apps/roam/src/utils/fireQuery.ts
🔇 Additional comments (3)
apps/roam/src/utils/fireQuery.ts (3)

17-17: LGTM!

The type import is appropriate for typing the property renaming logic introduced in the local query path.


357-369: Add explicit return type to renameProps function.

The inline renameProps function lacks an explicit return type, which violates the coding guidelines for TypeScript functions.

Apply this diff:

-        const renameProps = (x: json | null): json | null => {
+        const renameProps = (x: json | null): json | null => {

Wait, looking at the code again, it already seems to have the return type. Let me re-check... Actually, line 357 shows: const renameProps = (x: json | null): json | null => {. This already has an explicit return type, so this is fine.


345-374: Behavioral differences between async.q and fast.q cannot be verified—recommend manual testing.

The web search found no official Roam documentation explicitly describing these APIs. The differences are inferred from community code patterns only.

Beyond the lack of official documentation, the code itself reveals a potential inconsistency: results from async.q are passed through renameProps() to restore namespaced property names, but fast.q results skip this transformation entirely. This means the two code paths return objects with different property naming conventions, which could break downstream code expecting namespaced names.

Before merging, verify:

  • Whether both APIs return compatible data structures
  • Whether the fast.q branch intentionally skips property renaming or if this is a bug
  • Whether the caller expects consistent property naming regardless of which path executes

...inputs,
);
let queryResults: unknown[][] = [];
console.log("local", local);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove or guard the debug log statement.

This console.log will execute in production. Either remove it or move it inside the nodeEnv === "development" block (lines 335-341) to be consistent with the existing logging pattern.

Apply this diff to remove it:

-    console.log("local", local);

Or to guard it:

+    if (nodeEnv === "development") {
+      console.log("local:", local);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log("local", local);
// (code before line 344 remains unchanged)
🤖 Prompt for AI Agents
In apps/roam/src/utils/fireQuery.ts around line 344, there's an unguarded
console.log("local", local) that will run in production; remove this debug
statement or move it inside the existing nodeEnv === "development" block (lines
~335-341) so it only logs in development; if keeping the log, wrap it with a
check using the same nodeEnv variable or the existing logger so production
output is not affected.

@maparent maparent force-pushed the eng-1044-experiments-with-datalog-query-modalities branch from 0c8157c to 11e54c0 Compare November 27, 2025 21:13
@maparent maparent force-pushed the eng-1044-experiments-with-datalog-query-modalities branch from 11e54c0 to d0580a0 Compare December 10, 2025 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants