layerware/hugsql

def-sqlvec-fns hardcoded to take a resource

henryw374 opened this issue · 9 comments

I'm looking to reuse some snippets, so a way to do that currently would be to prepare a file for input to def-sqlvec-fns. but... i dont really want to write this out to a file first. Ideally def-sqlvec-fns would accept a stream or string as well, or just delegate to another macro that accepts parsed defs etc.

Why don't you want to write it out to a file?

well, since the file is read by hugsql from the classpath i think there would need to be a build step to create it before deployment which is possible... but seems a bit of a hassle.

I'm open to this enhancement. It would allow defining of hugsql functions coming from other sources than files (databases and others). I don't think I'd overload def-sqlvec-fns. I'll likely create another function/macro that takes a string or java.io.Reader.

@ohlo, an undocumented feature of def-db-fns and def-sqlvec-fns is that they can take a java.io.File object that has a path outside of the classpath. It's undocumented because I wasn't sure if I wanted to keep this functionality, but now I think I probably do. You might give it a go until the 0.4.x release hits with your requested enhancement.

thanks for the info. but... there seems to be a bug with that:

(condp isa? file
        java.io.File file ; already file
        java.net.URL file ; already resource
        ; assume resource path (on classpath)
        (if-let [f (io/resource file)]
          f
          (throw (ex-info (str "Can not read file: " file) {}))) 
        )

i think it should be instance? not isa? ... so. even if passing in a file it falls through to last statement.

I think this is actually a macro issue leading to the condp fall-through. Looks like it was introduced with this commit: 79a1020

So, this will have to wait just a bit. I should have more bandwidth to tackle this in a few days.

Thanks for the report!

that's ok, I have a workaround.

before calling (eval (list 'hugsql/def-db-fns my-temp-file))
in my code, i redefine the problem fn to use instance?

(in-ns 'hugsql.core)

;; temp redef of file. bug should be fixed shortly https://github.com/layerware/hugsql/issues/16
(defn ^:no-doc parsed-defs-from-file
  "Given a hugsql SQL file, parse it,
   and return the defs."
  [file]
  (parser/parse
    (slurp
      (condp instance? file
        java.io.File file ; already file
        java.net.URL file ; already resource
        ; assume resource path (on classpath)
        (if-let [f (io/resource file)]
          f
          (throw (ex-info (str "Can not read file: " file) {})))))))

which works :-)

Yes, instance? is correct. (My error is a direct result of my Ruby history where is_a? and instance? differ from Clojure's semantics).

When I fix this and make support of java.io.File official, it will include docs and a test to prevent regressions. Thanks!

As of the 0.4.0 release, you now have more options for defining database functions:

def-db-fns-from-string and def-sqlvec-fns-from-string take a HugSQL flavored string.

def-db-fns and def-sqlvec-fns now accept an existing java.io.File object properly.

The 0.4.0 refactor also added several functions that operate on individual SQL statements instead of entire files. See Other Useful Functions