korma / Korma

Tasty SQL for Clojure.
http://sqlkorma.com
1.48k stars 222 forks source link

`(raw)` function producing strange results inside (set-fields) with Postgres #297

Closed Gastove closed 9 years ago

Gastove commented 9 years ago

Hallo!

First: <3 this project so hard. Korma has made life much, much nicer -- so thank you all for that!

Now: I'm getting something weird; likely, this is an I'm Doing it Wrong problem, but I've no idea what's going wrong. I'm using Korma 0.4.0 and Postgres 9.3; I'm attempting to update a tsvector column in a table, like so:

(update documents
           (set-fields {:search-vector (raw "to_tsvector('english', body)")})
           (where {:uri [like "%html"]}))

Except, when I call this, I get:

UPDATE "documents" SET "search_vector" = {:korma.sql.utils/pred #<engine$do_group korma.sql.engine$do_group@27a77760>, :korma.sql.utils/args [" AND " ({:korma.sql.utils/pred #<engine$do_infix korma.sql.engine$do_infix@707563fc>, :korma.sql.utils/args [{:korma.sql.utils/generated "\"documents\".\"generated\""} "=" "to_tsvector('english', body)"]})]}, "updated" = ? WHERE ("documents"."uri" LIKE ?)  ::  [#inst "2015-05-26T05:19:47.797000000-00:00" %html]
PSQLException:
 Message: ERROR: syntax error at or near "{"
  Position: 42
 SQLState: 42601
 Error Code: 0

It sure looks to me like Korma isn't fully generating the SQL. Supporting that theory: that SQL above is the same string I get out of calling sql-only on my Korma code.

What's gone sideways?

Gastove commented 9 years ago

Just noticed I'm 0.0.1 versions behind, so bumped to 0.4.1; sql-only still spits out this:

"UPDATE \"documents\" SET \"search_vector\" = {:korma.sql.utils/pred #<engine$do_group korma.sql.engine$do_group@2954b099>, :korma.sql.utils/args [\" AND \" ({:korma.sql.utils/pred #<engine$do_infix korma.sql.engine$do_infix@1bbff2ae>, :korma.sql.utils/args [{:korma.sql.utils/generated \"\\\"documents\\\".\\\"generated\\\"\"} \"=\" \"to_tsvector('english', body)\"]})]}, \"updated\" = ? WHERE (\"documents\".\"uri\" LIKE ?)"
immoh commented 9 years ago

That's weird, it seems to work fine when I try the exact same update in REPL:

(use 'korma.core)
May 26, 2015 9:42:17 AM com.mchange.v2.log.MLog <clinit>
INFO: MLog clients using java 1.4+ standard logging.
=> nil
(defentity documents)
=> #'user/documents
(sql-only (update documents
                  (set-fields {:search-vector (raw "to_tsvector('english', body)")})
                  (where {:uri [like "%html"]})))
=> "UPDATE \"documents\" SET \"search-vector\" = to_tsvector('english', body) WHERE (\"documents\".\"uri\" LIKE ?)"
Gastove commented 9 years ago

Huh! Okay. Well, I now have an even clearer idea of the problem I'm running in to. When I run what you did -- with an empty defentity -- I get the same result you did. But: my defentity isn't empty:

(defentity documents
  (table :documents)
  (prepare ->snake-keys)
  (prepare add-updated)
  (transform ->kebab-keys)
  (belongs-to tentacles)
  (entity-fields :name :uri :tentacle_name :body))

(The full code is [here](https://github.com/Gastove/doctopus/blob/postgres-fs-impl/src/doctopus/db.clj, if you're curious about anything.)

The problem actually seems to be the transform; if I comment that out, my code immediately works as expected; as long as it's there, I get my earlier, much stranger result.

immoh commented 9 years ago

The problem appears to be

  (prepare ->snake-keys)

which transforms

{:search-vector {:korma.sql.utils/generated "to_tsvector('english', body)"}}

to

{:search_vector {:generated "to_tsvector('english', body)"}}

and Korma doesn't recognize it as a raw sql value anymore.

You can fix it by modifying ->snake-keys so that it applies transforms only on the top level of the map, not nested values. I think there's no reason for users to use map as a value, but Korma does it internally to recognize special values such as raw sql.

Gastove commented 9 years ago

@immoh yep, you're right -- problem solved.

Thanks for the help!