2

I'm trying to cast a list of ip addresses to ::inet but only the last element in the list gets converted.

I've tried the following but nothing seems to work.

select * from ip_addresses where address in (:addresses::inet)

select * from ip_addresses where address in (:addresses)::inet

select * from ip_addresses where address in CAST (:addresses AS inet)

I can't simply cast the address::text since matches can fail if the input addresses don't have a subnet specified.

BWStearns
  • 2,567
  • 2
  • 19
  • 33

2 Answers2

2

Sounds like HugSQL is replacing :addresses with a comma delimited list so your (:addresses::inet) ends up looking like (addr, addr, addr, ..., addr::inet). If that's the case then you could replace in (list) with = any(array), use the array constructor syntax, and apply a cast to that array as a whole:

select * from ip_addresses where address = any(array[:addresses]::inet[])
mu is too short
  • 426,620
  • 70
  • 833
  • 800
2

I think the answer from @mu-is-too-short is the better workaround for this--using the power of Postgresql to solve the problem.

Even so, if you did not want to use Postgresql arrays for this, you can generate a cast for each value in your vector in HugSQL by using a Clojure Expression:

-- :name x 
-- :require [clojure.string :as string]
select * from test where id in (
/*~
(clojure.string/join 
  ","
  (map-indexed (fn [i v] (str ":values." i "::int")) (:values params)))
~*/
)

Which will end up giving you something like this:

(x-sqlvec {:values ["1" "2"]})
;=> ["select * from test where id in (?::int,?::int)" "1" "2"]

So, the above takes the values vector and uses HugSQL's deep-get syntax to pull in each of the values individually and add the type cast to each one. So, you're effectively building a new set of HugSQL parameters on the fly that looks like:

in (:values.0::int, :values.1::int, :values.2::int)

Curtis Summers
  • 586
  • 5
  • 7