From 63b656b7bf39beb5b6095ab2b5e1e4e9d8c6a965 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 4 Mar 2011 21:51:14 -0500 Subject: [PATCH] Create extension infrastructure for the core procedural languages. This mostly just involves creating control, install, and update-from-unpackaged scripts for them. However, I had to adjust plperl and plpython to not share the same support functions between variants, because we can't put the same function into multiple extensions. catversion bump forced due to new contents of pg_pltemplate, and because initdb now installs plpgsql as an extension not a bare language. Add support for regression testing these as extensions not bare languages. Fix a couple of other issues that popped up while testing this: my initial hack at pg_dump binary-upgrade support didn't work right, and we don't want an extra schema permissions test after all. Documentation changes still to come, but I'm committing now to see whether the MSVC build scripts need work (likely they do). --- src/backend/commands/extension.c | 13 +++--- src/bin/initdb/initdb.c | 2 +- src/bin/pg_dump/pg_dump.c | 44 +++++++++++++------ src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_pltemplate.h | 4 +- src/pl/plperl/GNUmakefile | 23 ++++++++-- src/pl/plperl/plperl--1.0.sql | 9 ++++ src/pl/plperl/plperl--unpackaged--1.0.sql | 7 +++ src/pl/plperl/plperl.c | 36 +++++++++++++++ src/pl/plperl/plperl.control | 7 +++ src/pl/plperl/plperlu--1.0.sql | 9 ++++ src/pl/plperl/plperlu--unpackaged--1.0.sql | 7 +++ src/pl/plperl/plperlu.control | 7 +++ src/pl/plpgsql/src/Makefile | 20 +++++++-- src/pl/plpgsql/src/plpgsql--1.0.sql | 9 ++++ .../plpgsql/src/plpgsql--unpackaged--1.0.sql | 7 +++ src/pl/plpgsql/src/plpgsql.control | 7 +++ src/pl/plpython/Makefile | 27 ++++++++++-- src/pl/plpython/expected/plpython_drop.out | 3 +- src/pl/plpython/expected/plpython_test.out | 2 +- src/pl/plpython/plpython.c | 33 ++++++++++++++ src/pl/plpython/plpython2u--1.0.sql | 9 ++++ .../plpython/plpython2u--unpackaged--1.0.sql | 7 +++ src/pl/plpython/plpython2u.control | 7 +++ src/pl/plpython/plpython3u--1.0.sql | 9 ++++ .../plpython/plpython3u--unpackaged--1.0.sql | 7 +++ src/pl/plpython/plpython3u.control | 7 +++ src/pl/plpython/plpythonu--1.0.sql | 9 ++++ .../plpython/plpythonu--unpackaged--1.0.sql | 7 +++ src/pl/plpython/plpythonu.control | 7 +++ src/pl/plpython/sql/plpython_drop.sql | 4 +- src/pl/plpython/sql/plpython_test.sql | 2 +- src/pl/tcl/Makefile | 26 +++++++++-- src/pl/tcl/pltcl--1.0.sql | 9 ++++ src/pl/tcl/pltcl--unpackaged--1.0.sql | 5 +++ src/pl/tcl/pltcl.control | 7 +++ src/pl/tcl/pltclu--1.0.sql | 9 ++++ src/pl/tcl/pltclu--unpackaged--1.0.sql | 5 +++ src/pl/tcl/pltclu.control | 7 +++ src/test/regress/pg_regress.c | 17 +++++++ src/tools/msvc/vcregress.pl | 4 +- 41 files changed, 399 insertions(+), 43 deletions(-) create mode 100644 src/pl/plperl/plperl--1.0.sql create mode 100644 src/pl/plperl/plperl--unpackaged--1.0.sql create mode 100644 src/pl/plperl/plperl.control create mode 100644 src/pl/plperl/plperlu--1.0.sql create mode 100644 src/pl/plperl/plperlu--unpackaged--1.0.sql create mode 100644 src/pl/plperl/plperlu.control create mode 100644 src/pl/plpgsql/src/plpgsql--1.0.sql create mode 100644 src/pl/plpgsql/src/plpgsql--unpackaged--1.0.sql create mode 100644 src/pl/plpgsql/src/plpgsql.control create mode 100644 src/pl/plpython/plpython2u--1.0.sql create mode 100644 src/pl/plpython/plpython2u--unpackaged--1.0.sql create mode 100644 src/pl/plpython/plpython2u.control create mode 100644 src/pl/plpython/plpython3u--1.0.sql create mode 100644 src/pl/plpython/plpython3u--unpackaged--1.0.sql create mode 100644 src/pl/plpython/plpython3u.control create mode 100644 src/pl/plpython/plpythonu--1.0.sql create mode 100644 src/pl/plpython/plpythonu--unpackaged--1.0.sql create mode 100644 src/pl/plpython/plpythonu.control create mode 100644 src/pl/tcl/pltcl--1.0.sql create mode 100644 src/pl/tcl/pltcl--unpackaged--1.0.sql create mode 100644 src/pl/tcl/pltcl.control create mode 100644 src/pl/tcl/pltclu--1.0.sql create mode 100644 src/pl/tcl/pltclu--unpackaged--1.0.sql create mode 100644 src/pl/tcl/pltclu.control diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 6ff30ddc0a..b1673e6549 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 98915c4b89..ce24d6101d 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 ea1818b1d5..dfbdcadd14 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 fe7ccf4ba0..56fb4931ba 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 c0578f92c0..fa086525e7 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 e86cb84dba..71e2cef4c5 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 0000000000..befd882745 --- /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 0000000000..b062bd5d9b --- /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 72e1e5106a..9a94b3f085 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 0000000000..6faace12fa --- /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 0000000000..025f7957c4 --- /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 0000000000..bc62d36a3d --- /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 0000000000..69473caed4 --- /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 a5f161dc62..d748ef6826 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: 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 # 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 0000000000..514562d70f --- /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 0000000000..9de7e8392a --- /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 0000000000..b320227b12 --- /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 e6b6ed3ca5..46e0195142 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 fef642f7c0..a0e3b5c4ef 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 7b2e1703f4..c2358b452d 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 75f7b5cf57..e415aa36f4 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 0000000000..0e47876502 --- /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 0000000000..a89d8b4d09 --- /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 0000000000..39c2b791ef --- /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 0000000000..d5c6e5ab96 --- /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 0000000000..b1c0d03a30 --- /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 0000000000..01905ef398 --- /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 0000000000..beb0aa1645 --- /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 0000000000..7926233250 --- /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 0000000000..ae91b1c255 --- /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 319d5e0925..72d5d657ec 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 915189847a..c8d5ef5f53 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 b29478dd6f..c7797c61f5 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 0000000000..897e1a1fe9 --- /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 0000000000..dfad66c268 --- /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 0000000000..b9dc1b8a13 --- /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 0000000000..e53bb04e6d --- /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 0000000000..a5d359fc04 --- /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 0000000000..1418dc5a9e --- /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 a6160298ef..6ecf78488e 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 f3024f26ca..2fe6b8a05b 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