Reputation: 1556
I'm struggling to get the correct type hints to avoid a warn on reflection while writing text-file-output from a database query.
I've tried to put ^String type hints before each function being called, as ultimately the output is going to hit a text file on disk.
The reflection warning occurs on the :row-fn line towards the end of the function. I have the comment Reflection warning, dbdump/dbdump.clj:157:44 - call to write can't be resolved.
on the same line.
How can i get rid of this warning? I'm thinking there is a performance cost when working with large datasets.
(defn run-job [job-time-string db-spec config]
(let [; {{{
source-sql (str "select * from " (:source-base-name config)(:table-name config))
max-rows (:max-rows config)
fetch-size (:fetch-size config)
working-dir (:working-dir config)
output-name (str working-dir "/" job-time-string ".pipe" )
field-delim (:field-delim config)
row-delim (:row-delim config)
log-report-interval (:log-report-interval config)
row-count (atom 0) ; For state on rows
db-connection (doto (j/get-connection db-spec))
statement (j/prepare-statement db-connection source-sql :fetch-size fetch-size :concurrency :read-only :max-rows max-rows)
start-in-millis (System/currentTimeMillis)
replace-newline (^String fn [s]
(if
(string? s)
(clojure.string/replace s #"\n" " ")
s)) ; I'd prefer not to do this; Right now we can't load \n fields.
row-fn (^String fn [v]
(swap! row-count inc)
(when
(zero?
(mod @row-count log-report-interval))
(write-logs @row-count start-in-millis 3 (:table-name config) ))
(str (join field-delim (doall (map #(replace-newline %) v))) row-delim ))
]; }}}
(with-open [^java.io.Writer wrtr (io/writer output-name )]
(info "Fetching jdbc query..." )
(info source-sql)
(try
(j/query db-connection [statement]
:as-arrays? true
:result-set-fn vec
; Reflection warning, dbdump/dbdump.clj:157:44 - call to write can not be resolved.
:row-fn ^String #(.write wrtr (row-fn %)))
(catch Exception e
(error (str "Error while fetching JDBC data." (.getMessage e)))
(System/exit 9))))
(write-logs @row-count start-in-millis 0 (str (:source-base-name config) (:table-name config) " Completed - "))))
Upvotes: 3
Views: 2120
Reputation: 84361
The reflection warning tells you that you need to clarify which write
method is to be called in #(.write wrtr (row-fn %))
. So you'll need to type-hint wrtr
and (row-fn %)
:
#(.write ^java.io.Writer wrtr ^String (row-fn %))
Incidentally, adding type hints to fn
forms or function literals has no effect. (Well, adding primitive hints does make the resulting function implement the relevant clojure.lang.IFn$[OLD]+
interface, but those hints would need to be attached to the parameter vector and/or the individual symbols naming the parameters.)
(In contrast, adding type hints to function names in defn
forms does have the effect of placing :tag
metadata on the resulting Vars; this will be used by the compiler to disambiguate Java method calls.)
Upvotes: 8