drizzle-orm icon indicating copy to clipboard operation
drizzle-orm copied to clipboard

[BUG]: value.getTime is not a function

Open hmh6a opened this issue 1 year ago • 11 comments

What version of drizzle-orm are you using?

0.30.10

What version of drizzle-kit are you using?

0.21.2

Describe the Bug

Bug Report: Error when using time-related queries

Description

When attempting to use time-related queries with drizzle-kit, I encounter an error. Specifically, the error occurs when trying to fetch records from the visits table where the createdAt timestamp is greater than or equal to the current time.

Code Snippets

Here is the code that produces the error:

const visits = await db.query.visits.findMany({
    where: gte(tables.visits.createdAt, Date.now()),
})

Schema definition for the visits table:

export const visits = sqliteTable('visits', {
    id: integer('id').primaryKey({ autoIncrement: true }),
    // ....
    createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(new Date().getTime()),
})

Error Message

Error: value.getTime is not a function

Expected behavior

No response

Environment & setup

No response

hmh6a avatar May 15 '24 12:05 hmh6a

I don't have any issues with filtering, for your example, does gte(tables.visits.createdAt, new Date()) work?

I am getting the same error, TypeError: value.getTime is not a function, but only when updating. Here is my database schema.

    createdDate: integer("created_date", { mode: "timestamp" })
      .default(sql`(unixepoch())`)
      .notNull(),
    updatedDate: integer("updated_date", { mode: "timestamp" })
      .$onUpdate(() => sql`(unixepoch())`)
      .notNull(),

I suspect there is some epoch time vs JS date type issue. .$onUpdate(() => new Date()) works and so does setting it when updating with updatedDate: sql(unixepoch())``. It is just odd that it doesn't work in the schema onUpdate function.

magicalpuffin avatar May 27 '24 23:05 magicalpuffin

@magicalpuffin

You should change type from integer into text My problem solved like this

hmh6a avatar May 27 '24 23:05 hmh6a

@magicalpuffin I've got the same issue. I was happy to see that they added onUpdate but after refactoring to take advantage of it, I realized it didn't work on timestamps so I'm back to manually pushing updateOn values until it gets fixed.

I also don't want a text column, because it's a timestamp, not text.

bruceharrison1984 avatar May 31 '24 15:05 bruceharrison1984

Hopefully we see a fix soon, this one's really annoying.

Whats-A-MattR avatar Jun 30 '24 10:06 Whats-A-MattR

I did find what seems to be a way to do it. As long as you're okay with epoch time.

export const tableName = sqliteTable("tablename", {
    id: ...,
    updated_at: integer("updated_at", { mode: "timestamp_ms" })
        .$onUpdateFn(() => new Date()).$type<Date>(),
    otherFields: ...
}

I've only tested this with SQLite, but it seems to be working for me.

Whats-A-MattR avatar Jul 01 '24 05:07 Whats-A-MattR

The problem is the value is something like:

{"decoder":{},"shouldInlineParams":false,"queryChunks":[{"value":["(CURRENT_TIMESTAMP)"]}]}

So I just changed the line in 103 to: const unix = value?.getTime?.() ?? Date.now();

I'm not sure why it's doing this and didn't have time to look into it further but here is a quick workaround.

Here is my patch file.

diff --git a/node_modules/drizzle-orm/sqlite-core/columns/integer.cjs b/node_modules/drizzle-orm/sqlite-core/columns/integer.cjs
index b3d1837..56eaf41 100644
--- a/node_modules/drizzle-orm/sqlite-core/columns/integer.cjs
+++ b/node_modules/drizzle-orm/sqlite-core/columns/integer.cjs
@@ -100,7 +100,7 @@ class SQLiteTimestamp extends SQLiteBaseInteger {
     return new Date(value);
   }
   mapToDriverValue(value) {
-    const unix = value.getTime();
+    const unix = value?.getTime?.() ?? Date.now();
     if (this.config.mode === "timestamp") {
       return Math.floor(unix / 1e3);
     }
diff --git a/node_modules/drizzle-orm/sqlite-core/columns/integer.js b/node_modules/drizzle-orm/sqlite-core/columns/integer.js
index fa17466..06ebb75 100644
--- a/node_modules/drizzle-orm/sqlite-core/columns/integer.js
+++ b/node_modules/drizzle-orm/sqlite-core/columns/integer.js
@@ -68,7 +68,7 @@ class SQLiteTimestamp extends SQLiteBaseInteger {
     return new Date(value);
   }
   mapToDriverValue(value) {
-    const unix = value.getTime();
+    const unix = value?.getTime?.() ?? Date.now();
     if (this.config.mode === "timestamp") {
       return Math.floor(unix / 1e3);
     }

grantbi avatar Aug 10 '24 07:08 grantbi

Confirming that @grantbi's patch resolve the issue.

tijptjik avatar Aug 27 '24 06:08 tijptjik

I think only the generated typing is wrong. When I ignore the Typescript errors and just pass in Date objects, it just works.

Edit: Using sqlite and fields like integer("updated_at", { mode: "timestamp_ms" })

m9tdev avatar Sep 11 '24 18:09 m9tdev

I have a similar issue.

For this schema:

export const things = sqliteTable("things", {
  id: text("id", { length: 21 })
    .primaryKey()
    .$defaultFn(() => nanoid()),
  validFrom: integer("valid_from", { mode: "timestamp" })
    .notNull()
    .default(sql`(unixepoch())`),
  validTo: integer("valid_to", { mode: "timestamp" }),
});

running this update fails:

db.update(things)
  .set({
    validTo: new Date(),
  })
  .where(eq(things.id,'1'));

with the same error:

Error: value.getTime is not a function

pieterbeulque avatar Sep 16 '24 11:09 pieterbeulque

My issue above was not the problem, I removed the actual bug in my minimal reproduction.

I had another updatedAt column that had a .$onUpdateFn(() => sql`(unixepoch())`) which caused the issue, replacing that with .$onUpdateFn(() => new Date()) fixed it.

pieterbeulque avatar Sep 17 '24 07:09 pieterbeulque

My issue above was not the problem, I removed the actual bug in my minimal reproduction.

I had another updatedAt column that had a .$onUpdateFn(() => sql`(unixepoch())`) which caused the issue, replacing that with .$onUpdateFn(() => new Date()) fixed it.

Thanks, that seemed to resolve it for me too.

harrisonhoward avatar Sep 28 '24 11:09 harrisonhoward