diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 6ff30ddc0ae67c4b4e92214756156b351ac8dea1..b1673e6549a0ac945d9971d357ad07e559323c40 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -1188,7 +1188,6 @@ CreateExtension(CreateExtensionStmt *stmt) List *requiredExtensions; List *requiredSchemas; Oid extensionOid; - AclResult aclresult; ListCell *lc; /* Check extension name validity before any filesystem access */ @@ -1393,13 +1392,13 @@ CreateExtension(CreateExtensionStmt *stmt) } /* - * Check we have creation rights in target namespace. Although strictly - * speaking the extension itself isn't in the schema, it will almost - * certainly want to create objects therein, so let's just check now. + * We don't check creation rights on the target namespace here. If the + * extension script actually creates any objects there, it will fail if + * the user doesn't have such permissions. But there are cases such as + * procedural languages where it's convenient to set schema = pg_catalog + * yet we don't want to restrict the command to users with ACL_CREATE + * for pg_catalog. */ - aclresult = pg_namespace_aclcheck(schemaOid, extowner, ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, schemaName); /* * Look up the prerequisite extensions, and build lists of their OIDs diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 98915c4b8914b9fd9a0b85ed45f9790a5328e5a2..ce24d6101d13832e876e002b2d775e11fa94b60b 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1912,7 +1912,7 @@ load_plpgsql(void) PG_CMD_OPEN; - PG_CMD_PUTS("CREATE LANGUAGE plpgsql;\n"); + PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n"); PG_CMD_CLOSE; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index ea1818b1d574d107e93015a14e01f86ade46e2f4..dfbdcadd1453f72815f41c5e91a92ee3a2693afc 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -1171,6 +1171,24 @@ selectDumpableDefaultACL(DefaultACLInfo *dinfo) dinfo->dobj.dump = include_everything; } +/* + * selectDumpableExtension: policy-setting subroutine + * Mark an extension as to be dumped or not + * + * Normally, we just dump all extensions. However, in binary-upgrade mode + * it's necessary to skip built-in extensions, since we assume those will + * already be installed in the target database. We identify such extensions + * by their having OIDs in the range reserved for initdb. + */ +static void +selectDumpableExtension(ExtensionInfo *extinfo) +{ + if (binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId) + extinfo->dobj.dump = false; + else + extinfo->dobj.dump = true; +} + /* * selectDumpableObject: policy-setting subroutine * Mark a generic dumpable object as to be dumped or not @@ -2730,6 +2748,9 @@ getExtensions(int *numExtensions) extinfo[i].extversion = strdup(PQgetvalue(res, i, i_extversion)); extinfo[i].extconfig = strdup(PQgetvalue(res, i, i_extconfig)); extinfo[i].extcondition = strdup(PQgetvalue(res, i, i_extcondition)); + + /* Decide whether we want to dump it */ + selectDumpableExtension(&(extinfo[i])); } PQclear(res); @@ -7042,19 +7063,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) if (!extinfo->dobj.dump || dataOnly) return; - /* - * In a regular dump, we use IF NOT EXISTS so that there isn't a problem - * if the extension already exists in the target database; this is - * essential for installed-by-default extensions such as plpgsql. - * - * In binary-upgrade mode, that doesn't work well, so instead we skip - * extensions with OIDs less than FirstNormalObjectId; those were - * presumably installed by initdb, and we assume they'll exist in the - * target installation too. - */ - if (binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId) - return; - q = createPQExpBuffer(); delq = createPQExpBuffer(); labelq = createPQExpBuffer(); @@ -7065,6 +7073,16 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) if (!binary_upgrade) { + /* + * In a regular dump, we use IF NOT EXISTS so that there isn't a + * problem if the extension already exists in the target database; + * this is essential for installed-by-default extensions such as + * plpgsql. + * + * In binary-upgrade mode, that doesn't work well, so instead we skip + * built-in extensions based on their OIDs; see + * selectDumpableExtension. + */ appendPQExpBuffer(q, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s;\n", qextname, fmtId(extinfo->namespace)); } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index fe7ccf4ba0ba1c3ce7114dcb949bdf29ae32f737..56fb4931ba7c56884d31b9457499c6d51555e182 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201103041 +#define CATALOG_VERSION_NO 201103042 #endif diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h index c0578f92c098d7115b1926b4d0088a6387b85ad5..fa086525e7ffe4488a7c66af2eb6c62b63d2c99a 100644 --- a/src/include/catalog/pg_pltemplate.h +++ b/src/include/catalog/pg_pltemplate.h @@ -71,9 +71,9 @@ DATA(insert ( "plpgsql" t t "plpgsql_call_handler" "plpgsql_inline_handler" "pl DATA(insert ( "pltcl" t t "pltcl_call_handler" _null_ _null_ "$libdir/pltcl" _null_ )); DATA(insert ( "pltclu" f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ )); DATA(insert ( "plperl" t t "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); -DATA(insert ( "plperlu" f f "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); +DATA(insert ( "plperlu" f f "plperlu_call_handler" "plperlu_inline_handler" "plperlu_validator" "$libdir/plperl" _null_ )); DATA(insert ( "plpythonu" f f "plpython_call_handler" "plpython_inline_handler" "plpython_validator" "$libdir/plpython" _null_ )); -DATA(insert ( "plpython2u" f f "plpython_call_handler" "plpython_inline_handler" "plpython_validator" "$libdir/plpython2" _null_ )); +DATA(insert ( "plpython2u" f f "plpython2_call_handler" "plpython2_inline_handler" "plpython2_validator" "$libdir/plpython2" _null_ )); DATA(insert ( "plpython3u" f f "plpython3_call_handler" "plpython3_inline_handler" "plpython3_validator" "$libdir/plpython3" _null_ )); #endif /* PG_PLTEMPLATE_H */ diff --git a/src/pl/plperl/GNUmakefile b/src/pl/plperl/GNUmakefile index e86cb84dba22734686390c2586b2cb7aa2f873c3..71e2cef4c5ecb553aa5b9b91afa962302f6c247a 100644 --- a/src/pl/plperl/GNUmakefile +++ b/src/pl/plperl/GNUmakefile @@ -36,11 +36,14 @@ NAME = plperl OBJS = plperl.o SPI.o Util.o +DATA = plperl.control plperl--1.0.sql plperl--unpackaged--1.0.sql \ + plperlu.control plperlu--1.0.sql plperlu--unpackaged--1.0.sql + PERLCHUNKS = plc_perlboot.pl plc_trusted.pl SHLIB_LINK = $(perl_embed_ldflags) -REGRESS_OPTS = --dbname=$(PL_TESTDB) --load-language=plperl --load-language=plperlu +REGRESS_OPTS = --dbname=$(PL_TESTDB) --load-extension=plperl --load-extension=plperlu REGRESS = plperl plperl_trigger plperl_shared plperl_elog plperl_util plperl_init plperlu plperl_array # if Perl can support two interpreters in one backend, # test plperl-and-plperlu cases @@ -70,11 +73,25 @@ SPI.c: SPI.xs Util.c: Util.xs $(PERL) $(perl_privlibexp)/ExtUtils/xsubpp -typemap $(perl_privlibexp)/ExtUtils/typemap $< >$@ -install: all installdirs install-lib + +install: all installdirs install-lib install-data installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(datadir)/extension' + +uninstall: uninstall-lib uninstall-data + +install-data: + @for file in $(addprefix $(srcdir)/, $(DATA)); do \ + echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'"; \ + $(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'; \ + done + +uninstall-data: + rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA))) + +.PHONY: install-data uninstall-data -uninstall: uninstall-lib check: submake $(pg_regress_check) $(REGRESS_OPTS) $(REGRESS) diff --git a/src/pl/plperl/plperl--1.0.sql b/src/pl/plperl/plperl--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..befd88274550ce4ca8ef0accfb065e4d7971049a --- /dev/null +++ b/src/pl/plperl/plperl--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plperl/plperl--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plperl; diff --git a/src/pl/plperl/plperl--unpackaged--1.0.sql b/src/pl/plperl/plperl--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..b062bd5d9b3d983c948115f38e946035b567d02f --- /dev/null +++ b/src/pl/plperl/plperl--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plperl/plperl--unpackaged--1.0.sql */ + +ALTER EXTENSION plperl ADD PROCEDURAL LANGUAGE plperl; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plperl ADD FUNCTION plperl_call_handler(); +ALTER EXTENSION plperl ADD FUNCTION plperl_inline_handler(internal); +ALTER EXTENSION plperl ADD FUNCTION plperl_validator(oid); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 72e1e5106a679a463db19c61ae96ef321eb309f2..9a94b3f085236d4333eb1a80a8e1d19dcb891681 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -222,6 +222,9 @@ static plperl_call_data *current_call_data = NULL; Datum plperl_call_handler(PG_FUNCTION_ARGS); Datum plperl_inline_handler(PG_FUNCTION_ARGS); Datum plperl_validator(PG_FUNCTION_ARGS); +Datum plperlu_call_handler(PG_FUNCTION_ARGS); +Datum plperlu_inline_handler(PG_FUNCTION_ARGS); +Datum plperlu_validator(PG_FUNCTION_ARGS); void _PG_init(void); static PerlInterpreter *plperl_init_interp(void); @@ -1758,6 +1761,39 @@ plperl_validator(PG_FUNCTION_ARGS) } +/* + * plperlu likewise requires three externally visible functions: + * plperlu_call_handler, plperlu_inline_handler, and plperlu_validator. + * These are currently just aliases that send control to the plperl + * handler functions, and we decide whether a particular function is + * trusted or not by inspecting the actual pg_language tuple. + */ + +PG_FUNCTION_INFO_V1(plperlu_call_handler); + +Datum +plperlu_call_handler(PG_FUNCTION_ARGS) +{ + return plperl_call_handler(fcinfo); +} + +PG_FUNCTION_INFO_V1(plperlu_inline_handler); + +Datum +plperlu_inline_handler(PG_FUNCTION_ARGS) +{ + return plperl_inline_handler(fcinfo); +} + +PG_FUNCTION_INFO_V1(plperlu_validator); + +Datum +plperlu_validator(PG_FUNCTION_ARGS) +{ + return plperl_validator(fcinfo); +} + + /* * Uses mksafefunc/mkunsafefunc to create a subroutine whose text is * supplied in s, and returns a reference to it diff --git a/src/pl/plperl/plperl.control b/src/pl/plperl/plperl.control new file mode 100644 index 0000000000000000000000000000000000000000..6faace12fa5197b0252869702e43f6002266b4e2 --- /dev/null +++ b/src/pl/plperl/plperl.control @@ -0,0 +1,7 @@ +# plperl extension +comment = 'PL/Perl procedural language' +default_version = '1.0' +module_pathname = '$libdir/plperl' +relocatable = false +schema = pg_catalog +superuser = false diff --git a/src/pl/plperl/plperlu--1.0.sql b/src/pl/plperl/plperlu--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..025f7957c4d8f5a86da88d26418754ea5a411a41 --- /dev/null +++ b/src/pl/plperl/plperlu--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plperl/plperlu--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plperlu; diff --git a/src/pl/plperl/plperlu--unpackaged--1.0.sql b/src/pl/plperl/plperlu--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..bc62d36a3d864e6195dfca56b9f72af9d199b103 --- /dev/null +++ b/src/pl/plperl/plperlu--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plperl/plperlu--unpackaged--1.0.sql */ + +ALTER EXTENSION plperlu ADD PROCEDURAL LANGUAGE plperlu; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plperlu ADD FUNCTION plperlu_call_handler(); +ALTER EXTENSION plperlu ADD FUNCTION plperlu_inline_handler(internal); +ALTER EXTENSION plperlu ADD FUNCTION plperlu_validator(oid); diff --git a/src/pl/plperl/plperlu.control b/src/pl/plperl/plperlu.control new file mode 100644 index 0000000000000000000000000000000000000000..69473caed47de76d15315dd0d58aa35ad8037061 --- /dev/null +++ b/src/pl/plperl/plperlu.control @@ -0,0 +1,7 @@ +# plperlu extension +comment = 'PL/PerlU untrusted procedural language' +default_version = '1.0' +module_pathname = '$libdir/plperl' +relocatable = false +schema = pg_catalog +superuser = true diff --git a/src/pl/plpgsql/src/Makefile b/src/pl/plpgsql/src/Makefile index a5f161dc62d76d706fae7bf36f7b5ba11a6e1b93..d748ef682621f3b5fa2410130aa4e030ff1c08fc 100644 --- a/src/pl/plpgsql/src/Makefile +++ b/src/pl/plpgsql/src/Makefile @@ -1,6 +1,6 @@ #------------------------------------------------------------------------- # -# Makefile for the plpgsql shared object +# Makefile for the pl/pgsql procedural language # # src/pl/plpgsql/src/Makefile # @@ -19,17 +19,31 @@ rpath = OBJS = pl_gram.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o pl_scanner.o +DATA = plpgsql.control plpgsql--1.0.sql plpgsql--unpackaged--1.0.sql + all: all-lib # Shared library stuff include $(top_srcdir)/src/Makefile.shlib -install: installdirs all install-lib +install: all installdirs install-lib install-data installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(datadir)/extension' + +uninstall: uninstall-lib uninstall-data + +install-data: + @for file in $(addprefix $(srcdir)/, $(DATA)); do \ + echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'"; \ + $(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'; \ + done + +uninstall-data: + rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA))) -uninstall: uninstall-lib +.PHONY: install-data uninstall-data # Force these dependencies to be known even without dependency info built: diff --git a/src/pl/plpgsql/src/plpgsql--1.0.sql b/src/pl/plpgsql/src/plpgsql--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..514562d70fed83509b6498af28d9ec89aa0e9672 --- /dev/null +++ b/src/pl/plpgsql/src/plpgsql--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plpgsql/src/plpgsql--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plpgsql; diff --git a/src/pl/plpgsql/src/plpgsql--unpackaged--1.0.sql b/src/pl/plpgsql/src/plpgsql--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..9de7e8392aae2ea37b0aa8491ec13c63b4d7741a --- /dev/null +++ b/src/pl/plpgsql/src/plpgsql--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plpgsql/src/plpgsql--unpackaged--1.0.sql */ + +ALTER EXTENSION plpgsql ADD PROCEDURAL LANGUAGE plpgsql; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plpgsql ADD FUNCTION plpgsql_call_handler(); +ALTER EXTENSION plpgsql ADD FUNCTION plpgsql_inline_handler(internal); +ALTER EXTENSION plpgsql ADD FUNCTION plpgsql_validator(oid); diff --git a/src/pl/plpgsql/src/plpgsql.control b/src/pl/plpgsql/src/plpgsql.control new file mode 100644 index 0000000000000000000000000000000000000000..b320227b1202e3586b1617f166523626a64d2f74 --- /dev/null +++ b/src/pl/plpgsql/src/plpgsql.control @@ -0,0 +1,7 @@ +# plpgsql extension +comment = 'PL/pgSQL procedural language' +default_version = '1.0' +module_pathname = '$libdir/plpgsql' +relocatable = false +schema = pg_catalog +superuser = false diff --git a/src/pl/plpython/Makefile b/src/pl/plpython/Makefile index e6b6ed3ca5262dc3dd9e158b8c10694d77d75618..46e0195142424a8ec594c5202ee46aa6c60941ec 100644 --- a/src/pl/plpython/Makefile +++ b/src/pl/plpython/Makefile @@ -37,8 +37,13 @@ override CPPFLAGS := -I. -I$(srcdir) $(python_includespec) $(CPPFLAGS) rpathdir = $(python_libdir) NAME = plpython$(python_majorversion) + OBJS = plpython.o +DATA = plpythonu.control plpythonu--1.0.sql plpythonu--unpackaged--1.0.sql \ + plpython2u.control plpython2u--1.0.sql plpython2u--unpackaged--1.0.sql \ + plpython3u.control plpython3u--1.0.sql plpython3u--unpackaged--1.0.sql + # Python on win32 ships with import libraries only for Microsoft Visual C++, # which are not compatible with mingw gcc. Therefore we need to build a @@ -60,7 +65,7 @@ REGRESS_OPTS = --dbname=$(PL_TESTDB) # Only load plpythonu with Python 2. The test files themselves load # the versioned language plpython(2|3)u. ifeq ($(python_majorversion),2) -REGRESS_OPTS += --load-language=plpythonu +REGRESS_OPTS += --load-extension=plpythonu endif REGRESS = \ plpython_schema \ @@ -98,18 +103,32 @@ all: all-lib distprep: spiexceptions.h -install: all installdirs install-lib + +install: all installdirs install-lib install-data ifeq ($(python_majorversion),2) cd '$(DESTDIR)$(pkglibdir)' && rm -f plpython$(DLSUFFIX) && $(LN_S) $(shlib) plpython$(DLSUFFIX) endif installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(datadir)/extension' -uninstall: uninstall-lib +uninstall: uninstall-lib uninstall-data ifeq ($(python_majorversion),2) rm -f '$(DESTDIR)$(pkglibdir)/plpython$(DLSUFFIX)' endif +install-data: + @for file in $(addprefix $(srcdir)/, $(DATA)); do \ + echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'"; \ + $(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'; \ + done + +uninstall-data: + rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA))) + +.PHONY: install-data uninstall-data + + ifeq ($(python_majorversion),3) # Adjust regression tests for Python 3 compatibility prep3: @@ -124,6 +143,8 @@ prep3: -e "s/def next/def __next__/g" \ -e "s/LANGUAGE plpythonu/LANGUAGE plpython3u/g" \ -e "s/LANGUAGE plpython2u/LANGUAGE plpython3u/g" \ + -e "s/EXTENSION plpythonu/EXTENSION plpython3u/g" \ + -e "s/EXTENSION plpython2u/EXTENSION plpython3u/g" \ $$file >`echo $$file | sed 's,$(srcdir),python3,'`; \ done diff --git a/src/pl/plpython/expected/plpython_drop.out b/src/pl/plpython/expected/plpython_drop.out index fef642f7c06f8655875a82efcfe199191843466f..a0e3b5c4ef64bf8cfaf5adb288971eb6202c536e 100644 --- a/src/pl/plpython/expected/plpython_drop.out +++ b/src/pl/plpython/expected/plpython_drop.out @@ -2,4 +2,5 @@ -- For paranoia's sake, don't leave an untrusted language sitting around -- SET client_min_messages = WARNING; -DROP PROCEDURAL LANGUAGE plpythonu CASCADE; +DROP EXTENSION plpythonu CASCADE; +DROP EXTENSION IF EXISTS plpython2u CASCADE; diff --git a/src/pl/plpython/expected/plpython_test.out b/src/pl/plpython/expected/plpython_test.out index 7b2e1703f4bc5ed82a0beddf1fd6696778d0896b..c2358b452d9472e571a71d24681c921cbfeff375 100644 --- a/src/pl/plpython/expected/plpython_test.out +++ b/src/pl/plpython/expected/plpython_test.out @@ -1,5 +1,5 @@ -- first some tests of basic functionality -CREATE LANGUAGE plpython2u; +CREATE EXTENSION plpython2u; -- really stupid function just to get the module loaded CREATE FUNCTION stupid() RETURNS text AS 'return "zarkon"' LANGUAGE plpythonu; select stupid(); diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 75f7b5cf57fc371ce4a38e6eb8240d9f4d17155b..e415aa36f41c9a6cccc5f2729c5165bd3addb165 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -4652,3 +4652,36 @@ PLyUnicode_FromString(const char *s) } #endif /* PY_MAJOR_VERSION >= 3 */ + +#if PY_MAJOR_VERSION < 3 + +/* Define aliases plpython2_call_handler etc */ +Datum plpython2_call_handler(PG_FUNCTION_ARGS); +Datum plpython2_inline_handler(PG_FUNCTION_ARGS); +Datum plpython2_validator(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(plpython2_call_handler); + +Datum +plpython2_call_handler(PG_FUNCTION_ARGS) +{ + return plpython_call_handler(fcinfo); +} + +PG_FUNCTION_INFO_V1(plpython2_inline_handler); + +Datum +plpython2_inline_handler(PG_FUNCTION_ARGS) +{ + return plpython_inline_handler(fcinfo); +} + +PG_FUNCTION_INFO_V1(plpython2_validator); + +Datum +plpython2_validator(PG_FUNCTION_ARGS) +{ + return plpython_validator(fcinfo); +} + +#endif /* PY_MAJOR_VERSION < 3 */ diff --git a/src/pl/plpython/plpython2u--1.0.sql b/src/pl/plpython/plpython2u--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..0e4787650207ae6047eb3b787f6726a202d2cee4 --- /dev/null +++ b/src/pl/plpython/plpython2u--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plpython/plpython2u--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plpython2u; diff --git a/src/pl/plpython/plpython2u--unpackaged--1.0.sql b/src/pl/plpython/plpython2u--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..a89d8b4d09e77ec37d41471687644b4ac3019d32 --- /dev/null +++ b/src/pl/plpython/plpython2u--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plpython/plpython2u--unpackaged--1.0.sql */ + +ALTER EXTENSION plpython2u ADD PROCEDURAL LANGUAGE plpython2u; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plpython2u ADD FUNCTION plpython2_call_handler(); +ALTER EXTENSION plpython2u ADD FUNCTION plpython2_inline_handler(internal); +ALTER EXTENSION plpython2u ADD FUNCTION plpython2_validator(oid); diff --git a/src/pl/plpython/plpython2u.control b/src/pl/plpython/plpython2u.control new file mode 100644 index 0000000000000000000000000000000000000000..39c2b791efe7524be46f66a2fa513bc2af0d139b --- /dev/null +++ b/src/pl/plpython/plpython2u.control @@ -0,0 +1,7 @@ +# plpython2u extension +comment = 'PL/Python2U untrusted procedural language' +default_version = '1.0' +module_pathname = '$libdir/plpython2' +relocatable = false +schema = pg_catalog +superuser = true diff --git a/src/pl/plpython/plpython3u--1.0.sql b/src/pl/plpython/plpython3u--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..d5c6e5ab96aef7781c0645c75e87e1186c8fdeee --- /dev/null +++ b/src/pl/plpython/plpython3u--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plpython/plpython3u--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plpython3u; diff --git a/src/pl/plpython/plpython3u--unpackaged--1.0.sql b/src/pl/plpython/plpython3u--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..b1c0d03a3043ab7f13a981b60496685996d9ddb5 --- /dev/null +++ b/src/pl/plpython/plpython3u--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plpython/plpython3u--unpackaged--1.0.sql */ + +ALTER EXTENSION plpython3u ADD PROCEDURAL LANGUAGE plpython3u; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plpython3u ADD FUNCTION plpython3_call_handler(); +ALTER EXTENSION plpython3u ADD FUNCTION plpython3_inline_handler(internal); +ALTER EXTENSION plpython3u ADD FUNCTION plpython3_validator(oid); diff --git a/src/pl/plpython/plpython3u.control b/src/pl/plpython/plpython3u.control new file mode 100644 index 0000000000000000000000000000000000000000..01905ef398b0fdee320ce060c7cf2f513889081e --- /dev/null +++ b/src/pl/plpython/plpython3u.control @@ -0,0 +1,7 @@ +# plpython3u extension +comment = 'PL/Python3U untrusted procedural language' +default_version = '1.0' +module_pathname = '$libdir/plpython3' +relocatable = false +schema = pg_catalog +superuser = true diff --git a/src/pl/plpython/plpythonu--1.0.sql b/src/pl/plpython/plpythonu--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..beb0aa16457774ee747a3265c8b2001de1baf1e9 --- /dev/null +++ b/src/pl/plpython/plpythonu--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/plpython/plpythonu--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE plpythonu; diff --git a/src/pl/plpython/plpythonu--unpackaged--1.0.sql b/src/pl/plpython/plpythonu--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..7926233250830a3f13deeac003c4bff9a8dfcfd0 --- /dev/null +++ b/src/pl/plpython/plpythonu--unpackaged--1.0.sql @@ -0,0 +1,7 @@ +/* src/pl/plpython/plpythonu--unpackaged--1.0.sql */ + +ALTER EXTENSION plpythonu ADD PROCEDURAL LANGUAGE plpythonu; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION plpythonu ADD FUNCTION plpython_call_handler(); +ALTER EXTENSION plpythonu ADD FUNCTION plpython_inline_handler(internal); +ALTER EXTENSION plpythonu ADD FUNCTION plpython_validator(oid); diff --git a/src/pl/plpython/plpythonu.control b/src/pl/plpython/plpythonu.control new file mode 100644 index 0000000000000000000000000000000000000000..ae91b1c255c665329a15507a53755e6491e532e5 --- /dev/null +++ b/src/pl/plpython/plpythonu.control @@ -0,0 +1,7 @@ +# plpythonu extension +comment = 'PL/PythonU untrusted procedural language' +default_version = '1.0' +module_pathname = '$libdir/plpython2' +relocatable = false +schema = pg_catalog +superuser = true diff --git a/src/pl/plpython/sql/plpython_drop.sql b/src/pl/plpython/sql/plpython_drop.sql index 319d5e0925d1a405a15aefe980909c7ba9f6245c..72d5d657ec3f593f8b92028116dea70e270a548d 100644 --- a/src/pl/plpython/sql/plpython_drop.sql +++ b/src/pl/plpython/sql/plpython_drop.sql @@ -3,4 +3,6 @@ -- SET client_min_messages = WARNING; -DROP PROCEDURAL LANGUAGE plpythonu CASCADE; +DROP EXTENSION plpythonu CASCADE; + +DROP EXTENSION IF EXISTS plpython2u CASCADE; diff --git a/src/pl/plpython/sql/plpython_test.sql b/src/pl/plpython/sql/plpython_test.sql index 915189847a7cf0fd420da6c6c942dec65e60abbf..c8d5ef5f534613320f857863ade9d39cdb7287e1 100644 --- a/src/pl/plpython/sql/plpython_test.sql +++ b/src/pl/plpython/sql/plpython_test.sql @@ -1,5 +1,5 @@ -- first some tests of basic functionality -CREATE LANGUAGE plpython2u; +CREATE EXTENSION plpython2u; -- really stupid function just to get the module loaded CREATE FUNCTION stupid() RETURNS text AS 'return "zarkon"' LANGUAGE plpythonu; diff --git a/src/pl/tcl/Makefile b/src/pl/tcl/Makefile index b29478dd6fd135d4b1803bffe1da29d3dc546f0d..c7797c61f5eca6e6fe020831c98fa7e88c8834d9 100644 --- a/src/pl/tcl/Makefile +++ b/src/pl/tcl/Makefile @@ -1,6 +1,6 @@ #------------------------------------------------------------------------- # -# Makefile for the pltcl shared object +# Makefile for the pl/tcl procedural language # # src/pl/tcl/Makefile # @@ -35,9 +35,13 @@ SHLIB_LINK += $(TCL_LIBS) -lc endif NAME = pltcl + OBJS = pltcl.o -REGRESS_OPTS = --dbname=$(PL_TESTDB) --load-language=pltcl +DATA = pltcl.control pltcl--1.0.sql pltcl--unpackaged--1.0.sql \ + pltclu.control pltclu--1.0.sql pltclu--unpackaged--1.0.sql + +REGRESS_OPTS = --dbname=$(PL_TESTDB) --load-extension=pltcl REGRESS = pltcl_setup pltcl_queries # where to find psql for running the tests PSQLDIR = $(bindir) @@ -49,15 +53,29 @@ ifeq ($(TCL_SHARED_BUILD), 1) all: all-lib $(MAKE) -C modules $@ -install: all installdirs install-lib + +install: all installdirs install-lib install-data $(MAKE) -C modules $@ installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(datadir)/extension' $(MAKE) -C modules $@ -uninstall: uninstall-lib +uninstall: uninstall-lib uninstall-data $(MAKE) -C modules $@ +install-data: + @for file in $(addprefix $(srcdir)/, $(DATA)); do \ + echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'"; \ + $(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/extension'; \ + done + +uninstall-data: + rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA))) + +.PHONY: install-data uninstall-data + + check: submake $(pg_regress_check) $(REGRESS_OPTS) $(REGRESS) diff --git a/src/pl/tcl/pltcl--1.0.sql b/src/pl/tcl/pltcl--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..897e1a1fe92974b57770996b95517eda5ca1cd30 --- /dev/null +++ b/src/pl/tcl/pltcl--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/tcl/pltcl--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE pltcl; diff --git a/src/pl/tcl/pltcl--unpackaged--1.0.sql b/src/pl/tcl/pltcl--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..dfad66c268ba93923db5f38831fcbee60a860db5 --- /dev/null +++ b/src/pl/tcl/pltcl--unpackaged--1.0.sql @@ -0,0 +1,5 @@ +/* src/pl/tcl/pltcl--unpackaged--1.0.sql */ + +ALTER EXTENSION pltcl ADD PROCEDURAL LANGUAGE pltcl; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION pltcl ADD FUNCTION pltcl_call_handler(); diff --git a/src/pl/tcl/pltcl.control b/src/pl/tcl/pltcl.control new file mode 100644 index 0000000000000000000000000000000000000000..b9dc1b8a1381ef9ccbcd6c4989d5aeefb4e8a602 --- /dev/null +++ b/src/pl/tcl/pltcl.control @@ -0,0 +1,7 @@ +# pltcl extension +comment = 'PL/Tcl procedural language' +default_version = '1.0' +module_pathname = '$libdir/pltcl' +relocatable = false +schema = pg_catalog +superuser = false diff --git a/src/pl/tcl/pltclu--1.0.sql b/src/pl/tcl/pltclu--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..e53bb04e6d383e82abb6ae438aac1c16947d1e88 --- /dev/null +++ b/src/pl/tcl/pltclu--1.0.sql @@ -0,0 +1,9 @@ +/* src/pl/tcl/pltclu--1.0.sql */ + +/* + * Currently, all the interesting stuff is done by CREATE LANGUAGE. + * Later we will probably "dumb down" that command and put more of the + * knowledge into this script. + */ + +CREATE PROCEDURAL LANGUAGE pltclu; diff --git a/src/pl/tcl/pltclu--unpackaged--1.0.sql b/src/pl/tcl/pltclu--unpackaged--1.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..a5d359fc047327ae800dff0d793fa485bc4d2442 --- /dev/null +++ b/src/pl/tcl/pltclu--unpackaged--1.0.sql @@ -0,0 +1,5 @@ +/* src/pl/tcl/pltclu--unpackaged--1.0.sql */ + +ALTER EXTENSION pltclu ADD PROCEDURAL LANGUAGE pltclu; +-- ALTER ADD LANGUAGE doesn't pick up the support functions, so we have to. +ALTER EXTENSION pltclu ADD FUNCTION pltclu_call_handler(); diff --git a/src/pl/tcl/pltclu.control b/src/pl/tcl/pltclu.control new file mode 100644 index 0000000000000000000000000000000000000000..1418dc5a9ef1c32270024e8f28c3ca1e897a70b7 --- /dev/null +++ b/src/pl/tcl/pltclu.control @@ -0,0 +1,7 @@ +# pltclu extension +comment = 'PL/TclU untrusted procedural language' +default_version = '1.0' +module_pathname = '$libdir/pltcl' +relocatable = false +schema = pg_catalog +superuser = true diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index a6160298efb4590708085c8c7347b3033fcb08d0..6ecf78488e01943b912f4d4838f28dac11e2a776 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -86,6 +86,7 @@ char *outputdir = "."; char *psqldir = PGBINDIR; char *launcher = NULL; static _stringlist *loadlanguage = NULL; +static _stringlist *loadextension = NULL; static int max_connections = 0; static char *encoding = NULL; static _stringlist *schedulelist = NULL; @@ -1800,6 +1801,16 @@ create_database(const char *dbname) header(_("installing %s"), sl->str); psql_command(dbname, "CREATE OR REPLACE LANGUAGE \"%s\"", sl->str); } + + /* + * Install any requested extensions. We use CREATE IF NOT EXISTS + * so that this will work whether or not the extension is preinstalled. + */ + for (sl = loadextension; sl != NULL; sl = sl->next) + { + header(_("installing %s"), sl->str); + psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str); + } } static void @@ -1862,6 +1873,8 @@ help(void) printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n")); printf(_(" --load-language=lang load the named language before running the\n")); printf(_(" tests; can appear multiple times\n")); + printf(_(" --load-extension=ext load the named extension before running the\n")); + printf(_(" tests; can appear multiple times\n")); printf(_(" --create-role=ROLE create the specified role before testing\n")); printf(_(" --max-connections=N maximum number of concurrent connections\n")); printf(_(" (default is 0 meaning unlimited)\n")); @@ -1925,6 +1938,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc {"temp-config", required_argument, NULL, 19}, {"use-existing", no_argument, NULL, 20}, {"launcher", required_argument, NULL, 21}, + {"load-extension", required_argument, NULL, 22}, {NULL, 0, NULL, 0} }; @@ -2021,6 +2035,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc case 21: launcher = strdup(optarg); break; + case 22: + add_stringlist_item(&loadextension, optarg); + break; default: /* getopt_long already emitted a complaint */ fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"), diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl index f3024f26ca67ce5597f94bd0dfc6c62ded8c87f6..2fe6b8a05bec82a2464ba3e83ce263170a40f17e 100644 --- a/src/tools/msvc/vcregress.pl +++ b/src/tools/msvc/vcregress.pl @@ -146,14 +146,14 @@ sub plcheck my $lang = $pl eq 'tcl' ? 'pltcl' : $pl; next unless -d "../../$Config/$lang"; $lang = 'plpythonu' if $lang eq 'plpython'; - my @lang_args = ("--load-language=$lang"); + my @lang_args = ("--load-extension=$lang"); chdir $pl; my @tests = fetchTests(); if ($lang eq 'plperl') { # run both trusted and untrusted perl tests - push(@lang_args, "--load-language=plperlu"); + push(@lang_args, "--load-extension=plperlu"); # assume we're using this perl to built postgres # test if we can run two interpreters in one backend, and if so