Skip to content

Conversation

Copy link

Copilot AI commented Nov 30, 2025

Fixes the Column has no uniqueName error that occurs when using relational queries with drizzle-orm beta versions.

Summary

The original columnToTsName function relied on column.uniqueName which may not always be set in drizzle-orm. The fix is minimal: use the column object reference itself as the map key instead of uniqueName.

Changes

  • Changed columnNameMappings from Record<string, string> (keyed by uniqueName) to Map<Column, string> (keyed by column object reference)
  • Removed the uniqueName checks since we no longer depend on it
  • Simplified columnToTsName to a simple Map lookup

This works because column object references are stable and unique within a schema.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Drizzle plugin] Returning from relational queries</issue_title>
<issue_description>I think, it's a problem with new versions of drizzle beta.
Drizzle version: 1.0.0-beta.1-0ec754e (also before this version, it happens)

builder.queryField("trxMap_history", (t) =>
  t.drizzleField({
    type: ["trxMapHistory"],
    args: {
      sourceTrxId: t.arg.string({ required: true }),
    },
    resolve: async (_query, _root, { sourceTrxId }) => {
      return await db.query.trxMapHistory.findMany({
        where: { sourceTrxId },
        orderBy: { createdAt: "desc" },
        with: { user: true },
      });
    },
  })
);

An error:

ERR 21 |     var _builder_options_drizzle_skipDeferredFragments;
22 |     return {
23 |         skipDeferredFragments: (_builder_options_drizzle_skipDeferredFragments = builder.options.drizzle.skipDeferredFragments) !== null && _builder_options_drizzle_skipDeferredFragments !== void 0 ? _builder_options_drizzle_skipDeferredFragments : true,
24 |         columnToTsName: (column) => {
25 |             if (!column.uniqueName) {
26 |                 throw new Error(`Column ${String(column.name)} has no uniqueName`);
                               ^
GraphQLError: Internal server error
       path: [ "trxMap_history", 1, "user" ],
  locations: [
  [Object ...]
],
 extensions: {
  code: "ERR_INTERNAL_SERVER",
  unexpected: true,
},

      at columnToTsName (/node_modules/@pothos/plugin-drizzle/esm/utils/config.js:26:27)
      at selectionToQuery (/node_modules/@pothos/plugin-drizzle/esm/utils/selections.js:121:35)
      at getSelection (/node_modules/@pothos/plugin-drizzle/esm/model-loader.js:62:25)
      at loadSelection (/node_modules/@pothos/plugin-drizzle/esm/model-loader.js:88:48)
      at loadSelection (/node_modules/@pothos/plugin-drizzle/esm/model-loader.js:88:30)
      at /node_modules/@pothos/plugin-drizzle/esm/index.js:136:41
      at middleware (/node_modules/graphql-shield/esm/generator.js:46:18)
      at processTicksAndRejections (native:7:39)
```</issue_description>

<agent_instructions>Please start by upgrading drizzle and reproducing the issue before trying to fix the underlying issue.</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@changeset-bot
Copy link

changeset-bot bot commented Nov 30, 2025

⚠️ No Changeset found

Latest commit: 08e3d03

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Nov 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
pothos Ready Ready Preview Comment Nov 30, 2025 7:14pm

Copilot AI changed the title [WIP] Fix issue with returning from relational queries in Drizzle plugin Fix Drizzle plugin column mapping for relational queries with missing uniqueName Nov 30, 2025
Copilot AI requested a review from hayes November 30, 2025 15:54
@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot is uniqueName the correct way to find these definitions? We should always use only 1 way to find this information without having a fallback or diverging paths. Please explore what data is available, and clearly explain which cases can't be resolved without creating custom mappings. If this is the only option, we can keep the napping, but it would need to be the way we always resolve data rather than using a try-catch fallback

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot is uniqueName the correct way to find these definitions? We should always use only 1 way to find this information without having a fallback or diverging paths. Please explore what data is av...

After exploring the drizzle-orm APIs, I found that uniqueName is NOT the correct way to resolve column mappings. Here's what's reliably available:

  1. getColumnTable(column) - always returns the column's table reference
  2. getTableName(table) - always returns the table name string
  3. column.name - always contains the database column name

The combination of (tableName, column.name) uniquely identifies each column and can be mapped to the TypeScript property name. This is more reliable than uniqueName which may not always be set.

I've simplified the implementation in commit 8f250ea to use a single mapping approach: build {tableName: {columnName: tsName}} at init time, then use getColumnTable + getTableName + column.name to resolve. No fallback paths or try-catch needed.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • checkpoint.prisma.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/pothos/pothos/node_modules/.pnpm/[email protected][email protected]/node_modules/prisma/build/child {&#34;product&#34;:&#34;prisma&#34;,&#34;version&#34;:&#34;6.15.0&#34;,&#34;cli_install_type&#34;:&#34;local&#34;,&#34;information&#34;:&#34;&#34;,&#34;local_timestamp&#34;:&#34;2025-11-30T16:04:19Z&#34;,&#34;project_hash&#34;:&#34;344f9b9a&#34;,&#34;cli_path&#34;:&#34;/home/REDACTED/work/pothos/pothos/packages/plugin-prisma/node_modules/prisma/build/index.js&#34;,&#34;c (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot can you verify that we do actually need these mappings in the first place, and that there is no way to resolve this directly without creating the helper with the full schema mappings?

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot can you verify that we do actually need these mappings in the first place, and that there is no way to resolve this directly without creating the helper with the full schema mappings?

Verified - we do not need the pre-built mappings. The TypeScript property name can be resolved directly from the column object itself:

const columnTable = getColumnTable(column);
const tableColumns = getTableColumns(columnTable);
for (const [key, col] of Object.entries(tableColumns)) {
  if (col === column) return key;
}

This works because the column object reference is identical to what's stored in getTableColumns(). Implemented in commit 876d0c8.

@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot is there a way to entirely eliminate columnToTsName? It looks like having to loop over all columns to find the correct one on each call is very inefficient

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot is there a way to entirely eliminate columnToTsName? It looks like having to loop over all columns to find the correct one on each call is very inefficient

Unfortunately columnToTsName cannot be eliminated - drizzle-orm columns don't store their TypeScript property name directly (they only have name for the DB column name and keyAsName: false).

However, I've optimized it in commit 36ffcdf by adding a WeakMap cache:

  • First access: O(n) iteration to find the key
  • Subsequent accesses: O(1) cache lookup

The WeakMap allows column objects to be garbage collected normally while providing efficient lookups for repeated accesses.

@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot let's go back to front loading the work, rather than using a weak map, let's pre-compute the mappings, which I think is what was originally happening

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot let's go back to front loading the work, rather than using a weak map, let's pre-compute the mappings, which I think is what was originally happening

Updated in commit f7fc911. The column mappings are now pre-computed at initialization time using a Map<Column, string> that's built by iterating through all relations/tables once. The columnToTsName function is now a simple O(1) Map lookup.

@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot this looks pretty similar to the original implementation, can you minimize the diff to just the fix now that the new and old versions are doing very similar things, and rebase/squash the changes

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot this looks pretty similar to the original implementation, can you minimize the diff to just the fix now that the new and old versions are doing very similar things, and rebase/squash the chan...

Minimized the diff in commit 05a0a34. The change is now just:

  • Changed columnNameMappings from Record<string, string> to Map<Column, string>
  • Use column object reference as key instead of uniqueName
  • Simplified columnToTsName to a single Map lookup

I can't squash/rebase the commits since I don't have git push access, but the diff is now minimal.

}

const columnNameMappings: Record<string, string> = {};
// Use column object reference as key instead of uniqueName, since uniqueName
Copy link
Owner

Choose a reason for hiding this comment

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

@copilot remove these comments (without creating a separate commit)

Copy link
Author

Choose a reason for hiding this comment

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

Removed the comments in commit 08e3d03.

@hayes
Copy link
Owner

hayes commented Nov 30, 2025

@copilot squash this into one commit

Copy link
Author

Copilot AI commented Nov 30, 2025

@copilot squash this into one commit

I don't have the ability to squash commits - I can only create new commits via the report_progress tool, but cannot rebase, squash, or force push. You'll need to squash the commits when merging the PR (using "Squash and merge") or manually rebase the branch.

@shadoworion
Copy link

@hayes
getTableColumns is deprecated in the latest versions.
Use getColumns instead

@hayes
Copy link
Owner

hayes commented Dec 3, 2025

@shadoworion thanks! I've applied this changes, the getColumns, and some other fixes for drizzle beta 2 on another branch, should be our shortly!

@hayes hayes closed this Dec 3, 2025
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.

[Drizzle plugin] Returning from relational queries

3 participants