Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1syzrh-003Ys3-Pb for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Oct 2024 20:34:31 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1syzrh-006waW-1a for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Oct 2024 20:34:29 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1syzrf-006waG-JR for pgsql-hackers@lists.postgresql.org; Thu, 10 Oct 2024 20:34:29 +0000 Received: from fout-a5-smtp.messagingengine.com ([103.168.172.148]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1syzra-000OoD-Tg for pgsql-hackers@postgresql.org; Thu, 10 Oct 2024 20:34:27 +0000 Received: from phl-compute-07.internal (phl-compute-07.phl.internal [10.202.2.47]) by mailfout.phl.internal (Postfix) with ESMTP id CB3E41380142 for ; Thu, 10 Oct 2024 16:34:20 -0400 (EDT) Received: from phl-frontend-02 ([10.202.2.161]) by phl-compute-07.internal (MEProxy); Thu, 10 Oct 2024 16:34:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=justatheory.com; h=cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:message-id:mime-version:reply-to :subject:subject:to:to; s=2016-12.pbsmtp; t=1728592460; x= 1728678860; bh=9N94GyriKSYEZGsLZYxApJccECFGrZ/8TPvET1GkJ0s=; b=U Ld2aVta3IOaX/wB6NM6UDCzGV+K9MP1m1fidNljd+81bt0v79nVu3VMVO8KKtYYB CQi3NweJNgIAiPe6b7A405oQC7+/F/3y3wyf5pj/paPZe+r3IGbmEUsAjmSk/WHU 8pU8dV3qLiSmq5lsK6GbSlK0oAX4RBiXEAhuQraRpU= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pobox.com; h=cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:message-id:mime-version:reply-to:subject :subject:to:to; s=fm1; t=1728592460; x=1728678860; bh=9N94GyriKS YEZGsLZYxApJccECFGrZ/8TPvET1GkJ0s=; b=vVQh+jPfZQc9kmDyfjDKRrT0hn muUKz9IGjDspif+rzAe4GSmkBJ+CaEnKwfRVTz9C0Tw0XmaEZg3Bn2HskaE/dnSr tMCgniq0FgU62fKOukptMwSMZvWKhp52jn7WYwybNdXTIEbSKzsqIq781kg6sMP+ 9XsgC4RMm3uASejSCfolIYMLBOAsL67KH3wXz1cp6VqI6fAnJHKqy08vOaj//AAm 7dpeGC3Y9WRKvJ8uuRGd8ThNla59hwPlya/pbGRKv3xR+J0jRyQCt7BX5XaFA/vQ IECwVTduw6/IPD9hiHGCHr/0SUHtXIfFiOwk3Zksn0zny1cK34tkHzJQ4GBA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:message-id:mime-version:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; t=1728592460; x=1728678860; bh=9N94GyriKSYEZGsLZYxApJccECFG rZ/8TPvET1GkJ0s=; b=HL4sHrzQ4ZpiYt+n4I2gmxaQNVpuW+PHE3EYb/Bu0SXt kVO/zEOsOGlv8v9ymF8/pUVYrnwOdsW3Nr7frt4hg47EeST9gmbDqtIuhq0r1xB+ u1F0oigWv6AYL4jAWzIpPkabQK/TYlLpk3gVdFwU0Nhj1XhYYiBRLtT+LOe6/+ZU Kjjlw6UUHzKDBAudseLEpfpGBAzba8sKUeWQ2FrtIHkOaEb9Gm/5QoaoDrNFxHU0 nns1G4Y6nsJRUXGIK4VbL6QxherRNVOoFvpeIS7KOZmtrdlbky6QepZt/PDpMv9b UCv2GlrNV46DPYC03w5Fdlxa1Dv0/xfmzO/G0Qiqqg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrvdefiedgvdehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnh htshculddquddttddmnecujfgurhephfgtgfgguffkfffvofesthhqmhdthhdtjeenucfh rhhomhepfdffrghvihguucfgrdcuhghhvggvlhgvrhdfuceouggrvhhiugesjhhushhtrg hthhgvohhrhidrtghomheqnecuggftrfgrthhtvghrnhepgfevvdelfeduteduvdduhfef ieehleeuheeljeefudduhfekteekjeetieeftdfgnecuffhomhgrihhnpehpohhsthhgrh gvshhqlhdrohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhl fhhrohhmpegurghvihgusehjuhhsthgrthhhvghorhihrdgtohhmpdhnsggprhgtphhtth hopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehpghhsqhhlqdhhrggtkhgv rhhssehpohhsthhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i7c334307:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Thu, 10 Oct 2024 16:34:20 -0400 (EDT) From: "David E. Wheeler" Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3818.100.11.1.3\)) Subject: RFC: Extension Packaging & Lookup Message-Id: <2CAD6FA7-DC25-48FC-80F2-8F203DECAE6A@justatheory.com> Date: Thu, 10 Oct 2024 22:34:08 +0200 To: PostgreSQL Hackers X-Mailer: Apple Mail (2.3818.100.11.1.3) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hackers, Back at the end of August, I promised[1]: > I=E2=80=99ll try to put some thought into a more formal proposal in a = new thread next week. Unless your Gabriele beats me to it =F0=9F=98=82. I guess I should get off my butt and do it. So let=E2=80=99s do this. = Here=E2=80=99s what I propose. * When an extension is installed, all of its files should live in a = single directory. These include: * The Control file in directory describes extension * Subdirectories for SQL, shared libraries, docs, binaries (also locales and tsearch dictionaries?) * Next, there should be an extension lookup path. The first item in = the path is the compile-time default, and ideally would include only = core extensions. Subsequent paths would be set by a GUC, similar to = dynamic_library_path, but only for extensions (including their shared = libraries). * Modify PGXS (or create a new installer CLI used by PGXS?) to install = an extension according to this pattern. Allow the specification of a = prefix. This should differ from the current `PREFIX`, in that the values = of `sharedir`, `pkglibdir`, etc. would not be fully-duplicated under the = prefix, but point to a directory used in the extension path. For = example, when installing an extension need =E2=80=9Cpair", something = like make install BASE_DIR=3D/opt/pg/extension Would create `/opt/pg/extension/pair`, rather than = `/opt/pg/extension/$(pg_config --sharedir)/extension/pair`. * Perhaps there could also be an option to symlink binary files or man = pages to keep paths simple. * For CREATE EXTENSION, Postgres would look for an extension on the = file system by directory name in each of the extension paths instead of = control file name. It would then find the control file in that directory = and the necessary SQL and shared library files in the `sql` and `lib` = subdirectories of that directory. * Binary-only extensions might also be installed here; the difference = is they have no control file. The LOAD command and = shared_preload_libraries would need to know to look here, too. The basic idea, then, is three-fold: 1. This pattern is more like a packaging pattern than CREATE = EXTENSION-specific, since it includes other types of extensions 2. All the files for a given extension live within a single directory, = making it easier to reason about what=E2=80=99s installed and what=E2=80=99= s not. 3. These extension packages can live in multiple paths. Some examples. Core extensions, like citext, would live in, say, = $(pg_config --extensiondir)/citext), and have a structure such as: ``` citext =E2=94=9C=E2=94=80=E2=94=80 citext.control =E2=94=9C=E2=94=80=E2=94=80 lib =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80 citext.dylib =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 bitcode =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80 citext =E2=94=82 =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 citext.bc =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 citext.index.bc =E2=94=94=E2=94=80=E2=94=80 sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.0--1.1.sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.1--1.2.sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.2--1.3.sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.3--1.4.sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.4--1.5.sql =E2=94=9C=E2=94=80=E2=94=80 citext--1.4.sql =E2=94=94=E2=94=80=E2=94=80 citext--1.5--1.6.sql ``` Third-party extensions would live in one or more other directories on = the file system, unknown at compile time, but set in the extension path = GUC and accessible to/owned by the Postgres system user. Let=E2=80=99s = say we set `/opt/pgxn` as one of the paths. Within that directory, we = might have a directory for a pure SQL extension in a a directory named = =E2=80=9Cpair=E2=80=9D that looks like this: ``` pair =E2=94=9C=E2=94=80=E2=94=80 LICENSE.md =E2=94=9C=E2=94=80=E2=94=80 README.md =E2=94=9C=E2=94=80=E2=94=80 pair.control =E2=94=9C=E2=94=80=E2=94=80 doc =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80 html =E2=94=82 =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 pair.html =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 pair.md =E2=94=94=E2=94=80=E2=94=80 sql =E2=94=9C=E2=94=80=E2=94=80 pair--1.0--1.1.sql =E2=94=94=E2=94=80=E2=94=80 pair--1.1.sql ``` A binary application like pg_top would live in the pg_top directory, = structured something like: ``` pg_top =E2=94=9C=E2=94=80=E2=94=80 HISTORY.rst =E2=94=9C=E2=94=80=E2=94=80 INSTALL.rst =E2=94=9C=E2=94=80=E2=94=80 LICENSE =E2=94=9C=E2=94=80=E2=94=80 README.rst =E2=94=9C=E2=94=80=E2=94=80 bin | =E2=94=94=E2=94=80=E2=94=80 pg_top =E2=94=94=E2=94=80=E2=94=80 doc =E2=94=94=E2=94=80=E2=94=80 man =E2=94=94=E2=94=80=E2=94=80 man3 =E2=94=94=E2=94=80=E2=94=80 pg_top.3 ``` And a C extension like semver would live in the semver directory and be = structured something like: ``` semver =E2=94=9C=E2=94=80=E2=94=80 LICENSE =E2=94=9C=E2=94=80=E2=94=80 README.md =E2=94=9C=E2=94=80=E2=94=80 semver.control =E2=94=9C=E2=94=80=E2=94=80 doc =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 semver.md =E2=94=9C=E2=94=80=E2=94=80 lib =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80 semver.dylib =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80 bitcode =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 semver =E2=94=82 =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 semver.bc =E2=94=82 =E2=94=94=E2=94=80=E2=94=80 semver.index.bc =E2=94=94=E2=94=80=E2=94=80 sql =E2=94=9C=E2=94=80=E2=94=80 semver--1.0--1.1.sql =E2=94=94=E2=94=80=E2=94=80 semver--1.1.sql ``` Thoughts? Best, David [1]: = https://www.postgresql.org/message-id/D30A91FA-A6D4-4737-941F-0BBB2984B730= %40justatheory.com