On Thu, Jul 30, 2015 at 10:58 PM, Petr Jelinek wrote:
> On 2015-07-27 15:18, Michael Paquier wrote:
>> Something also has not been discussed yet: what to do with new_version
>> and old_version (the options of CreateExtensionStmt)? As of now if
>> those options are defined they are not passed down to the parent
>> extensions but shouldn't we raise an error if they are used in
>> combination with CASCADE? In any case, I think that the behavior
>> chosen should be documented.
>>
>
> I don't see why we should raise error, they are used just for the top-level
> extension and I think it makes sense that way. CASCADE documentation says
> SCHEMA option is cascaded to required extensions, do we need to say
> something more than that (ie explicitly saying that the old_version and
> new_version aren't)?
OK, let's do so then. I think that we should still document the fact
that the old and new version strings and not passed to the parent
extensions when cascade is used for clarity. Something like:
"Other options are not recursively applied when the CASCASE clause is used."
I have been through this patch one last time and changed the following:
- Improved documentation: missing markups with <literal>, SCHEMA is a
clause and not a parameter, added explanation that options other than
SCHEMA are not applied recursively with CASCADE
- Corrected .gitignore in test_extensions, log/ was missing.
Those are minor things though, hence I just switched patch as "Ready
for committer".
--
Michael
diff --git a/contrib/hstore_plperl/expected/hstore_plperl.out b/contrib/hstore_plperl/expected/hstore_plperl.out
index cf384eb..25fc506 100644
--- a/contrib/hstore_plperl/expected/hstore_plperl.out
+++ b/contrib/hstore_plperl/expected/hstore_plperl.out
@@ -1,6 +1,6 @@
-CREATE EXTENSION hstore;
-CREATE EXTENSION plperl;
-CREATE EXTENSION hstore_plperl;
+CREATE EXTENSION hstore_plperl CASCADE;
+NOTICE: installing required extension "hstore"
+NOTICE: installing required extension "plperl"
SELECT transforms.udt_schema, transforms.udt_name,
routine_schema, routine_name,
group_name, transform_type
diff --git a/contrib/hstore_plperl/expected/hstore_plperlu.out b/contrib/hstore_plperl/expected/hstore_plperlu.out
index 8c689ad..3fc3201 100644
--- a/contrib/hstore_plperl/expected/hstore_plperlu.out
+++ b/contrib/hstore_plperl/expected/hstore_plperlu.out
@@ -1,6 +1,6 @@
-CREATE EXTENSION hstore;
-CREATE EXTENSION plperlu;
-CREATE EXTENSION hstore_plperlu;
+CREATE EXTENSION hstore_plperlu CASCADE;
+NOTICE: installing required extension "hstore"
+NOTICE: installing required extension "plperlu"
SELECT transforms.udt_schema, transforms.udt_name,
routine_schema, routine_name,
group_name, transform_type
diff --git a/contrib/hstore_plperl/sql/hstore_plperl.sql b/contrib/hstore_plperl/sql/hstore_plperl.sql
index 0f70f14..9398aed 100644
--- a/contrib/hstore_plperl/sql/hstore_plperl.sql
+++ b/contrib/hstore_plperl/sql/hstore_plperl.sql
@@ -1,6 +1,4 @@
-CREATE EXTENSION hstore;
-CREATE EXTENSION plperl;
-CREATE EXTENSION hstore_plperl;
+CREATE EXTENSION hstore_plperl CASCADE;
SELECT transforms.udt_schema, transforms.udt_name,
routine_schema, routine_name,
diff --git a/contrib/hstore_plperl/sql/hstore_plperlu.sql b/contrib/hstore_plperl/sql/hstore_plperlu.sql
index 3cfb2fd..8d8508c 100644
--- a/contrib/hstore_plperl/sql/hstore_plperlu.sql
+++ b/contrib/hstore_plperl/sql/hstore_plperlu.sql
@@ -1,6 +1,4 @@
-CREATE EXTENSION hstore;
-CREATE EXTENSION plperlu;
-CREATE EXTENSION hstore_plperlu;
+CREATE EXTENSION hstore_plperlu CASCADE;
SELECT transforms.udt_schema, transforms.udt_name,
routine_schema, routine_name,
diff --git a/contrib/hstore_plpython/expected/hstore_plpython.out b/contrib/hstore_plpython/expected/hstore_plpython.out
index b7a6a92..55f4efe 100644
--- a/contrib/hstore_plpython/expected/hstore_plpython.out
+++ b/contrib/hstore_plpython/expected/hstore_plpython.out
@@ -1,5 +1,5 @@
-CREATE EXTENSION plpython2u;
-CREATE EXTENSION hstore_plpython2u;
+CREATE EXTENSION hstore_plpython2u CASCADE;
+NOTICE: installing required extension "plpython2u"
-- test hstore -> python
CREATE FUNCTION test1(val hstore) RETURNS int
LANGUAGE plpythonu
diff --git a/contrib/hstore_plpython/sql/hstore_plpython.sql b/contrib/hstore_plpython/sql/hstore_plpython.sql
index 9ff2ebc..d55beda 100644
--- a/contrib/hstore_plpython/sql/hstore_plpython.sql
+++ b/contrib/hstore_plpython/sql/hstore_plpython.sql
@@ -1,5 +1,4 @@
-CREATE EXTENSION plpython2u;
-CREATE EXTENSION hstore_plpython2u;
+CREATE EXTENSION hstore_plpython2u CASCADE;
-- test hstore -> python
diff --git a/contrib/ltree_plpython/expected/ltree_plpython.out b/contrib/ltree_plpython/expected/ltree_plpython.out
index 934529e..9bee6be 100644
--- a/contrib/ltree_plpython/expected/ltree_plpython.out
+++ b/contrib/ltree_plpython/expected/ltree_plpython.out
@@ -1,5 +1,5 @@
-CREATE EXTENSION plpython2u;
-CREATE EXTENSION ltree_plpython2u;
+CREATE EXTENSION ltree_plpython2u CASCADE;
+NOTICE: installing required extension "plpython2u"
CREATE FUNCTION test1(val ltree) RETURNS int
LANGUAGE plpythonu
TRANSFORM FOR TYPE ltree
diff --git a/contrib/ltree_plpython/sql/ltree_plpython.sql b/contrib/ltree_plpython/sql/ltree_plpython.sql
index f08ff6a..210f542 100644
--- a/contrib/ltree_plpython/sql/ltree_plpython.sql
+++ b/contrib/ltree_plpython/sql/ltree_plpython.sql
@@ -1,5 +1,4 @@
-CREATE EXTENSION plpython2u;
-CREATE EXTENSION ltree_plpython2u;
+CREATE EXTENSION ltree_plpython2u CASCADE;
CREATE FUNCTION test1(val ltree) RETURNS int
diff --git a/doc/src/sgml/ref/create_extension.sgml b/doc/src/sgml/ref/create_extension.sgml
index a1e7e4f8..fc85f80 100644
--- a/doc/src/sgml/ref/create_extension.sgml
+++ b/doc/src/sgml/ref/create_extension.sgml
@@ -25,6 +25,7 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name
[ WITH ] [ SCHEMA <replaceable class="parameter">schema_name</replaceable> ]
[ VERSION <replaceable class="parameter">version</replaceable> ]
[ FROM <replaceable class="parameter">old_version</replaceable> ]
+ [ CASCADE ]
</synopsis>
</refsynopsisdiv>
@@ -91,8 +92,38 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name
The name of the schema in which to install the extension's
objects, given that the extension allows its contents to be
relocated. The named schema must already exist.
- If not specified, and the extension's control file does not specify a
- schema either, the current default object creation schema is used.
+ If not specified, and the extension control file does not define
+ <literal>schema</> either, the current default object creation
+ schema is used.
+ </para>
+ <para>
+ If the extension specifies <literal>schema</> in its control file,
+ the schema cannot be overriden with <literal>SCHEMA</> clause.
+ The <literal>SCHEMA</> clause in this case works as follows:
+ <itemizedlist>
+ <listitem>
+ <para>
+ If <replaceable class="parameter">schema_name</replaceable> matches
+ the schema in control file, it will be used normally as there is no
+ conflict.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the <literal>CASCADE</> clause is defined, the
+ <replaceable class="parameter">schema_name</replaceable> will only
+ be used for the missing required extensions which do not specify
+ <literal>schema</> in their control files.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If <replaceable class="parameter">schema_name</replaceable> is not
+ the same as the one in extension's control file and the
+ <literal>CASCADE</> clause is not given, error will be thrown.
+ </para>
+ </listitem>
+ </itemizedlist>
</para>
<para>
Remember that the extension itself is not considered to be within any
@@ -139,6 +170,18 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>CASCADE</></term>
+ <listitem>
+ <para>
+ Try to install extension including the required dependencies
+ recursively. The <literal>SCHEMA</> option will be propagated
+ to the required extensions. Other options are not recursively
+ applied when using this clause.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 2b1dcd0..0dfbe7a 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -48,6 +48,7 @@
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "storage/fd.h"
#include "tcop/utility.h"
#include "utils/builtins.h"
@@ -1173,10 +1174,12 @@ CreateExtension(CreateExtensionStmt *stmt)
DefElem *d_schema = NULL;
DefElem *d_new_version = NULL;
DefElem *d_old_version = NULL;
+ DefElem *d_cascade = NULL;
char *schemaName;
- Oid schemaOid;
+ Oid schemaOid = InvalidOid;
char *versionName;
char *oldVersionName;
+ List *cascade_parents = NIL;
Oid extowner = GetUserId();
ExtensionControlFile *pcontrol;
ExtensionControlFile *control;
@@ -1260,6 +1263,14 @@ CreateExtension(CreateExtensionStmt *stmt)
errmsg("conflicting or redundant options")));
d_old_version = defel;
}
+ else if (strcmp(defel->defname, "cascade") == 0)
+ {
+ if (d_cascade)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ d_cascade = defel;
+ }
else
elog(ERROR, "unrecognized option: %s", defel->defname);
}
@@ -1330,6 +1341,14 @@ CreateExtension(CreateExtensionStmt *stmt)
*/
control = read_extension_aux_control_file(pcontrol, versionName);
+
+ /* Handle the CASCADE option. */
+ if (d_cascade)
+ {
+ if (d_cascade->arg)
+ cascade_parents = (List *) d_cascade->arg;
+ }
+
/*
* Determine the target schema to install the extension into
*/
@@ -1338,12 +1357,12 @@ CreateExtension(CreateExtensionStmt *stmt)
/*
* User given schema, CREATE EXTENSION ... WITH SCHEMA ...
*
- * It's an error to give a schema different from control->schema if
- * control->schema is specified.
+ * Unless CASCADE parameter was given, it's an error to give a schema
+ * different from control->schema if control->schema is specified.
*/
schemaName = strVal(d_schema->arg);
- if (control->schema != NULL &&
+ if (d_cascade == NULL && control->schema != NULL &&
strcmp(control->schema, schemaName) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1351,19 +1370,22 @@ CreateExtension(CreateExtensionStmt *stmt)
control->name,
control->schema)));
- /* If the user is giving us the schema name, it must exist already */
+ /* If the user is giving us the schema name, it must exist already. */
schemaOid = get_namespace_oid(schemaName, false);
}
- else if (control->schema != NULL)
+
+ if (control->schema != NULL)
{
/*
* The extension is not relocatable and the author gave us a schema
* for it. We create the schema here if it does not already exist.
+ *
+ * We already did the validation of user specified schema above.
*/
schemaName = control->schema;
schemaOid = get_namespace_oid(schemaName, true);
- if (schemaOid == InvalidOid)
+ if (!OidIsValid(schemaOid))
{
CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
@@ -1375,16 +1397,17 @@ CreateExtension(CreateExtensionStmt *stmt)
/*
* CreateSchemaCommand includes CommandCounterIncrement, so new
- * schema is now visible
+ * schema is now visible.
*/
schemaOid = get_namespace_oid(schemaName, false);
}
}
- else
+ else if (!OidIsValid(schemaOid))
{
/*
- * Else, use the current default creation namespace, which is the
- * first explicit entry in the search_path.
+ * Neither user nor author of the extension specified schema, use the
+ * current default creation namespace, which is the first explicit
+ * entry in the search_path.
*/
List *search_path = fetch_search_path(false);
@@ -1429,10 +1452,60 @@ CreateExtension(CreateExtensionStmt *stmt)
*/
reqext = get_extension_oid(curreq, true);
if (!OidIsValid(reqext))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("required extension \"%s\" is not installed",
- curreq)));
+ {
+ if (d_cascade)
+ {
+ CreateExtensionStmt *ces;
+ ListCell *lc;
+ ObjectAddress addr;
+
+ ereport(NOTICE,
+ (errmsg("installing required extension \"%s\"",
+ curreq)));
+
+ /* Check for cyclic dependency between extensions. */
+ foreach(lc, cascade_parents)
+ {
+ char *pname = (char *) lfirst(lc);
+
+ if (strcmp(pname, curreq) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_RECURSION),
+ errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
+ curreq, stmt->extname)));
+ }
+
+ /* Create and execute new CREATE EXTENSION statement. */
+ ces = makeNode(CreateExtensionStmt);
+ ces->extname = curreq;
+ ces->if_not_exists = false;
+
+ /*
+ * Propagate the CASCADE option and add current extension
+ * to the list for checking the cyclic dependencies.
+ */
+ cascade_parents = lappend(cascade_parents, stmt->extname);
+ ces->options = list_make1(makeDefElem("cascade",
+ (Node *) cascade_parents));
+
+ /* Propagate the SCHEMA option if given. */
+ if (d_schema && d_schema->arg)
+ ces->options = lappend(ces->options, d_schema);
+
+ addr = CreateExtension(ces);
+ reqext = addr.objectId;
+
+ /* We leak the DeflElems but probably not worth worrying about */
+ list_free(ces->options);
+ pfree(ces);
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("required extension \"%s\" is not installed",
+ curreq)));
+ }
+
reqschema = get_extension_schema(reqext);
requiredExtensions = lappend_oid(requiredExtensions, reqext);
requiredSchemas = lappend_oid(requiredSchemas, reqschema);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 6b02cec..4fb5457 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3877,6 +3877,10 @@ create_extension_opt_item:
{
$$ = makeDefElem("old_version", (Node *)makeString($2));
}
+ | CASCADE
+ {
+ $$ = makeDefElem("cascade", NULL);
+ }
;
/*****************************************************************************
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index ece0515..04da67c 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -2247,7 +2247,12 @@ psql_completion(const char *text, int start, int end)
/* CREATE EXTENSION <name> */
else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
- COMPLETE_WITH_CONST("WITH SCHEMA");
+ {
+ static const char *const list_CREATE_EXTENSION[] =
+ {"WITH SCHEMA", "CASCADE", NULL};
+
+ COMPLETE_WITH_LIST(list_CREATE_EXTENSION);
+ }
/* CREATE FOREIGN */
else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 8213e23..84b4423 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -8,6 +8,7 @@ SUBDIRS = \
commit_ts \
dummy_seclabel \
test_ddl_deparse \
+ test_extensions \
test_parser \
test_rls_hooks \
test_shm_mq \
diff --git a/src/test/modules/test_extensions/.gitignore b/src/test/modules/test_extensions/.gitignore
new file mode 100644
index 0000000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/test_extensions/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_extensions/Makefile b/src/test/modules/test_extensions/Makefile
new file mode 100644
index 0000000..6c50e6c
--- /dev/null
+++ b/src/test/modules/test_extensions/Makefile
@@ -0,0 +1,21 @@
+# src/test/modules/test_extensions/Makefile
+
+MODULE = test_extensions
+PGFILEDESC = "test_extensions - regression testing for EXTENSION support"
+
+EXTENSION = test_ext1 test_ext2 test_ext3 test_ext_cyclic1 test_ext_cyclic2
+DATA = test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \
+ test_ext_cyclic1--1.0.sql test_ext_cyclic2--1.0.sql
+
+REGRESS = test_extensions
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_extensions
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
new file mode 100644
index 0000000..6cc24e2
--- /dev/null
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -0,0 +1,30 @@
+-- test some errors
+CREATE EXTENSION test_ext1;
+ERROR: required extension "test_ext2" is not installed
+CREATE EXTENSION test_ext1 SCHEMA test_ext1;
+ERROR: schema "test_ext1" does not exist
+CREATE EXTENSION test_ext1 SCHEMA test_ext;
+ERROR: extension "test_ext1" must be installed in schema "test_ext1"
+CREATE SCHEMA test_ext;
+CREATE EXTENSION test_ext1 SCHEMA test_ext;
+ERROR: extension "test_ext1" must be installed in schema "test_ext1"
+-- finally success
+CREATE EXTENSION test_ext1 SCHEMA test_ext CASCADE;
+NOTICE: installing required extension "test_ext2"
+NOTICE: installing required extension "test_ext3"
+SELECT extname, nspname, extversion, extrelocatable FROM pg_extension e, pg_namespace n WHERE extname LIKE 'test_ext%' AND e.extnamespace = n.oid;
+ extname | nspname | extversion | extrelocatable
+-----------+-----------+------------+----------------
+ test_ext2 | test_ext | 1.0 | t
+ test_ext3 | test_ext | 1.0 | t
+ test_ext1 | test_ext1 | 1.0 | f
+(3 rows)
+
+CREATE EXTENSION test_ext_cyclic1 CASCADE;
+NOTICE: installing required extension "test_ext_cyclic2"
+NOTICE: installing required extension "test_ext_cyclic1"
+ERROR: cyclic dependency detected between extensions "test_ext_cyclic1" and "test_ext_cyclic2"
+DROP EXTENSION test_ext1;
+DROP EXTENSION test_ext2;
+DROP EXTENSION test_ext3;
+DROP SCHEMA test_ext;
diff --git a/src/test/modules/test_extensions/sql/test_extensions.sql b/src/test/modules/test_extensions/sql/test_extensions.sql
new file mode 100644
index 0000000..640ac9b
--- /dev/null
+++ b/src/test/modules/test_extensions/sql/test_extensions.sql
@@ -0,0 +1,18 @@
+-- test some errors
+CREATE EXTENSION test_ext1;
+CREATE EXTENSION test_ext1 SCHEMA test_ext1;
+CREATE EXTENSION test_ext1 SCHEMA test_ext;
+CREATE SCHEMA test_ext;
+CREATE EXTENSION test_ext1 SCHEMA test_ext;
+
+-- finally success
+CREATE EXTENSION test_ext1 SCHEMA test_ext CASCADE;
+
+SELECT extname, nspname, extversion, extrelocatable FROM pg_extension e, pg_namespace n WHERE extname LIKE 'test_ext%' AND e.extnamespace = n.oid;
+
+CREATE EXTENSION test_ext_cyclic1 CASCADE;
+
+DROP EXTENSION test_ext1;
+DROP EXTENSION test_ext2;
+DROP EXTENSION test_ext3;
+DROP SCHEMA test_ext;
diff --git a/src/test/modules/test_extensions/test_ext1--1.0.sql b/src/test/modules/test_extensions/test_ext1--1.0.sql
new file mode 100644
index 0000000..9a4bb1b
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext1--1.0.sql
@@ -0,0 +1,3 @@
+/* src/test/modules/test_extensions/test_ext1--1.0.sql */
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ext1" to load this file. \quit
diff --git a/src/test/modules/test_extensions/test_ext1.control b/src/test/modules/test_extensions/test_ext1.control
new file mode 100644
index 0000000..ae50cd8
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext1.control
@@ -0,0 +1,5 @@
+comment = 'Test extension 1'
+default_version = '1.0'
+schema = 'test_ext1'
+relocatable = false
+requires = 'test_ext2'
diff --git a/src/test/modules/test_extensions/test_ext2--1.0.sql b/src/test/modules/test_extensions/test_ext2--1.0.sql
new file mode 100644
index 0000000..0f6d4ec
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext2--1.0.sql
@@ -0,0 +1,3 @@
+/* src/test/modules/test_extensions/test_ext2--1.0.sql */
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ext2" to load this file. \quit
diff --git a/src/test/modules/test_extensions/test_ext2.control b/src/test/modules/test_extensions/test_ext2.control
new file mode 100644
index 0000000..788337e
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext2.control
@@ -0,0 +1,4 @@
+comment = 'Test extension 2'
+default_version = '1.0'
+relocatable = true
+requires = 'test_ext3'
diff --git a/src/test/modules/test_extensions/test_ext3--1.0.sql b/src/test/modules/test_extensions/test_ext3--1.0.sql
new file mode 100644
index 0000000..7dec684
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext3--1.0.sql
@@ -0,0 +1,3 @@
+/* src/test/modules/test_extensions/test_ext3--1.0.sql */
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ext3" to load this file. \quit
diff --git a/src/test/modules/test_extensions/test_ext3.control b/src/test/modules/test_extensions/test_ext3.control
new file mode 100644
index 0000000..5f1afe7
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext3.control
@@ -0,0 +1,3 @@
+comment = 'Test extension 3'
+default_version = '1.0'
+relocatable = true
diff --git a/src/test/modules/test_extensions/test_ext_cyclic1--1.0.sql b/src/test/modules/test_extensions/test_ext_cyclic1--1.0.sql
new file mode 100644
index 0000000..81bdaf4
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext_cyclic1--1.0.sql
@@ -0,0 +1,3 @@
+/* src/test/modules/test_extensions/test_ext_cyclic1--1.0.sql */
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ext_cyclic1" to load this file. \quit
diff --git a/src/test/modules/test_extensions/test_ext_cyclic1.control b/src/test/modules/test_extensions/test_ext_cyclic1.control
new file mode 100644
index 0000000..aaab403
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext_cyclic1.control
@@ -0,0 +1,4 @@
+comment = 'Test extension cyclic 1'
+default_version = '1.0'
+relocatable = true
+requires = 'test_ext_cyclic2'
diff --git a/src/test/modules/test_extensions/test_ext_cyclic2--1.0.sql b/src/test/modules/test_extensions/test_ext_cyclic2--1.0.sql
new file mode 100644
index 0000000..ae2b3e9
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext_cyclic2--1.0.sql
@@ -0,0 +1,3 @@
+/* src/test/modules/test_extensions/test_ext_cyclic2--1.0.sql */
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ext_cyclic2" to load this file. \quit
diff --git a/src/test/modules/test_extensions/test_ext_cyclic2.control b/src/test/modules/test_extensions/test_ext_cyclic2.control
new file mode 100644
index 0000000..1e28f96
--- /dev/null
+++ b/src/test/modules/test_extensions/test_ext_cyclic2.control
@@ -0,0 +1,4 @@
+comment = 'Test extension cyclic 2'
+default_version = '1.0'
+relocatable = true
+requires = 'test_ext_cyclic1'
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index d70db40..9b3e31e 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -41,7 +41,7 @@ my $contrib_extrasource = {
'seg' => [ 'contrib/seg/segscan.l', 'contrib/seg/segparse.y' ], };
my @contrib_excludes = (
'commit_ts', 'hstore_plperl', 'hstore_plpython', 'intagg',
- 'ltree_plpython', 'pgcrypto', 'sepgsql');
+ 'ltree_plpython', 'pgcrypto', 'sepgsql', 'test_extensions');
# Set of variables for frontend modules
my $frontend_defines = { 'initdb' => 'FRONTEND' };
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers