postgresql extension API proof of concept
Dear hackers,
after some comments and discussions, here is a proof-of-concept
demonstration of a postgresql extension infrastructure.
(1) apply the patch...
(2) ********** REGENERATE CONFIGURE ************
sh> autoconf configure.in > configure
sh> chmod +x configure
(3) configure, compile, install and use postgresql:
sh> configure --prefix=/tmp/pg
sh> make
sh> make install
where is our postgresql installation...
sh> PATH=/tmp/pg/bin:$PATH
(5) build an extension with the new infrastructure, for instance
with some contrib that define a new type.
sh> cd contrib/isbn_issn
sh> mv Makefile Makefile.old
now create an appropriate extension Makefile (well, this should
have been done by the person who provides the extension)
sh> cat > Makefile
PGXSDIR := $(shell pg_config --pgxsdir)
include $(PGXSDIR)/pgxs_begin.mk
MODULES = isbn_issn
DATA_built = isbn_issn.sql
DOCS = README.isbn_issn
include $(PGXSDIR)/pgxs_end.mk
(6) now enjoy:
sh> make
sh> make install
sh> make clean
sh> make uninstall
There is a sample extension makefile in $(pg_config --pgxsdir)/Makefile.pgxs
No real documentation yet, maybe hidden bugs...
Thanks in advance for your comments.
--
Fabien Coelho - coelho@cri.ensmp.fr
Attachments:
install_build.patchtext/plain; charset=US-ASCII; name=install_build.patchDownload
*** ./GNUmakefile.in.orig Tue Apr 20 09:35:41 2004
--- ./GNUmakefile.in Wed May 19 14:17:28 2004
***************
*** 13,30 ****
$(MAKE) -C src all
@echo "All of PostgreSQL successfully made. Ready to install."
! install:
$(MAKE) -C doc install
$(MAKE) -C src install
- @echo "PostgreSQL installation complete."
installdirs uninstall distprep:
$(MAKE) -C doc $@
$(MAKE) -C src $@
install-all-headers:
$(MAKE) -C src $@
# clean, distclean, etc should apply to contrib too, even though
# it's not built by default
clean:
--- 13,51 ----
$(MAKE) -C src all
@echo "All of PostgreSQL successfully made. Ready to install."
! install: light-install install-all-headers install-config-files
! @echo "PostgreSQL installation complete."
!
! light-install:
$(MAKE) -C doc install
$(MAKE) -C src install
installdirs uninstall distprep:
$(MAKE) -C doc $@
$(MAKE) -C src $@
+ uninstall:
+ $(RM) $(DESTDIR)$(insbuilddir)/* $(DESTDIR)$(insbuilddir)/config/*
+
install-all-headers:
$(MAKE) -C src $@
+ install-config-files: installdirs
+ $(MAKE) -C src $@
+ $(INSTALL_DATA) config.status $(DESTDIR)$(insbuilddir)
+ $(INSTALL_DATA) config/install-sh $(DESTDIR)$(insbuilddir)/config
+ $(INSTALL_DATA) config/mkinstalldirs $(DESTDIR)$(insbuilddir)/config
+
+ installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(insbuilddir)
+ $(mkinstalldirs) $(DESTDIR)$(insbuilddir)/config
+
+ install-client-only:
+ $(MAKE) -C src/bin install
+ $(MAKE) -C src/include install
+ $(MAKE) -C src/interfaces install
+ $(MAKE) -C doc install
+
# clean, distclean, etc should apply to contrib too, even though
# it's not built by default
clean:
*** ./configure.in.orig Wed May 19 11:51:46 2004
--- ./configure.in Wed May 19 14:17:28 2004
***************
*** 128,133 ****
--- 128,144 ----
#
+ # Installation directory for build utilities
+ #
+ PGAC_ARG(with, insbuilddir,
+ [ --with-insbuilddir=DIR install build utilities in DIR [[LIBDIR/build]]],
+ [AC_MSG_ERROR([option --with-insbuilddir requires an argument])],
+ [AC_MSG_ERROR([option --without-insbuilddir does not apply])],
+ [insbuilddir=$withval],
+ [insbuilddir='${libdir}/build'])
+ AC_SUBST(insbuilddir)
+
+ #
# Add non-standard directories to the library search path
#
PGAC_ARG_REQ(with, libraries, [ --with-libraries=DIRS look for additional libraries in DIRS],
*** ./doc/src/sgml/installation.sgml.orig Wed May 19 11:51:47 2004
--- ./doc/src/sgml/installation.sgml Wed May 19 14:17:28 2004
***************
*** 595,600 ****
--- 595,612 ----
</varlistentry>
<varlistentry>
+ <term><option>--with-insbuilddir=<replaceable>DIRECTORY</replaceable></option></term>
+ <listitem>
+ <para>
+ Useful files for building <productname>PostgreSQL</productname>
+ extensions, such as makefiles or scripts, will be installed in this
+ directory.
+ The default is <filename><replaceable>LIBDIR</replaceable>/build</filename>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--with-docdir=<replaceable>DIRECTORY</></option></term>
<term><option>--without-docdir</option></term>
<listitem>
***************
*** 1041,1070 ****
</para>
<para>
! The standard installation provides only the header files needed for client
! application development. If you plan to do any server-side program
! development (such as custom functions or data types written in C),
! then you may want to install the entire <productname>PostgreSQL</>
! include tree into your target include directory. To do that, enter
<screen>
! <userinput>gmake install-all-headers</userinput>
</screen>
! This adds a megabyte or two to the installation footprint, and is only
! useful if you don't plan to keep the whole source tree around for
! reference. (If you do, you can just use the source's include
! directory when building server-side software.)
</para>
<formalpara>
<title>Client-only installation:</title>
<para>
If you want to install only the client applications and
! interface libraries, then you can use these commands:
<screen>
! <userinput>gmake -C src/bin install</>
! <userinput>gmake -C src/include install</>
! <userinput>gmake -C src/interfaces install</>
! <userinput>gmake -C doc install</>
</screen>
</para>
</formalpara>
--- 1053,1079 ----
</para>
<para>
! The standard installation provides all the header files needed for client
! application development, as well as headers for server-side program
! development such as custom functions or data types written in C.
! If you do not want to install the entire <productname>PostgreSQL</>
! include tree into your target include directory. Enter
<screen>
! <userinput>gmake light-install</userinput>
</screen>
! rather than the <literal>install</literal> target.
! This reduce by two megabytes the installation footprint, at the price
! of having to recover the whole source tree if you need
! to add extensions such as new data types or custom functions.
</para>
<formalpara>
<title>Client-only installation:</title>
<para>
If you want to install only the client applications and
! interface libraries, then you can use these command:
<screen>
! <userinput>gmake install-client-only</>
</screen>
</para>
</formalpara>
*** ./src/Makefile.global.in.orig Mon May 17 14:00:06 2004
--- ./src/Makefile.global.in Wed May 19 15:45:23 2004
***************
*** 113,118 ****
--- 113,119 ----
localedir := @localedir@
+ insbuilddir := @insbuilddir@
##########################################################################
#
***************
*** 165,171 ****
--- 166,178 ----
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+
+ ifndef PGXS
override CPPFLAGS := -I$(top_srcdir)/src/include $(CPPFLAGS)
+ else
+ override CPPFLAGS := -I$(includedir_server) $(CPPFLAGS)
+ endif
+
ifdef VPATH
override CPPFLAGS := -I$(top_builddir)/src/include $(CPPFLAGS)
endif
***************
*** 365,370 ****
--- 372,380 ----
%.bz2: %
$(BZIP2) -f $<
+
+ ifndef PGXS
+
# Remake Makefile.global from Makefile.global.in if the latter
# changed. In order to trigger this rule, the including file must
# write `include $(top_builddir)/src/Makefile.global', not some
***************
*** 392,397 ****
--- 402,408 ----
$(top_builddir)/config.status: $(top_srcdir)/configure
cd $(top_builddir) && ./config.status --recheck
+ endif
install-strip:
@$(MAKE) INSTALL_PROGRAM_ENV="STRIPPROG='$(STRIP)'" \
*** ./src/Makefile.orig Fri Apr 30 17:18:16 2004
--- ./src/Makefile Wed May 19 15:58:16 2004
***************
*** 26,31 ****
--- 26,49 ----
install-all-headers:
$(MAKE) -C include $@
+ install-config-files: installdirs
+ $(MAKE) -C utils $@
+ $(MAKE) -C makefiles $@
+ for f in Makefile.global Makefile.port Makefile.shlib nls-global.mk \
+ makefiles/Makefile.pgxs ; \
+ do \
+ $(INSTALL_DATA) $$f $(DESTDIR)$(insbuilddir)/src ; \
+ done
+
+ uninstall:
+ $(MAKE) -C utils $@
+ $(MAKE) -C makefiles $@
+ $(RM) $(DESTDIR)$(insbuilddir)/* $(DESTDIR)$(insbuilddir)/src/*
+
+ installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(insbuilddir)
+ $(mkinstalldirs) $(DESTDIR)$(insbuilddir)/src
+
clean:
$(MAKE) -C port $@
$(MAKE) -C timezone $@
*** ./src/bin/pg_config/Makefile.orig Sat Nov 29 20:52:04 2003
--- ./src/bin/pg_config/Makefile Wed May 19 14:17:28 2004
***************
*** 14,19 ****
--- 14,20 ----
-e 's,@pkglibdir@,$(pkglibdir),g' \
-e "s|@configure@|$(configure_args)|g" \
-e 's,@version@,$(VERSION),g' \
+ -e 's,@insbuilddir@,$(insbuilddir),g' \
$< >$@
chmod a+x $@
*** ./src/bin/pg_config/pg_config.sh.orig Sat Nov 29 20:52:04 2003
--- ./src/bin/pg_config/pg_config.sh Wed May 19 15:51:38 2004
***************
*** 19,24 ****
--- 19,25 ----
val_pkglibdir='@pkglibdir@'
val_configure="@configure@"
val_version='@version@'
+ val_insbuilddir='@insbuilddir@'
help="\
$me provides information about the installed version of PostgreSQL.
***************
*** 35,40 ****
--- 36,43 ----
--pkglibdir show location of dynamically loadable modules
--configure show options given to 'configure' script when
PostgreSQL was built
+ --insbuilddir show location of files for building extensions
+ --pgxsdir show location of extension directory
--version show the PostgreSQL version, then exit
--help show this help, then exit
***************
*** 61,66 ****
--- 64,71 ----
--libdir) show="$show \$val_libdir";;
--pkglibdir) show="$show \$val_pkglibdir";;
--configure) show="$show \$val_configure";;
+ --insbuilddir) show="$show \$val_insbuilddir";;
+ --pgxsdir) show="$show \$val_insbuilddir/src/makefiles";;
--version) echo "PostgreSQL $val_version"
exit 0;;
*** ./src/makefiles/Makefile.orig Wed May 19 14:46:17 2004
--- ./src/makefiles/Makefile Wed May 19 15:56:44 2004
***************
*** 0 ****
--- 1,16 ----
+ # Makefile for src/makefiles
+
+ subdir = src/makefiles
+ top_builddir = ../..
+ include $(top_builddir)/src/Makefile.global
+
+ install-config-files: installdirs
+ for f in Makefile.* *.mk ; do \
+ $(INSTALL_DATA) $$f $(DESTDIR)$(insbuilddir)/$(subdir) ; \
+ done
+
+ installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(insbuilddir)/$(subdir)
+
+ uninstall:
+ $(RM) $(DESTDIR)$(insbuilddir)/$(subdir)/*
*** ./src/makefiles/Makefile.pgxs.orig Wed May 19 15:55:56 2004
--- ./src/makefiles/Makefile.pgxs Wed May 19 15:59:57 2004
***************
*** 0 ****
--- 1,11 ----
+ # PGXS: PostgreSQL eXtensionS template makefile
+
+ PGXSDIR := $(shell pg_config --pgxsdir)
+ include $(PGXSDIR)/pgxs_begin.mk
+
+ # just like contrib, to be documented...
+ #MODULES = isbn_issn
+ #DATA_built = isbn_issn.sql
+ #DOCS = README.isbn_issn
+
+ include $(PGXSDIR)/pgxs_end.mk
*** ./src/makefiles/pgxs_begin.mk.orig Wed May 19 14:19:21 2004
--- ./src/makefiles/pgxs_begin.mk Wed May 19 15:28:58 2004
***************
*** 0 ****
--- 1,27 ----
+ # $PostgreSQL$
+ #
+ # PGXS: PostGreSQL eXtensionS initial directory
+ #
+
+ ifndef PGXSDIR
+ $(error pgxs error: PGXSDIR makefile macro must be set)
+ endif
+
+ ifdef PGXS
+ $(error pgxs error: PGXS makefile macro must not be set)
+ endif
+
+ # now we're cleanly in pgxs
+ PGXS = 1
+
+ # we assume that we are in ./src/makefiles, so top is:
+ top_builddir := $(PGXSDIR)/../..
+
+ # now we assume we're in the main tree.
+ include $(top_builddir)/src/Makefile.global
+
+ # issue: what about includes?
+ # are extensions to find includes where they reside in the source
+ # tree, or as they are installed? contrib find them in the source
+ # tree...
+
*** ./src/makefiles/pgxs_end.mk.orig Wed May 19 14:33:51 2004
--- ./src/makefiles/pgxs_end.mk Wed May 19 14:33:40 2004
***************
*** 0 ****
--- 1,220 ----
+ # $PostgreSQL$
+ #
+ # This file contains generic rules to build many kinds of simple
+ # contrib modules. You only need to set a few variables and include
+ # this file, the rest will be done here.
+ #
+ # MODULES -- list of shared objects to be build from source file with
+ # same stem (do not include suffix in this list)
+ # DATA -- random files to install into $PREFIX/share/contrib
+ # DATA_built -- random files to install into $PREFIX/share/contrib,
+ # which need to be built first
+ # DOCS -- random files to install under $PREFIX/doc/contrib
+ # SCRIPTS -- script files (not binaries) to install into $PREFIX/bin
+ # SCRIPTS_built -- script files (not binaries) to install into $PREFIX/bin,
+ # which need to be built first
+ # REGRESS -- list of regression test cases (without suffix)
+ #
+ # or at most one of these two:
+ #
+ # PROGRAM -- a binary program to build (list objects files in OBJS)
+ # MODULE_big -- a shared object to build (list object files in OBJS)
+ #
+ # The following can also be set:
+ #
+ # EXTRA_CLEAN -- extra files to remove in 'make clean'
+ # PG_CPPFLAGS -- will be added to CPPFLAGS
+ # PG_LIBS -- will be added to PROGRAM link line
+ # SHLIB_LINK -- will be added to MODULE_big link line
+ #
+ # Better look at some of the existing uses for examples...
+
+ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
+
+ ifdef MODULES
+ override CFLAGS += $(CFLAGS_SL)
+ SHLIB_LINK += $(BE_DLLLIBS)
+ endif
+
+ ifdef PG_CPPFLAGS
+ override CPPFLAGS := $(PG_CPPFLAGS) $(CPPFLAGS)
+ endif
+
+ all: $(PROGRAM) $(DATA_built) $(SCRIPTS_built) $(addsuffix $(DLSUFFIX), $(MODULES))
+
+ ifdef MODULE_big
+ # shared library parameters
+ NAME = $(MODULE_big)
+ SO_MAJOR_VERSION= 0
+ SO_MINOR_VERSION= 0
+ rpath =
+
+ SHLIB_LINK += $(BE_DLLLIBS)
+
+ include $(top_srcdir)/src/Makefile.shlib
+
+ all: all-lib
+ endif # MODULE_big
+
+
+ install: all installdirs
+ ifneq (,$(DATA)$(DATA_built))
+ @for file in $(addprefix $(srcdir)/, $(DATA)) $(DATA_built); do \
+ echo "$(INSTALL_DATA) $$file $(DESTDIR)$(datadir)/contrib"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(datadir)/contrib; \
+ done
+ endif # DATA
+ ifdef MODULES
+ @for file in $(addsuffix $(DLSUFFIX), $(MODULES)); do \
+ echo "$(INSTALL_SHLIB) $$file $(DESTDIR)$(pkglibdir)"; \
+ $(INSTALL_SHLIB) $$file $(DESTDIR)$(pkglibdir); \
+ done
+ endif # MODULES
+ ifdef DOCS
+ @for file in $(addprefix $(srcdir)/, $(DOCS)); do \
+ echo "$(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/contrib"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/contrib; \
+ done
+ endif # DOCS
+ ifdef PROGRAM
+ $(INSTALL_PROGRAM) $(PROGRAM)$(X) $(DESTDIR)$(bindir)
+ endif # PROGRAM
+ ifdef MODULE_big
+ $(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(pkglibdir)/$(MODULE_big)$(DLSUFFIX)
+ endif # MODULE_big
+ ifdef SCRIPTS
+ @for file in $(addprefix $(srcdir)/, $(SCRIPTS)); do \
+ echo "$(INSTALL_SCRIPT) $$file $(DESTDIR)$(bindir)"; \
+ $(INSTALL_SCRIPT) $$file $(DESTDIR)$(bindir); \
+ done
+ endif # SCRIPTS
+ ifdef SCRIPTS_built
+ @for file in $(SCRIPTS_built); do \
+ echo "$(INSTALL_SCRIPT) $$file $(DESTDIR)$(bindir)"; \
+ $(INSTALL_SCRIPT) $$file $(DESTDIR)$(bindir); \
+ done
+ endif # SCRIPTS_built
+
+
+ installdirs:
+ ifneq (,$(DATA)$(DATA_built))
+ $(mkinstalldirs) $(DESTDIR)$(datadir)/contrib
+ endif
+ ifneq (,$(MODULES)$(MODULE_big))
+ $(mkinstalldirs) $(DESTDIR)$(pkglibdir)
+ endif
+ ifdef DOCS
+ $(mkinstalldirs) $(DESTDIR)$(docdir)/contrib
+ endif
+ ifneq (,$(PROGRAM)$(SCRIPTS)$(SCRIPTS_built))
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ endif
+
+
+ uninstall:
+ ifneq (,$(DATA)$(DATA_built))
+ rm -f $(addprefix $(DESTDIR)$(datadir)/contrib/, $(notdir $(DATA) $(DATA_built)))
+ endif
+ ifdef MODULES
+ rm -f $(addprefix $(DESTDIR)$(pkglibdir)/, $(addsuffix $(DLSUFFIX), $(MODULES)))
+ endif
+ ifdef DOCS
+ rm -f $(addprefix $(DESTDIR)$(docdir)/contrib/, $(DOCS))
+ endif
+ ifdef PROGRAM
+ rm -f $(DESTDIR)$(bindir)/$(PROGRAM)$(X)
+ endif
+ ifdef MODULE_big
+ rm -f $(DESTDIR)$(pkglibdir)/$(MODULE_big)$(DLSUFFIX)
+ endif
+ ifdef SCRIPTS
+ rm -f $(addprefix $(DESTDIR)$(bindir)/, $(SCRIPTS))
+ endif
+ ifdef SCRIPTS_built
+ rm -f $(addprefix $(DESTDIR)$(bindir)/, $(SCRIPTS_built))
+ endif
+
+
+ clean:
+ ifdef MODULES
+ rm -f $(addsuffix $(DLSUFFIX), $(MODULES)) $(addsuffix .o, $(MODULES))
+ endif
+ ifdef DATA_built
+ rm -f $(DATA_built)
+ endif
+ ifdef SCRIPTS_built
+ rm -f $(SCRIPTS_built)
+ endif
+ ifdef PROGRAM
+ rm -f $(PROGRAM)$(X)
+ endif
+ ifdef OBJS
+ rm -f $(OBJS)
+ endif
+ ifdef EXTRA_CLEAN
+ rm -f $(EXTRA_CLEAN)
+ endif
+ ifdef REGRESS
+ # things created by various check targets
+ rm -rf results tmp_check log
+ rm -f regression.diffs regression.out regress.out run_check.out
+ ifeq ($(PORTNAME), win)
+ rm -f regress.def
+ endif
+ endif # REGRESS
+
+ ifdef MODULE_big
+ clean: clean-lib
+ endif
+
+ distclean maintainer-clean: clean
+
+
+ ifdef REGRESS
+
+ # When doing a VPATH build, must copy over the test .sql and .out
+ # files so that the driver script can find them. We have to use an
+ # absolute path for the targets, because otherwise make will try to
+ # locate the missing files using VPATH, and will find them in
+ # $(srcdir), but the point here is that we want to copy them from
+ # $(srcdir) to the build directory.
+
+ ifdef VPATH
+ abs_builddir := $(shell pwd)
+ test_files_src := $(wildcard $(srcdir)/sql/*.sql) $(wildcard $(srcdir)/expected/*.out) $(wildcard $(srcdir)/data/*.data)
+ test_files_build := $(patsubst $(srcdir)/%, $(abs_builddir)/%, $(test_files_src))
+
+ all: $(test_files_build)
+ $(test_files_build): $(abs_builddir)/%: $(srcdir)/%
+ ln -s $< $@
+ endif # VPATH
+
+ .PHONY: submake
+ submake:
+ $(MAKE) -C $(top_builddir)/src/test/regress pg_regress
+
+ # against installed postmaster
+ installcheck: submake
+ $(top_builddir)/src/test/regress/pg_regress $(REGRESS)
+
+ # in-tree test doesn't work yet (no way to install my shared library)
+ #check: all submake
+ # $(top_builddir)/src/test/regress/pg_regress --temp-install \
+ # --top-builddir=$(top_builddir) $(REGRESS)
+ check:
+ @echo "'make check' is not supported."
+ @echo "Do 'make install', then 'make installcheck' instead."
+ endif # REGRESS
+
+
+ # STANDARD RULES
+
+ ifneq (,$(MODULES)$(MODULE_big))
+ %.sql: %.sql.in
+ sed 's,MODULE_PATHNAME,$$libdir/$*,g' $< >$@
+ endif
+
+ ifdef PROGRAM
+ $(PROGRAM): $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) $(PG_LIBS) $(LDFLAGS) $(LIBS) -o $@
+ endif
*** ./src/utils/Makefile.orig Sat Nov 29 20:52:15 2003
--- ./src/utils/Makefile Wed May 19 14:17:28 2004
***************
*** 16,18 ****
--- 16,24 ----
clean distclean maintainer-clean:
rm -f dllinit.o
+
+ uninstall:
+ $(RM) $(DESTDIR)$(insbuilddir)/dllinit.o
+
+ install-config-files:
+ -[ -f dllinit.o ] && $(INSTALL_DATA) dllinit.o $(DESTDIR)$(insbuilddir)
Dear Carl,
What is the purpose of the extension api in simple terms; what is it FOR?
What does it DO?
Thanks for this perfectly legitimate question, as my mail was not very
easy to understand without the context.
The aim is to provide a compilation infrastructure to external modules
(that is things that are not distributed with the core of postgresql but
must be integrated to it, such as new types or new functions which deal
with backend informations).
The idea is that any external module could have a very simple makefile and
reuse all of postgresql build infrastructure (makefiles, scripts...) to
be build against an already installed postgresql.
I hope this is clearer,
have a nice day,
--
Fabien Coelho - coelho@cri.ensmp.fr
Import Notes
Reply to msg id not found: 001501c43ddeb2ab20906600a8c0@DEVSONYReference msg id not found: 001501c43ddeb2ab20906600a8c0@DEVSONY | Resolved by subject fallback