diff options
author | Peter Eisentraut | 2015-04-26 14:33:14 +0000 |
---|---|---|
committer | Peter Eisentraut | 2015-04-26 14:33:14 +0000 |
commit | cac76582053ef8ea07df65fed0757f352da23705 (patch) | |
tree | 6ae01041aa61db9d686638b9d4c3ccd30d7c6487 /contrib/ltree_plpython | |
parent | f320cbb615e0374b18836337713239da58705cf3 (diff) |
Add transforms feature
This provides a mechanism for specifying conversions between SQL data
types and procedural languages. As examples, there are transforms
for hstore and ltree for PL/Perl and PL/Python.
reviews by Pavel Stěhule and Andres Freund
Diffstat (limited to 'contrib/ltree_plpython')
-rw-r--r-- | contrib/ltree_plpython/.gitignore | 6 | ||||
-rw-r--r-- | contrib/ltree_plpython/Makefile | 31 | ||||
-rw-r--r-- | contrib/ltree_plpython/expected/ltree_plpython.out | 45 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython.c | 32 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython2u--1.0.sql | 12 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython2u.control | 6 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython3u--1.0.sql | 12 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython3u.control | 6 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpythonu--1.0.sql | 12 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpythonu.control | 6 | ||||
-rw-r--r-- | contrib/ltree_plpython/sql/ltree_plpython.sql | 37 |
11 files changed, 205 insertions, 0 deletions
diff --git a/contrib/ltree_plpython/.gitignore b/contrib/ltree_plpython/.gitignore new file mode 100644 index 00000000000..ce6fab94a0f --- /dev/null +++ b/contrib/ltree_plpython/.gitignore @@ -0,0 +1,6 @@ +# Generated subdirectories +/expected/python3/ +/log/ +/results/ +/sql/python3/ +/tmp_check/ diff --git a/contrib/ltree_plpython/Makefile b/contrib/ltree_plpython/Makefile new file mode 100644 index 00000000000..c358cfa88b2 --- /dev/null +++ b/contrib/ltree_plpython/Makefile @@ -0,0 +1,31 @@ +# contrib/ltree_plpython/Makefile + +MODULE_big = ltree_plpython$(python_majorversion) +OBJS = ltree_plpython.o + +PG_CPPFLAGS = -I$(top_srcdir)/src/pl/plpython $(python_includespec) -I$(top_srcdir)/contrib/ltree + +EXTENSION = ltree_plpythonu ltree_plpython2u ltree_plpython3u +DATA = ltree_plpythonu--1.0.sql ltree_plpython2u--1.0.sql ltree_plpython3u--1.0.sql + +REGRESS = ltree_plpython +REGRESS_PLPYTHON3_MANGLE := $(REGRESS) + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/ltree_plpython +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +REGRESS_OPTS = --load-extension=ltree +ifeq ($(python_majorversion),2) +REGRESS_OPTS += --load-extension=plpythonu --load-extension=ltree_plpythonu +endif +EXTRA_INSTALL = contrib/ltree + +include $(top_srcdir)/src/pl/plpython/regress-python3-mangle.mk diff --git a/contrib/ltree_plpython/expected/ltree_plpython.out b/contrib/ltree_plpython/expected/ltree_plpython.out new file mode 100644 index 00000000000..934529ee0f5 --- /dev/null +++ b/contrib/ltree_plpython/expected/ltree_plpython.out @@ -0,0 +1,45 @@ +CREATE EXTENSION plpython2u; +CREATE EXTENSION ltree_plpython2u; +CREATE FUNCTION test1(val ltree) RETURNS int +LANGUAGE plpythonu +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; +SELECT test1('aa.bb.cc'::ltree); +INFO: ['aa', 'bb', 'cc'] +CONTEXT: PL/Python function "test1" + test1 +------- + 3 +(1 row) + +CREATE FUNCTION test1n(val ltree) RETURNS int +LANGUAGE plpython2u +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; +SELECT test1n('aa.bb.cc'::ltree); +INFO: ['aa', 'bb', 'cc'] +CONTEXT: PL/Python function "test1n" + test1n +-------- + 3 +(1 row) + +CREATE FUNCTION test2() RETURNS ltree +LANGUAGE plpythonu +TRANSFORM FOR TYPE ltree +AS $$ +return ['foo', 'bar', 'baz'] +$$; +-- plpython to ltree is not yet implemented, so this will fail, +-- because it will try to parse the Python list as an ltree input +-- string. +SELECT test2(); +ERROR: syntax error at position 0 +CONTEXT: while creating return value +PL/Python function "test2" diff --git a/contrib/ltree_plpython/ltree_plpython.c b/contrib/ltree_plpython/ltree_plpython.c new file mode 100644 index 00000000000..111e3e356e5 --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython.c @@ -0,0 +1,32 @@ +#include "postgres.h" +#include "fmgr.h" +#include "plpython.h" +#include "ltree.h" + +PG_MODULE_MAGIC; + + +PG_FUNCTION_INFO_V1(ltree_to_plpython); +Datum ltree_to_plpython(PG_FUNCTION_ARGS); + +Datum +ltree_to_plpython(PG_FUNCTION_ARGS) +{ + ltree *in = PG_GETARG_LTREE(0); + int i; + PyObject *list; + ltree_level *curlevel; + + list = PyList_New(in->numlevel); + + curlevel = LTREE_FIRST(in); + for (i = 0; i < in->numlevel; i++) + { + PyList_SetItem(list, i, PyString_FromStringAndSize(curlevel->name, curlevel->len)); + curlevel = LEVEL_NEXT(curlevel); + } + + PG_FREE_IF_COPY(in, 0); + + return PointerGetDatum(list); +} diff --git a/contrib/ltree_plpython/ltree_plpython2u--1.0.sql b/contrib/ltree_plpython/ltree_plpython2u--1.0.sql new file mode 100644 index 00000000000..29a12d45a28 --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython2u--1.0.sql @@ -0,0 +1,12 @@ +-- make sure the prerequisite libraries are loaded +DO '1' LANGUAGE plpython2u; +SELECT NULL::ltree; + + +CREATE FUNCTION ltree_to_plpython2(val internal) RETURNS internal +LANGUAGE C STRICT IMMUTABLE +AS 'MODULE_PATHNAME', 'ltree_to_plpython'; + +CREATE TRANSFORM FOR ltree LANGUAGE plpython2u ( + FROM SQL WITH FUNCTION ltree_to_plpython2(internal) +); diff --git a/contrib/ltree_plpython/ltree_plpython2u.control b/contrib/ltree_plpython/ltree_plpython2u.control new file mode 100644 index 00000000000..bedfd0acbad --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython2u.control @@ -0,0 +1,6 @@ +# ltree_plpython2u extension +comment = 'transform between ltree and plpython2u' +default_version = '1.0' +module_pathname = '$libdir/ltree_plpython2' +relocatable = true +requires = 'ltree,plpython2u' diff --git a/contrib/ltree_plpython/ltree_plpython3u--1.0.sql b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql new file mode 100644 index 00000000000..1300a78c66f --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql @@ -0,0 +1,12 @@ +-- make sure the prerequisite libraries are loaded +DO '1' LANGUAGE plpython3u; +SELECT NULL::ltree; + + +CREATE FUNCTION ltree_to_plpython3(val internal) RETURNS internal +LANGUAGE C STRICT IMMUTABLE +AS 'MODULE_PATHNAME', 'ltree_to_plpython'; + +CREATE TRANSFORM FOR ltree LANGUAGE plpython3u ( + FROM SQL WITH FUNCTION ltree_to_plpython3(internal) +); diff --git a/contrib/ltree_plpython/ltree_plpython3u.control b/contrib/ltree_plpython/ltree_plpython3u.control new file mode 100644 index 00000000000..96c9764331b --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython3u.control @@ -0,0 +1,6 @@ +# ltree_plpython3u extension +comment = 'transform between ltree and plpython3u' +default_version = '1.0' +module_pathname = '$libdir/ltree_plpython3' +relocatable = true +requires = 'ltree,plpython3u' diff --git a/contrib/ltree_plpython/ltree_plpythonu--1.0.sql b/contrib/ltree_plpython/ltree_plpythonu--1.0.sql new file mode 100644 index 00000000000..1d1af28f4eb --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpythonu--1.0.sql @@ -0,0 +1,12 @@ +-- make sure the prerequisite libraries are loaded +DO '1' LANGUAGE plpythonu; +SELECT NULL::ltree; + + +CREATE FUNCTION ltree_to_plpython(val internal) RETURNS internal +LANGUAGE C STRICT IMMUTABLE +AS 'MODULE_PATHNAME'; + +CREATE TRANSFORM FOR ltree LANGUAGE plpythonu ( + FROM SQL WITH FUNCTION ltree_to_plpython(internal) +); diff --git a/contrib/ltree_plpython/ltree_plpythonu.control b/contrib/ltree_plpython/ltree_plpythonu.control new file mode 100644 index 00000000000..b03c89a2e6e --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpythonu.control @@ -0,0 +1,6 @@ +# ltree_plpythonu extension +comment = 'transform between ltree and plpythonu' +default_version = '1.0' +module_pathname = '$libdir/ltree_plpython2' +relocatable = true +requires = 'ltree,plpythonu' diff --git a/contrib/ltree_plpython/sql/ltree_plpython.sql b/contrib/ltree_plpython/sql/ltree_plpython.sql new file mode 100644 index 00000000000..f08ff6a3f06 --- /dev/null +++ b/contrib/ltree_plpython/sql/ltree_plpython.sql @@ -0,0 +1,37 @@ +CREATE EXTENSION plpython2u; +CREATE EXTENSION ltree_plpython2u; + + +CREATE FUNCTION test1(val ltree) RETURNS int +LANGUAGE plpythonu +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; + +SELECT test1('aa.bb.cc'::ltree); + + +CREATE FUNCTION test1n(val ltree) RETURNS int +LANGUAGE plpython2u +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; + +SELECT test1n('aa.bb.cc'::ltree); + + +CREATE FUNCTION test2() RETURNS ltree +LANGUAGE plpythonu +TRANSFORM FOR TYPE ltree +AS $$ +return ['foo', 'bar', 'baz'] +$$; + +-- plpython to ltree is not yet implemented, so this will fail, +-- because it will try to parse the Python list as an ltree input +-- string. +SELECT test2(); |