drizzle-orm
drizzle-orm copied to clipboard
[BUG]: timestamp mode 'date' returns value.toISOString is not a function for parameterized inserts
What version of drizzle-orm are you using?
0.28.5
What version of drizzle-kit are you using?
0.19.13
Describe the Bug
Trying to do a sql.placeholder of a timestamp mode 'date' returns value.toISOString is not a function at compile time. When I first load my page presumably it is doing the prepared statement and throwing error. Mode 'string' seems to work.
export const TaskTable = pgTable('task', {
....
title: varchar('name', { length: 256 }).notNull(),
dueDate: timestamp('due_date', { mode: 'date' } )
});
const preparedInsert = db
.insert(TaskTable)
.values({
title: sql.placeholder('title'), // works
dueDate: sql.placeholder('dueDate'), // crashes
})
.returning()
.prepare('Task.create');
Exception
- error Error [TypeError]: value.toISOString is not a function
at PgTimestamp.mapToDriverValue (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:1363:68)
at eval (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:3785:81)
at Array.map (<anonymous>)
at SQL.buildQueryFromSourceParams (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:3724:36)
at eval (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:3754:29)
at Array.map (<anonymous>)
at SQL.buildQueryFromSourceParams (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:3724:36)
at eval (webpack-internal:///(rsc)/./node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/alias-a0c6a0a1.mjs:3757:29)
at Array.map (<anonymous>)
Note that this seems to work around it at parameterization:
dueDate: sql`${sql.placeholder('dueDate')}`,
or in schema switch to string mode:
dueDate: timestamp('due_date', { mode: 'string' } )
Expected behavior
I would expect placeholders of timestamp to not try to do toISOString.
Environment & setup
Windows. Postgres 15.
This is likely related to the issue I created.
When we set mode to string, TypeScript shows the return type as string, however a date object is returned. I suspect the inverse might happen with string mode.
any updates ?
"drizzle-orm/mysql-core"'s datetime have same problem.
Same error on Version 0.29.0 👎
Releated: https://github.com/drizzle-team/drizzle-orm/issues/1407
I tried to change from:
createdAt: timestamp("created_at", { mode: "string" })
To:
createdAt: text("created_at"),
But i get a still a Date object. Drizzle is so crazy
had this error, but was a user land error, double check what you are passing
still happening in 0.31.0 for me. having to use expiresAt: sql`${sql.placeholder("expiresAt")}`, because otherwise the toIsoString error happens.
but now excluded on onConflictDoUpdate doesn't work.
.onConflictDoUpdate({target: [...], set: { ... expiresAt: sql`'excluded.expiresAt'`},)
I have to use the single quotes because otherwise postgres throws this error:
[...] column excluded.expiresat does not exist [...]
code: '42703',
hint: 'Perhaps you meant to reference the column "excluded.expiresAt".',
position: '210',
file: 'parse_relation.c',
line: '3720',
routine: 'errorMissingColumn'
But now postgres tells me
invalid input syntax for type timestamp with time zone: "excluded.expiresAt"
@AndriiSherman any ideas?
I had the same issue in "drizzle-orm": "^0.31.2".
In order to workaround it, I had to create a new instance of Date when I set the value. The property communication.creationDate was already type Date and it had the proper values, but without the new Date, I had the error "value.toISOString is not a function"
await db.insert(communicationsSchema).values({
id: communication.id,
content: communication.content,
creationDate: new Date(communication.creationDate),
});
This issue is also present in queries and using the magic sql string operator is a workaround.
Works when I change folder node_mules/drizzle-orm/pg-core/columns change files: timestamp.js, timestamp.cjs
from
mapToDriverValue = (value) => {
return value.toISOString
};
to
mapToDriverValue = (value) => {
return value
};
works in update and onConflictDoUpdate
"drizzle-orm": "^0.32.0", "drizzle-kit": "^0.23.0",
same
Hello, drizzle-orm/pg-core seems to have the same issue
Based on this issue I did this as a temporal solution https://github.com/drizzle-team/drizzle-orm/issues/1113#issuecomment-2244273171
script.js
const fs = require('fs');
const path = require('path');
const filesToModify = [
'node_mules/drizzle-orm/pg-core/columns/timestamp.js',
'node_mules/drizzle-orm/pg-core/columns/timestamp.cjs'
];
filesToModify.forEach((file) => {
const filePath = path.join(__dirname, file);
console.log(`Checking path: ${filePath}`);
if (fs.existsSync(filePath)) {
let fileContent = fs.readFileSync(filePath, 'utf8');
fileContent = fileContent.replace(
'return value.toISOString()',
'return value'
);
fs.writeFileSync(filePath, fileContent, 'utf8');
console.log(`Modified: ${file}`);
} else {
console.error(`File not found: ${filePath}`);
}
});
I implement this in a postinstall script package.json
"postinstall": "node ./script.js",
Note: The versions that I mention are "drizzle-orm": "^0.32.1", "drizzle-kit": "^0.23.1",
Super weird - i'm also seeing this error. All im trying to do is set the value of a timestamp date mode field to the value of an existing table column (which is also a timestamp date mode field) and yet when i try and pass table.timestampfield (which should be a date), its actually a string!
Similar issue here, but not using prepared statements.
When I changed my table definition from
updatedAt: timestamp("updated_at", { mode: "string" })
.defaultNow()
.$onUpdate(() => sql`CURRENT_TIMESTAMP`),
to
updatedAt: timestamp("updated_at")
.defaultNow()
.$onUpdate(() => sql`CURRENT_TIMESTAMP`),
Notice that I removed the "mode: string" option.
Updating a row results in an Exception:
TypeError: value.toISOString is not a function
at PgTimestamp.mapToDriverValue (webpack-internal:///(action-browser)/./node_modules/.pnpm/[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/pg-core/columns/timestamp.js:44:18)
at eval (webpack-internal:///(action-browser)/./node_modules/.pnpm/[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/sql/sql.js:146:73)
at Array.map (<anonymous>)
at SQL.buildQueryFromSourceParams (webpack-internal:///(action-browser)/./node_modules/.pnpm/[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/drizzle-orm/sql/sql.js:99:32)
Based on how my column is defined, it was expecting a "date" value as the result of the .onUpdate function in the second case.
Solution
Choose the correct combination
updatedAt: timestamp("updated_at", { mode: "string" }).$onUpdate(() => sql`CURRENT_TIMESTAMP`),
updatedAt: timestamp("updated_at", { mode: "date" }).$onUpdate(() => new Date()),
docs: https://orm.drizzle.team/learn/latest-releases/drizzle-orm-v0305#onupdate-functionality-for-postgresql-mysql-and-sqlite