Type `jsonpath` can not be handled by the types module Postgrex.DefaultTypes

Hi, all.

Today I encountered this problem and I really appreciate your help. Thanks in advance.

I’m developing a Phoenix app.

Here’s my simplified schema:

defmodule MyApp.Foo do
  import Ecto.Schema

  schema "foos" do
    # maps to a jsonb column
    field :bar, {:array, :map}
  end
end

Here’s the Ecto query:

MyApp.Foo
|> where([f], fragment(
  ~S[? @\? ?],
  f.bar,
  ^~s{$[*].x.y ? (@ == "#{some_text_injection_here}")}
))
|> MyApp.Repo.all()

And here’s the error message:

14:30:42.212 [error] Postgrex.Protocol (#PID<0.123.0>) disconnected: ** (Postgrex.QueryError) type `jsonpath` can not be handled by the types module Postgrex.DefaultTypes

So, how can I make Postgrex and Ecto support jsonpath, or how to rewrite the query to avoid such problem? Thanks again.

By the way, I tried adding lib/my_app/postgrex/types.ex with the following content:

Postgrex.Types.define(
  MyApp.Postgrex.Types,
  [MyApp.Postgrex.JSONPath],
  [decode_binary: :reference]
)

and lib/my_app/postgrex/jsonpath.ex:

defmodule MyApp.Postgrex.JSONPath do
  @behaviour Postgrex.Extension

  @impl Postgrex.Extension
  def init(opts) do
    Keyword.get(opts, :decode_copy, :copy)
  end

  @impl Postgrex.Extension
  def matching(_state), do: [type: "jsonpath"]

  @impl Postgrex.Extension
  def format(_state), do: :text

  @impl Postgrex.Extension
  def encode(_state) do
    quote do
      bin when is_binary(bin) ->
        [<<byte_size(bin) :: signed-size(32)>> | bin]
    end
  end

  @impl Postgrex.Extension
  def decode(:reference) do
    quote do
      <<len::signed-size(32), bin::binary-size(len)>> ->
        bin
    end
  end

  def decode(:copy) do
    quote do
      <<len::signed-size(32), bin::binary-size(len)>> ->
        :binary.copy(bin)
    end
  end
end

But I don’t know if this code is correct. I also don’t know how to configure my Phoenix app so that Postgrex can recognize my type definition.

try this pattern for fragment:

~S[? @\? ?::text::jsonpath]

Thanks for your suggestion. It doesn’t work though.

One of my colleagues told me that I can do this in config.exs

config :my_app, MyApp.Repo,
  types: MyApp.Postgrex.Types

I tried, and it worked.

it returns invalid results or you caught an exception?

Same exception as in my question.