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

[BUG]:Error Typescript for query where in relation (version "drizzle-orm": "^0.38.3") #3911

Open
1 task done
Kokleng-Dev opened this issue Jan 7, 2025 · 4 comments · May be fixed by #4011
Open
1 task done

[BUG]:Error Typescript for query where in relation (version "drizzle-orm": "^0.38.3") #3911

Kokleng-Dev opened this issue Jan 7, 2025 · 4 comments · May be fixed by #4011
Labels
bug Something isn't working priority Will be worked on next rqb relational queries

Comments

@Kokleng-Dev
Copy link

Report hasn't been filed before.

  • I have verified that the bug I'm about to report hasn't been filed before.

What version of drizzle-orm are you using?

0.38.3

What version of drizzle-kit are you using?

^0.30.1

Other packages

No response

Describe the Bug

Screenshot 2025-01-07 at 6 01 48 in the evening Screenshot 2025-01-07 at 6 01 57 in the evening

it is work fine for one-many but one-to-one it is error typescript.
However it is error of typescript but it working fine in process.

@Kokleng-Dev Kokleng-Dev added the bug Something isn't working label Jan 7, 2025
@Kokleng-Dev Kokleng-Dev reopened this Jan 7, 2025
@Kokleng-Dev
Copy link
Author

+1

@ramipellumbi
Copy link

Also noted this just now. In the relation types:

export type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many', TIsRoot extends boolean = boolean, TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = {
    columns?: {
        [K in keyof TTableConfig['columns']]?: boolean;
    } | undefined;
    with?: {
        [K in keyof TTableConfig['relations']]?: true | DBQueryConfig<TTableConfig['relations'][K] extends One ? 'one' : 'many', false, TSchema, FindTableByDBName<TSchema, TTableConfig['relations'][K]['referencedTableName']>> | undefined;
    } | undefined;
    extras?: Record<string, SQL.Aliased> | ((fields: Simplify<[
        TTableConfig['columns']
    ] extends [never] ? {} : TTableConfig['columns']>, operators: {
        sql: Operators['sql'];
    }) => Record<string, SQL.Aliased>) | undefined;
} & (TRelationType extends 'many' ? {
    where?: SQL | undefined | ((fields: Simplify<[
        TTableConfig['columns']
    ] extends [never] ? {} : TTableConfig['columns']>, operators: Operators) => SQL | undefined);
    orderBy?: ValueOrArray<AnyColumn | SQL> | ((fields: Simplify<[
        TTableConfig['columns']
    ] extends [never] ? {} : TTableConfig['columns']>, operators: OrderByOperators) => ValueOrArray<AnyColumn | SQL>) | undefined;
    limit?: number | Placeholder | undefined;
} & (TIsRoot extends true ? {
    offset?: number | Placeholder | undefined;
} : {}) : {});

Note how the where is only defined as a valid key when TRelationType extends 'many'. I will open a PR for this.

@ramipellumbi
Copy link

ramipellumbi commented Jan 26, 2025

Leaving a follow up comment as adding just the typing does not exactly completely resolve the issue. What is happening underneath the hood is some confusing behavior in this case.

Consider the following simple example:

// schemas.ts
import {
  pgTable,
  varchar,
  timestamp,
  text,
  integer,
  uniqueIndex,
  foreignKey,
  boolean,
  index,
  primaryKey,
} from "drizzle-orm/pg-core";
import { relations, sql } from "drizzle-orm";

export const location = pgTable(
  "location",
  {
    id: text().primaryKey().notNull(),
    name: text().notNull(),
  },
);

export const bedAssignment = pgTable(
  "bed_assignment",
  {
    id: text().primaryKey().notNull(),
    startDate: text("start_date").notNull(),
    endDate: text("end_date"),
    clientId: text("client_id").notNull(),
    bedId: text("bed_id").notNull(),
  },
  (table) => [
    foreignKey({
      columns: [table.clientId],
      foreignColumns: [client.id],
      name: "bed_assignment_client_id_fkey",
    })
      .onUpdate("cascade")
      .onDelete("restrict"),
    foreignKey({
      columns: [table.bedId],
      foreignColumns: [bed.id],
      name: "bed_assignment_bed_id_fkey",
    })
      .onUpdate("cascade")
      .onDelete("restrict"),
  ],
);

export const client = pgTable(
  "client",
  {
    id: text().primaryKey().notNull(),
    locationId: text("location_id"),
  },
  (table) => [
    index("client_id_idx").using("btree", table.id.asc().nullsLast().op("text_ops")),
    foreignKey({
      columns: [table.locationId],
      foreignColumns: [location.id],
      name: "client_location_id_fkey",
    })
      .onUpdate("cascade")
      .onDelete("set null"),
  ],
);

export const bed = pgTable(
  "bed",
  {
    id: text().primaryKey().notNull(),
    locationId: text().notNull(),
  },
  (table) => [
    foreignKey({
      columns: [table.locationId],
      foreignColumns: [location.id],
      name: "bed_locationId_fkey",
    })
      .onUpdate("cascade")
      .onDelete("restrict"),
  ],
);

export const clientRelations = relations(client, ({ one, many }) => ({
  bedAssignments: many(bedAssignment),
  location: one(location, {
    fields: [client.locationId],
    references: [location.id],
  }),
}));

export const locationRelations = relations(location, ({ many }) => ({
  clients: many(client),
  beds: many(bed),
}));

export const bedRelations = relations(bed, ({ one, many }) => ({
  bedAssignments: many(bedAssignment),
  location: one(location, {
    fields: [bed.locationId],
    references: [location.id],
  }),
}));

export const bedAssignmentRelations = relations(bedAssignment, ({ one }) => ({
  client: one(client, {
    fields: [bedAssignment.clientId],
    references: [client.id],
  }),
  bed: one(bed, {
    fields: [bedAssignment.bedId],
    references: [bed.id],
  }),
}));

And suppose I do the following query:

const db = drizzle({
  connection: {
    connectionString: process.env.DATABASE_URL,
    ssl: process.env.NODE_ENV === "production",
  },
  schema: {
    location,
    bedAssignment,
    client,
    bed,
    locationRelations,
    clientRelations,
    bedRelations,
    bedAssignmentRelations,
  },
});

(async () => {
  const result = await db.query.client.findMany({
    with: {
      bedAssignments: {
        with: {
          bed: {
            where: (bed, { eq }) => eq(bed.locationId, "some-location-id"),
            // ^ this should omit bed assignments that have a bed that don't match the location id
          }
        }
      }
    }
  });
})()

But the expected behavior does not happen. Instead, I retrieve bedAssignments that have their bed property as null (but are not typed as such), which is very confusing behavior.

@L-Mario564 L-Mario564 added rqb relational queries priority Will be worked on next labels Jan 29, 2025
@MickL
Copy link

MickL commented Feb 7, 2025

I just opened an issue because the docs show a relation can be filtered while in reality they cant. From the docs:

await db.query.posts.findMany({
   where: (posts, { eq }) => (eq(posts.id, 1)),
      with: {
         comments: {
            where: (comments, { lt }) => lt(comments.createdAt, new Date()),
         },
      },
});

Seems like the docs are okay but this is an actual bug. Hope this gets fixed soon! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working priority Will be worked on next rqb relational queries
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants