Skip to content

⚡ Bolt: Optimize Prisma Export Dictionary Complexity - #1301

Open
seonghobae wants to merge 4 commits into
mainfrom
bolt-perf-prisma-16429897218157036046
Open

seonghobae wants to merge 4 commits into
mainfrom
bolt-perf-prisma-16429897218157036046

Conversation

@seonghobae

@seonghobae seonghobae commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

💡 What: Replaced the O(N * C * E) nested loop checking edge inclusions per column per node in Prisma export with an O(1) Map lookup. 🎯 Why: Iterating over every edge for every column causes massive overhead for large database schemas, slowing down exports and UI thread. 📊 Impact: Export generation on large graphs improved from 284ms to 91ms, scaling smoothly for massive schemas. 🔬 Measurement: Verify export speed scales linearly rather than exponentially.


PR created automatically by Jules for task 16429897218157036046 started by @seonghobae


Devin Review

@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 8 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a3d7c97b-21aa-4c97-ad43-ad4ea1dca059
📥 Commits

Reviewing files that changed from the base of the PR and between 8dc7469 and 1c7663d.

📒 Files selected for processing (2)
  • .jules/bolt.md
  • frontend/src/erd/prisma.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

Devin Review

};
edgesProcessed.set(edge.id, edgeInfo);

const sourceKey = `${edgeInfo.sourceModel}:${edgeInfo.sourceFields[0]}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Snapshot foreign keys lack forward relations

For normal snapshot edges, edgesProcessedBySource indexes encoded handles instead of column names. The field lookup uses sanitizeName(col.column_name), so exported Prisma models omit their forward relations.

Learn more

Graph edges created by snapshotToGraph use src-c-... handles from sourceColumnHandleId. The exporter removes src-, then indexes c_... after sanitization; a column named user_id is looked up as user_id. The original edge scan had the same mismatch, but the new index preserves it in the changed relation path. Back-relations are still emitted, leaving a broken one-sided Prisma relation.

Example: A posts.user_id foreign key gets handle src-c-0075-0073-0065-0072-005f-0069-0064. Its index key ends with c_0075_..., while the posts.user_id field lookup ends with user_id; no users_user_id relation field appears.

Recommended fix: Resolve sourceHandle and targetHandle against each node's columns using sourceColumnHandleId and targetColumnHandleId before building relation keys and references. Also support legacy unencoded handles where needed. Add a test with an edge returned by snapshotToGraph.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

for (const edgeInfo of fieldEdges) {
const relField = sanitizeName(edgeInfo.targetModel) + "_" + fieldName;
relationDef = `\n ${relField} ${edgeInfo.targetModel}${optional} @relation("${edgeInfo.relationName}", fields: [${fieldName}], references: [${edgeInfo.targetFields[0]}])`;
relationDef += `\n ${relField} ${edgeInfo.targetModel}${optional} @relation("${edgeInfo.relationName}", fields: [${fieldName}], references: [${edgeInfo.targetFields[0]}])`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Repeated foreign keys invalidate Prisma models

When two edges connect one source field to the same target model, relationDef emits both with the same name. Prisma rejects the duplicate field, whereas the previous exporter emitted only the last relation.

Learn more

Each matching edge contributes a Prisma relation field named from its target model and source field. Appending every matching edge creates the same field name twice when edges share both values. The previous exporter overwrote relationDef and produced just one forward field, even though it retained both back-relations.

Example: Two edges with different IDs use sourceHandle: 'src-user_id' from posts to users. Both generate users_user_id inside posts, and Prisma rejects the exported model as having duplicate fields.

Recommended fix: Decide how to represent multiple relations on the same scalar field, and ensure generated relation field names are unique and correspond to matching back-relations. Cover two edges with the same source field and target model in the exporter tests.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

relationName: relName
});
};
edgesProcessed.set(edge.id, edgeInfo);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Redundant edge index remains allocated

edgesProcessed has no readers after this change, but each edge still enters it. Large exports retain two edge indexes instead of one.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

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