`Ecto.Adapters.SQL.query` dialyxir error

Greetings. I have an issue, or a misunderstanding perhaps, on my part, of Ecto.Adapters.SQL.query.
Apparently, its return type is %{rows: nil | [tuple], num_rows: non_neg_integer} | no_return.
But, because I’m using Postgrex, the real return type is somewhat like %Postgrex.Result{columns: ..., rows: ...}.
Dialyzer does not like this.
My question is: is this an issue with dialyxir as it doesn’t know which Ecto adapter I’m using?
I’m using:
Ecto 2.1.5
Dialyxir 0.5
Elixir 1.5

Can you provide a little bit more code? And also the exact complain from dialyzer?

%Postgrex.Result{columns: columns, rows: rows} = Ecto.Adapters.SQL.query!(Repo, query, params) (I don’t use the struct here, added it for clarity)

And this is what dialyzer says:
apps/pop/lib/pop/library.ex:41: Function update_searchable/1 has no local return apps/pop/lib/pop/library.ex:43: The pattern #{'rows':=_rows@1, 'columns':=_columns@1} can never match the type #{'num_rows':=non_neg_integer(), 'rows':='nil' | [tuple()]}

I get it, he’s right, but still, query should return Postgrex.Result, right?

The fact the return has extra data (the __struct__ field) is inconsequental. You can only be assured that it will always return what the spec states, anything extra you should ignore as it may not always exist (in your case it will, but dialyzer does not know that as it is not able to infer the return type from the Repo type at this time).

This is exactly what this PR fixed https://github.com/elixir-ecto/ecto/pull/2141. Should be released with the next version.

2 Likes