Gladear

Gladear

How to I dump an Elixir tuple into a PostgreSQL composite type?

Hello :wave:

I’m using Ecto along with PostgreSQL. I’ve been trying to add a field containing a 2-tuple to an Ecto schema, but can’t seem to make it work.

There is no built-in :tuple type in Ecto, so I tried to create an Ecto.Type, but that does not seem to be enough:

defmodule MyType do
  use Ecto.Type

  @impl Ecto.Type
  def type, do: :my_type

  @impl Ecto.Type
  def cast({one, two}) when is_binary(one) and is_binary(two), do: {:ok, {one, two}}
  def cast(_), do: :error

  @impl Ecto.Type
  def cast({one, two}) when is_binary(one) and is_binary(two), do: {:ok, {one, two}}
  def cast(_), do: :error

  @impl Ecto.Type
  def load({one, two}) do
    {:ok, {one, two}}
  end
end

I create the field in an Ecto migration using this command:

execute "CREATE TYPE my_type AS (one text, two text)"

Then, when trying to insert a struct from a schema with a field of this type, I get the following message:

(DBConnection.EncodeError) cannot encode anonymous tuple {"one", "two"}. Please define a custom Postgrex extension that matches on its underlying type:

    use Postgrex.BinaryExtension, type: "typeinthedb"

I tried to follow the instructions and create an extension, but could never make it work.

What blows my mind is that the library :ex_money_sql (cc @kip) does not seem to have to create a Postgrex extension (or at least, I could never find it). See type source. Postgrex is pretty clear on the subject: “Anonymous composite types are decoded (read) as tuples but they cannot be encoded (written) to the database” (doc). So how does it work? Why does it work? I’m a bit lost here :confused:

If you see any flaw in my reasoning, please tell me what I’m doing wrong :pray:
Thanks for your time,

Most Liked

LostKobrakai

LostKobrakai

There’s no dump/1 callback in your type. Not sure if that’s related, but should be fixed non the less.

kip

kip

ex_cldr Core Team

There is a mix task that defines the money_with_currency type. Hopefully that at least clears that up :slight_smile:

Last Post!

Gladear

Gladear

@LostKobrakai oops, this was a problem when adapting my “real” schema, the second couple of “cast” clauses were actually “dump”.

Although I did find my issue when trying to make a simple reproduction: the problem was not when inserting the struct, it was when querying without the struct - something along the lines of Repo.get_by(MySchema, composite_field: {"one", "two"}). This indeed does not work, however, it can be worked around by explicitly casting to the type:

from(schema in MySchema,
  where: schema.composite_field == type(^{"one", "two"}, MyType)
)
|> Repo.one()

This works perfectly fine :ok_hand:

Thank you for your time, sorry for the bother, I may have been quite tired yesterday :see_no_evil:

Where Next?

Popular in Questions Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 131117 1222
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement