Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pZKEg-0007KQ-Dz for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Mar 2023 23:27:18 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pZKEe-0000Xr-2q for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Mar 2023 23:27:16 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pZKEd-0000V1-Aj for pgsql-hackers@lists.postgresql.org; Mon, 06 Mar 2023 23:27:15 +0000 Received: from mail-qt1-x82c.google.com ([2607:f8b0:4864:20::82c]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pZKET-0005j1-DS for pgsql-hackers@lists.postgresql.org; Mon, 06 Mar 2023 23:27:14 +0000 Received: by mail-qt1-x82c.google.com with SMTP id c19so12570369qtn.13 for ; Mon, 06 Mar 2023 15:27:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pcorp-us.20210112.gappssmtp.com; s=20210112; t=1678145224; h=content-language:thread-index:mime-version:message-id:date:subject :in-reply-to:references:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ryDmOBuvYzfGr+hGnXcMSw9v/UKb6e4+w6fx9/IW6c4=; b=7W1Nv9E/oCXXROz13lQlo+0DfBLB99XFB6rDE/V92TnNDM759rUgttNTpLSjDnUnx7 mn+zXGlqBeC1Y1+afblRTs0H9q7HWq08BAvIM1NW36LAGciNJmuonE8C8bQ15YPg9x7d sv+xR+P2j+cHuGxPJRbUdHNk+oI/HHBspMZnp5+hu5TkgP6UMHTMvNiR/HIgbvUXfh63 TLPyZwQ8HdIZ4a11UgXxtSur5SxPoFkSgExTuL8Aj8FLBT1K2jKrBZvj3zwCmvV3mhRv FAMIvVtK76Jt1BVtUSPslEl+GjkBpCU2JSXl7I6FbGq9/WjipBy0+RLY7DaGoOYxPE9L V2mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678145224; h=content-language:thread-index:mime-version:message-id:date:subject :in-reply-to:references:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ryDmOBuvYzfGr+hGnXcMSw9v/UKb6e4+w6fx9/IW6c4=; b=h8y0e6r4W5BotMJZPIt2T7xpwyTEtJqNViYfdBjxgyNxyjSPDgHP6eJzebLVEu+0m2 9vipY1bo//1GI0oFxVw0bUx6PvUaWfV+k6KExlkASp+xXuQ4Io02x1PVqdL3ViBdIp0R ST2pfafJZy5UlBP84XKT+5LJfaUKliqoFcHx2rrysIkOJSVOMPN6i/3XSEfXayKezMlK jymD+5xq9g3Tys/iLmyqKgxB8yizHT9AYpKmHAkVjGoEGzfwVe5e+ilqPG0PjcCY/oQw Cktp4VvZY/30fKP5q1pZ0ntRmW8Q709fr4TpZnIMUklF4aUyNoVAUkFu8lfqBfsaA8PN 5zpA== X-Gm-Message-State: AO0yUKU337MPxMv5wp4LFEts424QWM4sAFW63pLwvq5x7nsBXIMHICPJ L2q+dHcBYp48RZzi2zJLq+twcNN4YQR/alRr77TDmw== X-Google-Smtp-Source: AK7set9TwdjUUlovwZ7hhvdCKKiM+GTuSWnUcTsHu81hVYID57V7UUAO8VTqWo0Q1nl4Mz5MOayY0g== X-Received: by 2002:a05:622a:5d2:b0:3b9:a5d8:2c50 with SMTP id d18-20020a05622a05d200b003b9a5d82c50mr20041758qtb.38.1678145224248; Mon, 06 Mar 2023 15:27:04 -0800 (PST) Received: from F (50-78-240-110-static.hfc.comcastbusiness.net. [50.78.240.110]) by smtp.gmail.com with ESMTPSA id n190-20020a37bdc7000000b0071a291f0a4asm8418323qkf.27.2023.03.06.15.27.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Mar 2023 15:27:03 -0800 (PST) From: "Regina Obe" To: "'Gregory Stark \(as CFM\)'" , "'Sandro Santilli'" Cc: , "'Regina Obe'" References: <003001d8f4ae$402282c0$c0678840$@pcorp.us> <000401d94bc8$48dff700$da9fe500$@pcorp.us> <167762779361.628976.14009177203307564086.pgcf@coridan.postgresql.org> In-Reply-To: Subject: RE: Ability to reference other extensions by schema in extension scripts Date: Mon, 6 Mar 2023 18:26:59 -0500 Message-ID: <005401d95083$26ca24a0$745e6de0$@pcorp.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0055_01D95059.3DF41CA0" X-Mailer: Microsoft Outlook 15.0 Thread-Index: AQFgXZxpr0yOB+9uS1Xwc1lFBKthIAFb3UkpAlqGOBEBdWkveq+27GGg Content-Language: en-us List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multipart message in MIME format. ------=_NextPart_000_0055_01D95059.3DF41CA0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > It looks like this patch needs a quick rebase, there's a conflict in = the > meson.build. >=20 > I'll leave the state since presumably this would be easy to resolve = but it would > be more likely to get attention if it's actually building cleanly. >=20 > http://cfbot.cputube.org/patch_42_4023.log > -- > Gregory Stark > As Commitfest Manager Attach is the patch rebased against master. ------=_NextPart_000_0055_01D95059.3DF41CA0 Content-Type: application/octet-stream; name="0005-Allow-use-of-extschema-reqextname-to-reference.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0005-Allow-use-of-extschema-reqextname-to-reference.patch" From dce6168357e9ed410f94deb66b552129884195ba Mon Sep 17 00:00:00 2001=0A= From: Regina Obe =0A= Date: Sun, 5 Feb 2023 01:35:29 -0500=0A= Subject: [PATCH 5/5] Allow @extschema:@ in extension scripts=0A= =0A= This feature allows an extension author to reference=0A= extension schemas of extensions in the requires variable=0A= of the control file using variable syntax=0A= @extschema:@ where is the=0A= name of any of the listed required extensions.=0A= =0A= This feature is needed particularly in cases=0A= when another extension packages a function=0A= which references an object from one of its=0A= required extensions and this function is used to back=0A= indexes, constraints, and materialized views.=0A= =0A= Without this feature, because pg_restore removes the paths,=0A= these indexes, constraints, materialized views are not restored=0A= because when the function is called, the function call fails=0A= because items it depends on cannot be schema qualified.=0A= =0A= This feature will allow extension authors to schema qualify=0A= references to required extension objects to prevent this issue.=0A= Aside from this issue, schema qualifying all these references will=0A= improve security by preventing a rogue version of a function from being=0A= used.=0A= =0A= - Extension tests both Makefile and meson.build=0A= - Documentation of the new feature=0A= - Prevent an extension from being relocated if=0A= another extension requires it=0A= =0A= Discussion: = https://postgr.es/m/000801d94959%2463a9f520%242afddf60%24%40pcorp.us=0A= ---=0A= doc/src/sgml/extend.sgml | 17 +++++++=0A= src/backend/commands/extension.c | 49 +++++++++++++++++++=0A= src/test/modules/test_extensions/Makefile | 9 +++-=0A= .../expected/test_extensions.out | 40 +++++++++++++++=0A= src/test/modules/test_extensions/meson.build | 7 +++=0A= .../test_extensions/sql/test_extensions.sql | 14 ++++++=0A= .../test_ext_req_schema1--1.0.sql | 6 +++=0A= .../test_ext_req_schema1.control | 3 ++=0A= .../test_ext_req_schema2--1.0--2.0.sql | 7 +++=0A= .../test_ext_req_schema2--1.0.sql | 9 ++++=0A= .../test_ext_req_schema2.control | 4 ++=0A= .../test_ext_req_schema3--1.0.sql | 13 +++++=0A= .../test_ext_req_schema3.control | 4 ++=0A= 13 files changed, 180 insertions(+), 2 deletions(-)=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema1--1.0.sql=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema1.control=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema2--1.0--2.0.sql=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema2.control=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema3--1.0.sql=0A= create mode 100644 = src/test/modules/test_extensions/test_ext_req_schema3.control=0A= =0A= diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml=0A= index b70cbe83ae..6c93bddb36 100644=0A= --- a/doc/src/sgml/extend.sgml=0A= +++ b/doc/src/sgml/extend.sgml=0A= @@ -908,6 +908,23 @@ RETURNS anycompatible AS ...=0A= =0A= =0A= =0A= + =0A= + =0A= + An extension might depend on other extensions.=0A= + It is useful to schema qualify calls to dependent extension to = minimize reliance on search_path.=0A= + This is critical for cases such as functions used in indexes, = materialized views, or check constraints.=0A= + To reference a required extension's schema, you must first have = requires=0A= + variable specifying the list of extensions your extension = requires.=0A= + In your extension sql scripts,=0A= + you can reference a required extension's schema with syntax=0A= + @extschema:reqextname@ where = reqextname=0A= + is the name of an extension in your requires = list.=0A= + All occurrences of this string will be=0A= + replaced by the schema the required extension is installed in = before the script is=0A= + executed.=0A= + =0A= + =0A= +=0A= =0A= =0A= If the extension does not support relocation at all, set=0A= diff --git a/src/backend/commands/extension.c = b/src/backend/commands/extension.c=0A= index b1509cc505..17ebb1a4fc 100644=0A= --- a/src/backend/commands/extension.c=0A= +++ b/src/backend/commands/extension.c=0A= @@ -1030,6 +1030,41 @@ execute_extension_script(Oid extensionOid, = ExtensionControlFile *control,=0A= CStringGetTextDatum(qSchemaName));=0A= }=0A= =0A= + /*=0A= + * If this extension requires other extensions=0A= + * Check each required extension to see if its schema=0A= + * is referenced by @extschema:reqextname@ syntax=0A= + */=0A= + foreach(lc, control->requires)=0A= + {=0A= + char *curreq =3D (char *) lfirst(lc);=0A= + Oid reqext;=0A= + Oid reqschema;=0A= + StringInfoData rToken;=0A= + char *reqname;=0A= + reqext =3D get_required_extension(curreq,=0A= + control->name,=0A= + (char *) schemaName,=0A= + false,=0A= + NIL,=0A= + false);=0A= + reqschema =3D get_extension_schema(reqext);=0A= + reqname =3D get_namespace_name(reqschema);=0A= + initStringInfo(&rToken);=0A= + appendStringInfo(&rToken, "%s%s%s", "@extschema:", curreq, "@");=0A= +=0A= + /*=0A= + * If the required extension's schema is referenced=0A= + * by variable name,=0A= + * Replace each occurence of @extschema:@=0A= + * with the required extension's schema=0A= + */=0A= + t_sql =3D DirectFunctionCall3Coll(replace_text,=0A= + C_COLLATION_OID,=0A= + t_sql,=0A= + CStringGetTextDatum(rToken.data),=0A= + CStringGetTextDatum(quote_identifier(reqname)));=0A= + }=0A= /*=0A= * If module_pathname was set in the control file, substitute its=0A= * value for occurrences of MODULE_PATHNAME.=0A= @@ -2816,6 +2851,20 @@ AlterExtensionNamespace(const char = *extensionName, const char *newschema, Oid *o=0A= ObjectAddress dep;=0A= Oid dep_oldNspOid;=0A= =0A= + /* If an extension requires this extension=0A= + * do not allow relocation */=0A= + if (pg_depend->deptype =3D=3D DEPENDENCY_NORMAL && pg_depend->classid = =3D=3D ExtensionRelationId){=0A= + dep.classId =3D pg_depend->classid;=0A= + dep.objectId =3D pg_depend->objid;=0A= + dep.objectSubId =3D pg_depend->objsubid;=0A= + ereport(ERROR,=0A= + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),=0A= + errmsg("cannot SET SCHEMA of extension %s because other = extensions require it",=0A= + NameStr(extForm->extname)),=0A= + errdetail("%s requires extension %s",=0A= + getObjectDescription(&dep, false), = NameStr(extForm->extname))));=0A= +=0A= + }=0A= /*=0A= * Ignore non-membership dependencies. (Currently, the only other=0A= * case we could see here is a normal dependency from another=0A= diff --git a/src/test/modules/test_extensions/Makefile = b/src/test/modules/test_extensions/Makefile=0A= index c3139ab0fc..c073df963c 100644=0A= --- a/src/test/modules/test_extensions/Makefile=0A= +++ b/src/test/modules/test_extensions/Makefile=0A= @@ -6,14 +6,19 @@ PGFILEDESC =3D "test_extensions - regression testing = for EXTENSION support"=0A= EXTENSION =3D test_ext1 test_ext2 test_ext3 test_ext4 test_ext5 = test_ext6 \=0A= test_ext7 test_ext8 test_ext_cine test_ext_cor \=0A= test_ext_cyclic1 test_ext_cyclic2 \=0A= - test_ext_evttrig=0A= + test_ext_evttrig \=0A= + test_ext_req_schema1 test_ext_req_schema2 = test_ext_req_schema3=0A= +=0A= DATA =3D test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \=0A= test_ext4--1.0.sql test_ext5--1.0.sql test_ext6--1.0.sql \=0A= test_ext7--1.0.sql test_ext7--1.0--2.0.sql test_ext8--1.0.sql \=0A= test_ext_cine--1.0.sql test_ext_cine--1.0--1.1.sql \=0A= test_ext_cor--1.0.sql \=0A= test_ext_cyclic1--1.0.sql test_ext_cyclic2--1.0.sql \=0A= - test_ext_evttrig--1.0.sql test_ext_evttrig--1.0--2.0.sql=0A= + test_ext_evttrig--1.0.sql test_ext_evttrig--1.0--2.0.sql \=0A= + test_ext_req_schema1--1.0.sql \=0A= + test_ext_req_schema2--1.0.sql test_ext_req_schema2--1.0--2.0.sql = \=0A= + test_ext_req_schema3--1.0.sql=0A= =0A= REGRESS =3D test_extensions test_extdepend=0A= =0A= diff --git = a/src/test/modules/test_extensions/expected/test_extensions.out = b/src/test/modules/test_extensions/expected/test_extensions.out=0A= index 821fed38d1..21dfd05982 100644=0A= --- a/src/test/modules/test_extensions/expected/test_extensions.out=0A= +++ b/src/test/modules/test_extensions/expected/test_extensions.out=0A= @@ -312,3 +312,43 @@ Objects in extension "test_ext_cine"=0A= table ext_cine_tab3=0A= (9 rows)=0A= =0A= +CREATE SCHEMA test_s_dep;=0A= +CREATE EXTENSION test_ext_req_schema1 SCHEMA test_s_dep;=0A= +CREATE EXTENSION test_ext_req_schema3 CASCADE;=0A= +NOTICE: installing required extension "test_ext_req_schema2"=0A= +SELECT dep_req();=0A= + dep_req =0A= +---------=0A= + 1032w=0A= +(1 row)=0A= +=0A= +SELECT dep_req2();=0A= + dep_req2 =0A= +----------=0A= + 1032w=0A= +(1 row)=0A= +=0A= +SELECT dep_req3();=0A= + dep_req3 =0A= +----------=0A= + 2032w=0A= +(1 row)=0A= +=0A= +ALTER EXTENSION test_ext_req_schema2 UPDATE TO '2.0';=0A= +CREATE SCHEMA test_s_dep2;=0A= +ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_s_dep2;=0A= +ERROR: cannot SET SCHEMA of extension test_ext_req_schema1 because = other extensions require it=0A= +DETAIL: extension test_ext_req_schema3 requires extension = test_ext_req_schema1=0A= +SELECT dep_req();=0A= + dep_req =0A= +---------=0A= + 1update=0A= +(1 row)=0A= +=0A= +DROP EXTENSION test_ext_req_schema1;=0A= +ERROR: cannot drop extension test_ext_req_schema1 because other = objects depend on it=0A= +DETAIL: extension test_ext_req_schema2 depends on extension = test_ext_req_schema1=0A= +extension test_ext_req_schema3 depends on extension test_ext_req_schema1=0A= +HINT: Use DROP ... CASCADE to drop the dependent objects too.=0A= +DROP EXTENSION test_ext_req_schema3;=0A= +DROP EXTENSION test_ext_req_schema2;=0A= diff --git a/src/test/modules/test_extensions/meson.build = b/src/test/modules/test_extensions/meson.build=0A= index c3af3e1721..7f47a6fc23 100644=0A= --- a/src/test/modules/test_extensions/meson.build=0A= +++ b/src/test/modules/test_extensions/meson.build=0A= @@ -30,6 +30,13 @@ test_install_data +=3D files(=0A= 'test_ext_evttrig--1.0--2.0.sql',=0A= 'test_ext_evttrig--1.0.sql',=0A= 'test_ext_evttrig.control',=0A= + 'test_ext_req_schema1--1.0.sql',=0A= + 'test_ext_req_schema1.control',=0A= + 'test_ext_req_schema2--1.0.sql',=0A= + 'test_ext_req_schema2.control',=0A= + 'test_ext_req_schema2--1.0--2.0.sql',=0A= + 'test_ext_req_schema3.control',=0A= + 'test_ext_req_schema3--1.0.sql',=0A= )=0A= =0A= tests +=3D {=0A= diff --git a/src/test/modules/test_extensions/sql/test_extensions.sql = b/src/test/modules/test_extensions/sql/test_extensions.sql=0A= index 41b6cddf0b..81ecd13736 100644=0A= --- a/src/test/modules/test_extensions/sql/test_extensions.sql=0A= +++ b/src/test/modules/test_extensions/sql/test_extensions.sql=0A= @@ -209,3 +209,17 @@ CREATE EXTENSION test_ext_cine;=0A= ALTER EXTENSION test_ext_cine UPDATE TO '1.1';=0A= =0A= \dx+ test_ext_cine=0A= +=0A= +CREATE SCHEMA test_s_dep;=0A= +CREATE EXTENSION test_ext_req_schema1 SCHEMA test_s_dep;=0A= +CREATE EXTENSION test_ext_req_schema3 CASCADE;=0A= +SELECT dep_req();=0A= +SELECT dep_req2();=0A= +SELECT dep_req3();=0A= +ALTER EXTENSION test_ext_req_schema2 UPDATE TO '2.0';=0A= +CREATE SCHEMA test_s_dep2;=0A= +ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_s_dep2;=0A= +SELECT dep_req();=0A= +DROP EXTENSION test_ext_req_schema1;=0A= +DROP EXTENSION test_ext_req_schema3;=0A= +DROP EXTENSION test_ext_req_schema2;=0A= \ No newline at end of file=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema1--1.0.sql = b/src/test/modules/test_extensions/test_ext_req_schema1--1.0.sql=0A= new file mode 100644=0A= index 0000000000..462fb52145=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema1--1.0.sql=0A= @@ -0,0 +1,6 @@=0A= +/* src/test/modules/test_extensions/test_ext_req_schema1--1.0.sql */=0A= +-- complain if script is sourced in psql, rather than via CREATE = EXTENSION=0A= +\echo Use "CREATE EXTENSION test_ext_req_schema1" to load this file. = \quit=0A= +=0A= +CREATE DOMAIN req AS text=0A= + CONSTRAINT starts_with_1 check(pg_catalog.left(value,1) = OPERATOR(pg_catalog.=3D) '1');=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema1.control = b/src/test/modules/test_extensions/test_ext_req_schema1.control=0A= new file mode 100644=0A= index 0000000000..9ea4558a90=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema1.control=0A= @@ -0,0 +1,3 @@=0A= +comment =3D 'Create required extension to be referenced'=0A= +default_version =3D '1.0'=0A= +relocatable =3D true=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema2--1.0--2.0.sql = b/src/test/modules/test_extensions/test_ext_req_schema2--1.0--2.0.sql=0A= new file mode 100644=0A= index 0000000000..73a44a25e5=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema2--1.0--2.0.sql=0A= @@ -0,0 +1,7 @@=0A= +/* src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql */=0A= +-- complain if script is sourced in psql, rather than via CREATE = EXTENSION=0A= +\echo Use "CREATE EXTENSION test_ext_req_schema2" to load this file. = \quit=0A= +=0A= +CREATE OR REPLACE FUNCTION dep_req() RETURNS = @extschema:test_ext_req_schema1@.req=0A= +LANGUAGE SQL IMMUTABLE PARALLEL SAFE=0A= +AS 'SELECT ''1update''::@extschema:test_ext_req_schema1@.req';=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql = b/src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql=0A= new file mode 100644=0A= index 0000000000..9fe25d48a1=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql=0A= @@ -0,0 +1,9 @@=0A= +/* src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql */=0A= +-- complain if script is sourced in psql, rather than via CREATE = EXTENSION=0A= +\echo Use "CREATE EXTENSION test_ext_req_schema2" to load this file. = \quit=0A= +CREATE DOMAIN dreq AS text=0A= + CONSTRAINT starts_with_2 check(pg_catalog.left(value,1) = OPERATOR(pg_catalog.=3D) '2');=0A= +=0A= +CREATE FUNCTION dep_req() RETURNS @extschema:test_ext_req_schema1@.req=0A= +LANGUAGE SQL IMMUTABLE PARALLEL SAFE=0A= +AS 'SELECT ''1032w''::@extschema:test_ext_req_schema1@.req';=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema2.control = b/src/test/modules/test_extensions/test_ext_req_schema2.control=0A= new file mode 100644=0A= index 0000000000..d2ba5add97=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema2.control=0A= @@ -0,0 +1,4 @@=0A= +comment =3D 'Test schema referencing of required extensions'=0A= +default_version =3D '1.0'=0A= +relocatable =3D true=0A= +requires =3D 'test_ext_req_schema1'=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema3--1.0.sql = b/src/test/modules/test_extensions/test_ext_req_schema3--1.0.sql=0A= new file mode 100644=0A= index 0000000000..bd05669097=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema3--1.0.sql=0A= @@ -0,0 +1,13 @@=0A= +/* src/test/modules/test_extensions/test_ext_req_schema2--1.0.sql */=0A= +-- complain if script is sourced in psql, rather than via CREATE = EXTENSION=0A= +\echo Use "CREATE EXTENSION test_ext_req_schema2" to load this file. = \quit=0A= +CREATE DOMAIN req2 AS text=0A= + CONSTRAINT starts_with_2 check(pg_catalog.left(value,1) = OPERATOR(pg_catalog.=3D) '2');=0A= +=0A= +CREATE FUNCTION dep_req2() RETURNS @extschema:test_ext_req_schema1@.req=0A= +LANGUAGE SQL IMMUTABLE PARALLEL SAFE=0A= +AS 'SELECT ''1032w''::@extschema:test_ext_req_schema1@.req';=0A= +=0A= +CREATE FUNCTION dep_req3() RETURNS @extschema:test_ext_req_schema2@.dreq=0A= +LANGUAGE SQL IMMUTABLE PARALLEL SAFE=0A= +AS 'SELECT ''2032w''::@extschema:test_ext_req_schema2@.dreq';=0A= diff --git = a/src/test/modules/test_extensions/test_ext_req_schema3.control = b/src/test/modules/test_extensions/test_ext_req_schema3.control=0A= new file mode 100644=0A= index 0000000000..b052fad785=0A= --- /dev/null=0A= +++ b/src/test/modules/test_extensions/test_ext_req_schema3.control=0A= @@ -0,0 +1,4 @@=0A= +comment =3D 'Test schema referencing of 2 required extensions'=0A= +default_version =3D '1.0'=0A= +relocatable =3D true=0A= +requires =3D 'test_ext_req_schema1,test_ext_req_schema2'=0A= -- =0A= 2.21.0.windows.1=0A= =0A= ------=_NextPart_000_0055_01D95059.3DF41CA0--