mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
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
This commit is contained in:
6
contrib/ltree_plpython/.gitignore
vendored
Normal file
6
contrib/ltree_plpython/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Generated subdirectories
|
||||
/expected/python3/
|
||||
/log/
|
||||
/results/
|
||||
/sql/python3/
|
||||
/tmp_check/
|
31
contrib/ltree_plpython/Makefile
Normal file
31
contrib/ltree_plpython/Makefile
Normal file
@ -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
|
45
contrib/ltree_plpython/expected/ltree_plpython.out
Normal file
45
contrib/ltree_plpython/expected/ltree_plpython.out
Normal file
@ -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"
|
32
contrib/ltree_plpython/ltree_plpython.c
Normal file
32
contrib/ltree_plpython/ltree_plpython.c
Normal file
@ -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);
|
||||
}
|
12
contrib/ltree_plpython/ltree_plpython2u--1.0.sql
Normal file
12
contrib/ltree_plpython/ltree_plpython2u--1.0.sql
Normal file
@ -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)
|
||||
);
|
6
contrib/ltree_plpython/ltree_plpython2u.control
Normal file
6
contrib/ltree_plpython/ltree_plpython2u.control
Normal file
@ -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'
|
12
contrib/ltree_plpython/ltree_plpython3u--1.0.sql
Normal file
12
contrib/ltree_plpython/ltree_plpython3u--1.0.sql
Normal file
@ -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)
|
||||
);
|
6
contrib/ltree_plpython/ltree_plpython3u.control
Normal file
6
contrib/ltree_plpython/ltree_plpython3u.control
Normal file
@ -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'
|
12
contrib/ltree_plpython/ltree_plpythonu--1.0.sql
Normal file
12
contrib/ltree_plpython/ltree_plpythonu--1.0.sql
Normal file
@ -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)
|
||||
);
|
6
contrib/ltree_plpython/ltree_plpythonu.control
Normal file
6
contrib/ltree_plpython/ltree_plpythonu.control
Normal file
@ -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'
|
37
contrib/ltree_plpython/sql/ltree_plpython.sql
Normal file
37
contrib/ltree_plpython/sql/ltree_plpython.sql
Normal file
@ -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();
|
Reference in New Issue
Block a user