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]: Type error with postgresjs strings/dates in version 0.30 #1993

Open
jam-fran opened this issue Mar 11, 2024 · 6 comments
Open

[BUG]: Type error with postgresjs strings/dates in version 0.30 #1993

jam-fran opened this issue Mar 11, 2024 · 6 comments
Labels

Comments

@jam-fran
Copy link

What version of drizzle-orm are you using?

0.30.1

What version of drizzle-kit are you using?

0.20.14

Describe the Bug

I'm using Drizzle with postgresjs and recently updated to v0.30.1, where I know the driver was updated to always return strings for dates.

Many of my queries then failed with an error ERR_INVALID_ARG_TYPE: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Date".

Here's an example of a failed query that produced that error message:

const startDate = subDays(new Date(), 30) // Date object

const results = await db
  .select({
    id: sessions.id,
    userId: sessions.userId,
  })
  .from(sessions)
  .where(gte(sessions.timestamp, startDate))

Where sessions.timestamp is defined as timestamp('timestamp', { mode: 'date', withTimezone: true }) in my schema.

When I convert startDate to a string with .toISOString(), the query works, but I get the following type error:

No overload matches this call.
  Overload 1 of 3, '(left: PgColumn<{ name: "timestamp"; tableName: "sessions"; dataType: "date"; columnType: "PgTimestamp"; data: Date; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>, right: Date | SQLWrapper): SQL<...>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'Date | SQLWrapper'.
  Overload 2 of 3, '(left: Aliased<string>, right: string | SQLWrapper): SQL<unknown>', gave the following error.
    Argument of type 'PgColumn<{ name: "timestamp"; tableName: "sessions"; dataType: "date"; columnType: "PgTimestamp"; data: Date; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>' is not assignable to parameter of type 'Aliased<string>'.
      Type 'PgColumn<{ name: "timestamp"; tableName: "sessions"; dataType: "date"; columnType: "PgTimestamp"; data: Date; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>' is missing the following properties from type 'Aliased<string>': sql, fieldAlias
  Overload 3 of 3, '(left: never, right: unknown): SQL<unknown>', gave the following error.
    Argument of type 'PgColumn<{ name: "timestamp"; tableName: "sessions"; dataType: "date"; columnType: "PgTimestamp"; data: Date; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>' is not assignable to parameter of type 'never'.ts(2769)

Any tips would be appreciated. Thank you!

Expected behavior

No response

Environment & setup

No response

@gp27
Copy link

gp27 commented Mar 24, 2024

I am having the same issue on version 0.30.4 when i pass Date objects to queries. The last version on which passing a Date worked correctly was 0.29.3

@jam-fran
Copy link
Author

@gp27 Please keep me posted if you find a solution or workaround for this. I'm surprised that more people don't appear to be experiencing this since it's such a basic use case, so I feel like I must be overlooking something obvious.

@jam-fran
Copy link
Author

jam-fran commented Apr 3, 2024

Quick update - I've narrowed down the source of the issue to instances where a date is passed to the sql operator, either directly (sql`${dateHereWillBreakThings}) or in a sql.placeholder(date). Doing that worked in v 0.29.x, but not in 0.30.x.

It still works to pass a date to a filter operator (e.g. gte(sessions.timestamp, startDate)).

The workaround that worked for me for now is to convert any dates used with the sql operator to strings, like sql`${date.toISOString()}.

@gp27
Copy link

gp27 commented Apr 21, 2024

I tried to investigate this issue further.
I think it has been introduced with this PR #1659, which fixed an issue with the postgres driver where timestamps with mode "string" that should have been returned by queries as string values, were actually parsed into Date objects.

When the parsers for timezone related types were switched, so were the serializers:
https://github.com/Angelelz/drizzle-orm/blob/b29a5e1a837cbbb45be5e2caf3564c0493c28d08/drizzle-orm/src/postgres-js/driver.ts#L28

The replacements of those serializers is probably what is causing this issue and #2009 as well.

I am not sure it was necessary to replace the serialziers as well, since the issue was on the parsing side, but I may be wrong. Maybe @Angelelz who authored the fix might have some further info about it.

@Angelelz
Copy link
Collaborator

The replacement of the serializer and parsers was necessary to guarantee that the same parsing/serializer code from Drizzle will work for both postgres.js and node-PG interchangeably. Unfortunately I have very little time lately to dedicate to drizzle but if somebody puts together a quick reproduction it will make it easier to investigate/fix.

@erkstruwe
Copy link

Until this is solved, a temporary workaround is to create a custom type:

import { customType } from "drizzle-orm/pg-core"

export const customDate = customType<{
    data: string
    driverData: Date
}>({
    dataType() {
        return "date"
    },
    fromDriver(value: Date): string {
        return value.toISOString().slice(0, 10)
    },
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants