How to use postgresql table inheritance with ecto

Postgresql supports table inheritance which allows to create tables like this:

CREATE TABLE cities (
  name       text,
  population real,
  altitude   int    

CREATE TABLE capitals (
  state      char(2)
) INHERITS (cities);

and to query these tables like this:

SELECT name, altitude
  FROM cities
  WHERE altitude > 500;

and like this:

SELECT name, altitude
    FROM ONLY cities
    WHERE altitude > 500;

How do we write the same using Ecto?

In migration:

create table(:cities) do
  add :name, :text,
  add :population, :integer,
  add :altitutde, :integer
end

create table(:capitals, options: "INHERITS (cities)") do
  add :state, :text
end

And then you can query it like:

from city in "cities",
  where: city.altitude > 500,
  select: %{
    name: city.name,
    altitude: city.altitude
  }

Second query thought is not possible with Ecto.Query right now (AFAIK) and you need to use raw SQL, ex.:

{:ok, result} =
  Repo.query("""
  SELECT name, altitude
      FROM ONLY cities
      WHERE altitude > ?
  """, [500])

Enum.map(result.rows, fn [name, altitude] -> %{name: name, altitude: altitude} end)

Thanks!

Yeah as it stands Ecto is not capable of handling PostgreSQL inheritance tables, you have to fall back to raw SQL, thus losing the typing and testing abilities of Ecto. A PR might be welcome though? :slight_smile:

I think its still not supported in ecto. I would love to submit a PR for it. if you have specific instructions or steps in mind, please do share. Thanks

It would be better to see if there is a way to make an addon library for it instead, Ecto is mostly in ‘keep-it-updated’ mode rather than accepting specific DB server features.

But I am not sure, what should be the best way to create some add on. eg I dont know if ecto provides some hooks to change query just before sending to db(I am not sure, if this is even recommened). some steps/guidelines(maybe someone from core team eg @josevalim @ericmj @michalmuskala ) will be really helpful as I dont find any clue yet(prepare_query or other callbacks dont seem to be the correct ones). Thanks

I think there’d be some way to do it, but if there isn’t then making the appropriate hooks with their inputs on the design would be very likely to be accepted I would bet. :slight_smile: