drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
24.02k stars 608 forks source link

[BUG]: Placeholder does not work with Json for prepared statement #1117

Open Djboy08 opened 1 year ago

Djboy08 commented 1 year ago

What version of drizzle-orm are you using?

^0.28.2

What version of drizzle-kit are you using?

^0.19.12

Describe the Bug

Creating a prepared statement and using placeholder for dynamic data that is JSON does not work properly. It just makes a json of {"name":"data"}

Expected behavior

The placeholder should fill in the JSON into the proper type that the database will take the json in as.

Environment & setup

Windows 11 Node v18.17.0

Angelelz commented 10 months ago

Can you show the query that you were attempting to prepare?

ghosh commented 9 months ago

I am facing the same issue.

This is a simplified version of my prepared statement:

const saveData = db.
  insert(tableName)
  .values({
    jsonData: sql.placeholder("jsonData")
  })
  .prepare()

This is how I am calling it:

// Neither of these work
await saveData.execute({ jsonData: jsonData })
await saveData.execute({ 
  jsonData: JSON.stringify(jsonData)
})

Finally this is what shows up in the json column in the db:

{"name": "jsonData"}
lhjt commented 6 months ago

I also have the same issue when trying to store jsonb content with postgres and using the postgres.js connector.

Versions:

Here's a version of my prepared statement:

const preparedUpdateStory = db
  .update(stories)
  .set({ story: sql.placeholder("storyContent") })
  .where(eq(stories.id, sql.placeholder("storyID")))
  .prepare("updateStory");

Call site:

  await preparedUpdateStory.execute({
    storyContent: content,
    storyID: sID.toUUID(),
  });

What the DB shows:

{"name": "storyContent"}

Log output from drizzle:

Query: update "stories" set "story" = $1 where "stories"."id" = $2 -- params: ["{\"name\":\"storyContent\"}", "some-uuid"]
L-Mario564 commented 1 week ago

It seems like Drizzle is not checking for Placeholder and only checks for object. Since a class instance is an object when doing typeof, it inserts the instance rather than the actual data passed to the placeholder.