Gladear

Gladear

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,

Showing Posts 1 to 4

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:

kip

kip

ex_cldr Core Team

Oh, I read a bit more closely. I suspect, as @LostKobrakai says, the lack of a dump/2 callback is the issue.

Gladear

Gladear OP

@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:

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews