How to override a postgresql extension?

I am trying to override the version of a postgresql extension with an overlay but I haven’t been able to propagate it to pkgs.postgresql_13.withPackages (p: [p.postgis]).

This is the extension overlay.

postgis_overlay = (self: super: {
  postgis = super.postgis.overrideAttrs (prev: rec {
    version = "3.1.4";
    src = super.fetchurl {
      url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
      sha256 = "15ip38p7df9d9l6l3xhn2x8marbz8dy5lk3jblpl4bjkpkl3z3nw";
    };
  });
})

As I observed bellow, while postgis is made available as a toplevel package, it’s not the same used in the passthru (source).

pkgs = import inputs.nixpkgs { system = "aarch64-darwin"; overlays = [postgis_overlay]; }

pkgs.postgis.version
"3.1.4"

pkgs.postgresql_13.pkgs.postgis.version
"3.2.2"

pkgs.postgresql_13.passthru.pkgs.postgis.version
"3.2.2"

I have tried some variations but without success.

postgis_overlay = (self: super: {
  postgresql13Packages.postgis = super.postgresql13Packages.postgis.overrideAttrs (prev: rec {
    version = "3.1.4";
    src = super.fetchurl {
      url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
      sha256 = "15ip38p7df9d9l6l3xhn2x8marbz8dy5lk3jblpl4bjkpkl3z3nw";
    };
  });
})

pkgs = import inputs.nixpkgs { system = "aarch64-darwin"; overlays = [postgis_overlay]; }

pkgs.postgresql13Packages.postgis.version
"3.1.4"

pkgs.postgresql_13.pkgs.postgis.version
"3.2.2"

Any ideas on how to resolve this :smiley:?

Overlays can only consistently update references from pkgs and other fixed points. To know how to override an attribute, you need to look at its definition:

In this case postgresql13Packages is defined in terms of postgresql_13.pkgs from the final package set so if you replace the former in the overlay, the latter will not be touched at all:

Layer/Attribute postgresql13Packages points to postgresql_13.pkgs points to
Nixpkgs top-level pkgs final.postgresql_13.pkgs original definition
postgis_overlay { postgis = …; } Ø
Final composition of layers { postgis = …; } original definition

What is worse, since {postgresql13Packages.postgis = …; } is the same as {postgresql13Packages = { postgis = …; }; } and overlays do not merge nested attribute sets, the postgresql13Packages in the final composition will not contain anything other than your overridden postgis attribute.

You will need to continue your quest to the definition of the pkgs attribute of postgresql_13 attribute:

This appears to be a manually managed scope. You will want to check that postgresql_13.pkgs only refers to the consistent set if you override it, which seems to be the case since this only ever points to postgresql_* attribute from the top-level fix point (I only skimmed the code, make sure for yourself).

So I would expect something like the following to be sufficient:

(self: super: {
  postgresql_13 = super.postgresql_13 // {
    pkgs = super.postgresql_13.pkgs // {
      postgis = super.postgresql_13.pkgs.postgis.overrideAttrs (prev: rec {
        version = "3.1.4";
        src = super.fetchurl {
          url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
          sha256 = "15ip38p7df9d9l6l3xhn2x8marbz8dy5lk3jblpl4bjkpkl3z3nw";
        };
      });
    };
  };
})

(Or slightly shorter variant with lib.recursiveUpdate.)

1 Like

Thank you @jtojnar for taking the time to explain the overlay intricacies as well as providing a solution.