Age Owner Branch data TLA Line data Source code
1 : : #include "postgres.h"
2 : :
3 : : #include "fmgr.h"
4 : : #include "hstore/hstore.h"
5 : : #include "plpy_typeio.h"
6 : : #include "plpy_util.h"
7 : :
164 tgl@sss.pgh.pa.us 8 :CBC 1 : PG_MODULE_MAGIC_EXT(
9 : : .name = "hstore_plpython",
10 : : .version = PG_VERSION
11 : : );
12 : :
13 : : /* Linkage to functions in plpython module */
14 : : typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
15 : : static PLyObject_AsString_t PLyObject_AsString_p;
16 : : typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size);
17 : : static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
18 : :
19 : : /* Linkage to functions in hstore module */
20 : : typedef HStore *(*hstoreUpgrade_t) (Datum orig);
21 : : static hstoreUpgrade_t hstoreUpgrade_p;
22 : : typedef int (*hstoreUniquePairs_t) (Pairs *a, int32 l, int32 *buflen);
23 : : static hstoreUniquePairs_t hstoreUniquePairs_p;
24 : : typedef HStore *(*hstorePairs_t) (Pairs *pairs, int32 pcount, int32 buflen);
25 : : static hstorePairs_t hstorePairs_p;
26 : : typedef size_t (*hstoreCheckKeyLen_t) (size_t len);
27 : : static hstoreCheckKeyLen_t hstoreCheckKeyLen_p;
28 : : typedef size_t (*hstoreCheckValLen_t) (size_t len);
29 : : static hstoreCheckValLen_t hstoreCheckValLen_p;
30 : :
31 : :
32 : : /*
33 : : * Module initialize function: fetch function pointers for cross-module calls.
34 : : */
35 : : void
3260 36 : 1 : _PG_init(void)
37 : : {
38 : : /* Asserts verify that typedefs above match original declarations */
39 : : AssertVariableIsOfType(&PLyObject_AsString, PLyObject_AsString_t);
40 : 1 : PLyObject_AsString_p = (PLyObject_AsString_t)
41 : 1 : load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyObject_AsString",
42 : : true, NULL);
43 : : AssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t);
3259 44 : 1 : PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t)
45 : 1 : load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize",
46 : : true, NULL);
47 : : AssertVariableIsOfType(&hstoreUpgrade, hstoreUpgrade_t);
3260 48 : 1 : hstoreUpgrade_p = (hstoreUpgrade_t)
49 : 1 : load_external_function("$libdir/hstore", "hstoreUpgrade",
50 : : true, NULL);
51 : : AssertVariableIsOfType(&hstoreUniquePairs, hstoreUniquePairs_t);
52 : 1 : hstoreUniquePairs_p = (hstoreUniquePairs_t)
53 : 1 : load_external_function("$libdir/hstore", "hstoreUniquePairs",
54 : : true, NULL);
55 : : AssertVariableIsOfType(&hstorePairs, hstorePairs_t);
56 : 1 : hstorePairs_p = (hstorePairs_t)
57 : 1 : load_external_function("$libdir/hstore", "hstorePairs",
58 : : true, NULL);
59 : : AssertVariableIsOfType(&hstoreCheckKeyLen, hstoreCheckKeyLen_t);
60 : 1 : hstoreCheckKeyLen_p = (hstoreCheckKeyLen_t)
61 : 1 : load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
62 : : true, NULL);
63 : : AssertVariableIsOfType(&hstoreCheckValLen, hstoreCheckValLen_t);
64 : 1 : hstoreCheckValLen_p = (hstoreCheckValLen_t)
65 : 1 : load_external_function("$libdir/hstore", "hstoreCheckValLen",
66 : : true, NULL);
67 : 1 : }
68 : :
69 : :
70 : : /* These defines must be after the module init function */
71 : : #define PLyObject_AsString PLyObject_AsString_p
72 : : #define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p
73 : : #define hstoreUpgrade hstoreUpgrade_p
74 : : #define hstoreUniquePairs hstoreUniquePairs_p
75 : : #define hstorePairs hstorePairs_p
76 : : #define hstoreCheckKeyLen hstoreCheckKeyLen_p
77 : : #define hstoreCheckValLen hstoreCheckValLen_p
78 : :
79 : :
3786 peter_e@gmx.net 80 : 2 : PG_FUNCTION_INFO_V1(hstore_to_plpython);
81 : :
82 : : Datum
83 : 7 : hstore_to_plpython(PG_FUNCTION_ARGS)
84 : : {
2910 tgl@sss.pgh.pa.us 85 : 7 : HStore *in = PG_GETARG_HSTORE_P(0);
86 : : int i;
3786 peter_e@gmx.net 87 : 7 : int count = HS_COUNT(in);
88 : 7 : char *base = STRPTR(in);
89 : 7 : HEntry *entries = ARRPTR(in);
90 : : PyObject *dict;
91 : :
92 : 7 : dict = PyDict_New();
2867 93 [ - + ]: 7 : if (!dict)
2867 peter_e@gmx.net 94 [ # # ]:UBC 0 : ereport(ERROR,
95 : : (errcode(ERRCODE_OUT_OF_MEMORY),
96 : : errmsg("out of memory")));
97 : :
3786 peter_e@gmx.net 98 [ + + ]:CBC 20 : for (i = 0; i < count; i++)
99 : : {
100 : : PyObject *key;
101 : :
1279 andres@anarazel.de 102 [ + + ]: 13 : key = PLyUnicode_FromStringAndSize(HSTORE_KEY(entries, base, i),
1213 tgl@sss.pgh.pa.us 103 [ + + ]: 13 : HSTORE_KEYLEN(entries, i));
3579 104 [ + + ]: 13 : if (HSTORE_VALISNULL(entries, i))
3786 peter_e@gmx.net 105 : 6 : PyDict_SetItem(dict, key, Py_None);
106 : : else
107 : : {
108 : : PyObject *value;
109 : :
1279 andres@anarazel.de 110 [ + - ]: 7 : value = PLyUnicode_FromStringAndSize(HSTORE_VAL(entries, base, i),
1213 tgl@sss.pgh.pa.us 111 [ - + ]: 7 : HSTORE_VALLEN(entries, i));
3786 peter_e@gmx.net 112 : 7 : PyDict_SetItem(dict, key, value);
113 : 7 : Py_XDECREF(value);
114 : : }
115 : 13 : Py_XDECREF(key);
116 : : }
117 : :
118 : 7 : return PointerGetDatum(dict);
119 : : }
120 : :
121 : :
122 : 2 : PG_FUNCTION_INFO_V1(plpython_to_hstore);
123 : :
124 : : Datum
125 : 8 : plpython_to_hstore(PG_FUNCTION_ARGS)
126 : : {
127 : : PyObject *dict;
128 : : PyObject *volatile items;
129 : : Py_ssize_t pcount;
130 : : HStore *volatile out;
131 : :
132 : 8 : dict = (PyObject *) PG_GETARG_POINTER(0);
133 : :
134 : : /*
135 : : * As of Python 3, PyMapping_Check() is unreliable unless one first checks
136 : : * that the object isn't a sequence. (Cleaner solutions exist, but not
137 : : * before Python 3.10, which we're not prepared to require yet.)
138 : : */
863 tgl@sss.pgh.pa.us 139 [ + + - + ]: 8 : if (PySequence_Check(dict) || !PyMapping_Check(dict))
3786 peter_e@gmx.net 140 [ + - ]: 1 : ereport(ERROR,
141 : : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
142 : : errmsg("not a Python mapping")));
143 : :
144 : 7 : pcount = PyMapping_Size(dict);
2368 peter@eisentraut.org 145 : 7 : items = PyMapping_Items(dict);
146 : :
3786 peter_e@gmx.net 147 [ + - ]: 7 : PG_TRY();
148 : : {
149 : : int32 buflen;
150 : : Py_ssize_t i;
151 : : Pairs *pairs;
152 : :
153 : 7 : pairs = palloc(pcount * sizeof(*pairs));
154 : :
155 [ + + ]: 26 : for (i = 0; i < pcount; i++)
156 : : {
157 : : PyObject *tuple;
158 : : PyObject *key;
159 : : PyObject *value;
160 : :
161 : 19 : tuple = PyList_GetItem(items, i);
162 : 19 : key = PyTuple_GetItem(tuple, 0);
163 : 19 : value = PyTuple_GetItem(tuple, 1);
164 : :
165 : 19 : pairs[i].key = PLyObject_AsString(key);
166 : 19 : pairs[i].keylen = hstoreCheckKeyLen(strlen(pairs[i].key));
167 : 19 : pairs[i].needfree = true;
168 : :
169 [ + + ]: 19 : if (value == Py_None)
170 : : {
171 : 6 : pairs[i].val = NULL;
172 : 6 : pairs[i].vallen = 0;
173 : 6 : pairs[i].isnull = true;
174 : : }
175 : : else
176 : : {
177 : 13 : pairs[i].val = PLyObject_AsString(value);
178 : 13 : pairs[i].vallen = hstoreCheckValLen(strlen(pairs[i].val));
179 : 13 : pairs[i].isnull = false;
180 : : }
181 : : }
182 : :
183 : 7 : pcount = hstoreUniquePairs(pairs, pcount, &buflen);
184 : 7 : out = hstorePairs(pairs, pcount, buflen);
185 : : }
2136 peter@eisentraut.org 186 :UBC 0 : PG_FINALLY();
187 : : {
2368 peter@eisentraut.org 188 :CBC 7 : Py_DECREF(items);
189 : : }
3786 peter_e@gmx.net 190 [ - + ]: 7 : PG_END_TRY();
191 : :
192 : 7 : PG_RETURN_POINTER(out);
193 : : }
|