Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

result extension that shadows a field of the same name causes Maximum call stack exceeded at runtime #16643

Closed
sbking opened this issue Dec 6, 2022 · 0 comments · Fixed by #17044
Assignees
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. tech/typescript Issue for tech TypeScript. topic: clientExtensions
Milestone

Comments

@sbking
Copy link

sbking commented Dec 6, 2022

Bug description

When a result extension adds a computed field that shadows a field of the same name, AND the extension field needs the shadowed field, the following error occurs:

RangeError: Maximum call stack size exceeded
    at Array.flatMap (<anonymous>)
    at /Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31121:48
    at Cache.getOrCreate (/Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31090:19)
    at resolveNeeds (/Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31119:18)
    at Array.flatMap (<anonymous>)
    at /Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31121:48
    at Cache.getOrCreate (/Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31090:19)
    at resolveNeeds (/Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31119:18)
    at Array.flatMap (<anonymous>)
    at /Users/stephen/Projects/prisma-client-extensions-shadowing/node_modules/@prisma/client/runtime/index.js:31121:48 {
  clientVersion: '4.7.1'
}

Here is where the issue actually happens:

https://github.com/prisma/prisma/blob/main/packages/client/src/runtime/core/extensions/resultUtils.ts#L58

(resolveNeeds doesn't check for cycles in the dependencies)

How to reproduce

Repository with a minimal reproduction and instructions in the README: https://github.com/sbking/prisma-client-extensions-shadowing

Expected behavior

A computed field should be able to shadow a field of the same name, and use the original value to compute the computed value.

This works at the type level - the extended client uses the data type returned by the computed field, not the type of the original field.

The TypeScript types also seem suggest that you can chain extensions that shadow the same computed field. This would be intuitive, but the docs suggest that the last extension always wins in the case of conflicts. See the inferred inlay hints in this screenshot:

Screen Shot 2022-12-05 at 5 43 04 PM

Prisma information

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["clientExtensions"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Post {
  id        String   @id @default(cuid())
  title     String
  createdAt DateTime @default(now())
}

Here is the extension code:

const prisma = new PrismaClient().$extends({
  name: "i18n",
  result: {
    post: {
      createdAt: {
        needs: { createdAt: true },
        compute(post) {
          return formatDistanceToNow(post.createdAt, { locale: de });
        },
      },
    },
  },
});

async function main() {
  const posts = await prisma.post.findMany({
    select: {
      title: true,
      createdAt: true,
    },
    take: 5,
  });

  for (const post of posts) {
    console.info(`- ${post.title} (${post.createdAt})`);
  }
}

And here is where the error occurs:

async function main() {
  const posts = await prisma.post.findMany({
    select: {
      title: true,
      createdAt: true,
    },
    take: 5,
  });

  for (const post of posts) {
    console.info(`- ${post.title} (${post.createdAt})`);
  }
}

Environment & setup

  • OS: macOS
  • Database: PostgreSQL
  • Node.js version: v18.10.0

Prisma Version

4.7.1
@sbking sbking added the kind/bug A reported bug. label Dec 6, 2022
@millsp millsp added team/client Issue for team Client. topic: clientExtensions tech/typescript Issue for tech TypeScript. bug/2-confirmed Bug has been reproduced and confirmed. process/candidate labels Dec 6, 2022
@SevInf SevInf self-assigned this Dec 28, 2022
SevInf added a commit that referenced this issue Dec 28, 2022
Was broken because of the 2 things:

1. Depenency resolution did not account for circualar dependencies
2. When building a query, all computed fields in selection were ignored,
   even if there is an actual DB field of the same name.

Fix #16643
SevInf added a commit that referenced this issue Jan 12, 2023
Was broken because of the 2 things:

1. Depenency resolution did not account for circualar dependencies
2. When building a query, all computed fields in selection were ignored,
   even if there is an actual DB field of the same name.

Fix #16643
SevInf added a commit that referenced this issue Jan 12, 2023
* fix: Allow result extensions to shadow fields

Was broken because of the 2 things:

1. Depenency resolution did not account for circualar dependencies
2. When building a query, all computed fields in selection were ignored,
   even if there is an actual DB field of the same name.

Fix #16643

* Fix shadowing already shadowed field
@SevInf SevInf added this to the 4.9.0 milestone Jan 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. tech/typescript Issue for tech TypeScript. topic: clientExtensions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants