diff options
Diffstat (limited to 'contrib/ltree_plpython')
-rw-r--r-- | contrib/ltree_plpython/.gitignore | 4 | ||||
-rw-r--r-- | contrib/ltree_plpython/Makefile | 39 | ||||
-rw-r--r-- | contrib/ltree_plpython/expected/ltree_plpython.out | 43 | ||||
-rw-r--r-- | contrib/ltree_plpython/ltree_plpython.c | 58 | ||||
-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/meson.build | 45 | ||||
-rw-r--r-- | contrib/ltree_plpython/sql/ltree_plpython.sql | 36 |
8 files changed, 243 insertions, 0 deletions
diff --git a/contrib/ltree_plpython/.gitignore b/contrib/ltree_plpython/.gitignore new file mode 100644 index 0000000..5dcb3ff --- /dev/null +++ b/contrib/ltree_plpython/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/ltree_plpython/Makefile b/contrib/ltree_plpython/Makefile new file mode 100644 index 0000000..406d278 --- /dev/null +++ b/contrib/ltree_plpython/Makefile @@ -0,0 +1,39 @@ +# contrib/ltree_plpython/Makefile + +MODULE_big = ltree_plpython$(python_majorversion) +OBJS = \ + $(WIN32RES) \ + ltree_plpython.o +PGFILEDESC = "ltree_plpython - ltree transform for plpython" + +EXTENSION = ltree_plpython3u +DATA = ltree_plpython3u--1.0.sql + +REGRESS = ltree_plpython + +PG_CPPFLAGS = $(python_includespec) -DPLPYTHON_LIBNAME='"plpython$(python_majorversion)"' + +ifdef USE_PGXS +PG_CPPFLAGS += -I$(includedir_server)/extension +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +PG_CPPFLAGS += -I$(top_srcdir)/src/pl/plpython -I$(top_srcdir)/contrib +subdir = contrib/ltree_plpython +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +# We must link libpython explicitly +ifeq ($(PORTNAME), win32) +# ... see silliness in plpython Makefile ... +SHLIB_LINK_INTERNAL += $(sort $(wildcard ../../src/pl/plpython/libpython*.a)) +else +rpathdir = $(python_libdir) +SHLIB_LINK += $(python_libspec) $(python_additional_libs) +endif + +REGRESS_OPTS += --load-extension=ltree +EXTRA_INSTALL += contrib/ltree diff --git a/contrib/ltree_plpython/expected/ltree_plpython.out b/contrib/ltree_plpython/expected/ltree_plpython.out new file mode 100644 index 0000000..bd32541 --- /dev/null +++ b/contrib/ltree_plpython/expected/ltree_plpython.out @@ -0,0 +1,43 @@ +CREATE EXTENSION ltree_plpython3u CASCADE; +NOTICE: installing required extension "plpython3u" +CREATE FUNCTION test1(val ltree) RETURNS int +LANGUAGE plpython3u +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; +SELECT test1('aa.bb.cc'::ltree); +INFO: ['aa', 'bb', 'cc'] + test1 +------- + 3 +(1 row) + +CREATE FUNCTION test1n(val ltree) RETURNS int +LANGUAGE plpython3u +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; +SELECT test1n('aa.bb.cc'::ltree); +INFO: ['aa', 'bb', 'cc'] + test1n +-------- + 3 +(1 row) + +CREATE FUNCTION test2() RETURNS ltree +LANGUAGE plpython3u +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: ltree syntax error at character 1 +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 0000000..ac159ea --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython.c @@ -0,0 +1,58 @@ +#include "postgres.h" + +#include "fmgr.h" +#include "ltree/ltree.h" +#include "plpython.h" + +PG_MODULE_MAGIC; + +/* Linkage to functions in plpython module */ +typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size); +static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p; + + +/* + * Module initialize function: fetch function pointers for cross-module calls. + */ +void +_PG_init(void) +{ + /* Asserts verify that typedefs above match original declarations */ + AssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t); + PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t) + load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize", + true, NULL); +} + + +/* These defines must be after the module init function */ +#define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p + + +PG_FUNCTION_INFO_V1(ltree_to_plpython); + +Datum +ltree_to_plpython(PG_FUNCTION_ARGS) +{ + ltree *in = PG_GETARG_LTREE_P(0); + int i; + PyObject *list; + ltree_level *curlevel; + + list = PyList_New(in->numlevel); + if (!list) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + curlevel = LTREE_FIRST(in); + for (i = 0; i < in->numlevel; i++) + { + PyList_SetItem(list, i, PLyUnicode_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_plpython3u--1.0.sql b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql new file mode 100644 index 0000000..09ada3c --- /dev/null +++ b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql @@ -0,0 +1,12 @@ +/* contrib/ltree_plpython/ltree_plpython3u--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION ltree_plpython3u" to load this file. \quit + +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 0000000..96c9764 --- /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/meson.build b/contrib/ltree_plpython/meson.build new file mode 100644 index 0000000..d6c1a25 --- /dev/null +++ b/contrib/ltree_plpython/meson.build @@ -0,0 +1,45 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +if not python3_dep.found() + subdir_done() +endif + +ltree_plpython_sources = files( + 'ltree_plpython.c', +) + +if host_system == 'windows' + ltree_plpython_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'ltree_plpython3', + '--FILEDESC', 'ltree_plpython - ltree transform for plpython',]) +endif + +ltree_plpython = shared_module('ltree_plpython3', + ltree_plpython_sources, + include_directories: [plpython_inc, ltree_inc], + c_args: ['-DPLPYTHON_LIBNAME="plpython3"'], + kwargs: contrib_mod_args + { + 'dependencies': [python3_dep, contrib_mod_args['dependencies']], + }, +) +contrib_targets += ltree_plpython + +install_data( + 'ltree_plpython3u--1.0.sql', + 'ltree_plpython3u.control', + kwargs: contrib_data_args, +) + +ltree_plpython_regress = [ + 'ltree_plpython' +] + +tests += { + 'name': 'ltree_plpython', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': ltree_plpython_regress, + 'regress_args': ['--load-extension=ltree'], + }, +} diff --git a/contrib/ltree_plpython/sql/ltree_plpython.sql b/contrib/ltree_plpython/sql/ltree_plpython.sql new file mode 100644 index 0000000..0b8d283 --- /dev/null +++ b/contrib/ltree_plpython/sql/ltree_plpython.sql @@ -0,0 +1,36 @@ +CREATE EXTENSION ltree_plpython3u CASCADE; + + +CREATE FUNCTION test1(val ltree) RETURNS int +LANGUAGE plpython3u +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 plpython3u +TRANSFORM FOR TYPE ltree +AS $$ +plpy.info(repr(val)) +return len(val) +$$; + +SELECT test1n('aa.bb.cc'::ltree); + + +CREATE FUNCTION test2() RETURNS ltree +LANGUAGE plpython3u +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(); |