honeysql

Patrick Winter 2023-08-26T15:21:36.246079Z

I have the following query for a PostgreSQL database + TimescaleDB extension:

(defn get-most-recent-sample
  "Return most recent sample of `type` for `plant-id`."
  [plant-id type]
  (->>  {:select [[[:time_bucket "1 hour" :time] :bucket]
                  [[:last :value :time] :value]
                  [[:sign [:- [:last :value :time] [:first :value :time]]] :trend]]
         :from :samples
         :where [:and
                 [:= :plant-id plant-id]
                 [:= :type (as-other (name type))]
                 [:> :time [:- [:now] [:cast "1 hours" :interval]]]]
         :group-by [:bucket]
         :order-by [[:bucket :asc]]
         :limit 4}
        sql/format
        (jdbc/execute! *db*)
        first))
Running it through honesql.sql/format returns the following:
["SELECT TIME_BUCKET(?, time) AS bucket, LAST(value, time) AS value, SIGN(LAST(value, time) - FIRST(value, time)) AS trend FROM samples WHERE (plant_id = ?) AND (type = ?) AND (time > (NOW() - CAST(? AS interval))) GROUP BY bucket ORDER BY bucket ASC LIMIT ?"
 "1 hour"
 #uuid "73c41a17-f698-4c58-9ac4-cfa55c207131"
 #function[clojure.lang.AFunction/1]
 "1 hours"
 4]
If I run this query through psql it works as expected:
SELECT TIME_BUCKET('1 hour', time) AS bucket,
         LAST(value, time) AS value,
         SIGN(LAST(value, time) - FIRST(value, time)) AS trend
    FROM samples WHERE (plant_id = '73c41a17-f698-4c58-9ac4-cfa55c207131')
     AND (type = 'temperature') AND (time > (NOW() - CAST('1 hours' AS interval)))
GROUP BY bucket ORDER BY bucket ASC LIMIT 4
Executing it in Clojure throws the following exception:
org.postgresql.util.PSQLException: ERROR: function time_bucket(character varying, timestamp with time zone) does not exist
  Hint: No function matches the given name and argument types. You might need to add explicit type casts.
  Position: 8
Any ideas why this happens and what I need to do to fix it?

Patrick Winter 2023-08-26T15:35:10.964729Z

I think I found a workaround: [:raw "time_bucket('1 hour', time)"]

seancorfield 2023-08-26T17:47:17.361859Z

You could use [:inline "1 hour"] there. No need to revert to :raw.

🙌 1