Fix use-after-free in parallel_vacuum_reset_dead_items
[pgsql.git] / contrib / hstore_plpython / hstore_plpython.c
blob310f63c30d48193b3944458c6469cc463c97fff6
1 #include "postgres.h"
3 #include "fmgr.h"
4 #include "hstore/hstore.h"
5 #include "plpy_typeio.h"
6 #include "plpython.h"
8 PG_MODULE_MAGIC;
10 /* Linkage to functions in plpython module */
11 typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
12 static PLyObject_AsString_t PLyObject_AsString_p;
13 typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size);
14 static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
16 /* Linkage to functions in hstore module */
17 typedef HStore *(*hstoreUpgrade_t) (Datum orig);
18 static hstoreUpgrade_t hstoreUpgrade_p;
19 typedef int (*hstoreUniquePairs_t) (Pairs *a, int32 l, int32 *buflen);
20 static hstoreUniquePairs_t hstoreUniquePairs_p;
21 typedef HStore *(*hstorePairs_t) (Pairs *pairs, int32 pcount, int32 buflen);
22 static hstorePairs_t hstorePairs_p;
23 typedef size_t (*hstoreCheckKeyLen_t) (size_t len);
24 static hstoreCheckKeyLen_t hstoreCheckKeyLen_p;
25 typedef size_t (*hstoreCheckValLen_t) (size_t len);
26 static hstoreCheckValLen_t hstoreCheckValLen_p;
30 * Module initialize function: fetch function pointers for cross-module calls.
32 void
33 _PG_init(void)
35 /* Asserts verify that typedefs above match original declarations */
36 AssertVariableIsOfType(&PLyObject_AsString, PLyObject_AsString_t);
37 PLyObject_AsString_p = (PLyObject_AsString_t)
38 load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyObject_AsString",
39 true, NULL);
40 AssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t);
41 PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t)
42 load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize",
43 true, NULL);
44 AssertVariableIsOfType(&hstoreUpgrade, hstoreUpgrade_t);
45 hstoreUpgrade_p = (hstoreUpgrade_t)
46 load_external_function("$libdir/hstore", "hstoreUpgrade",
47 true, NULL);
48 AssertVariableIsOfType(&hstoreUniquePairs, hstoreUniquePairs_t);
49 hstoreUniquePairs_p = (hstoreUniquePairs_t)
50 load_external_function("$libdir/hstore", "hstoreUniquePairs",
51 true, NULL);
52 AssertVariableIsOfType(&hstorePairs, hstorePairs_t);
53 hstorePairs_p = (hstorePairs_t)
54 load_external_function("$libdir/hstore", "hstorePairs",
55 true, NULL);
56 AssertVariableIsOfType(&hstoreCheckKeyLen, hstoreCheckKeyLen_t);
57 hstoreCheckKeyLen_p = (hstoreCheckKeyLen_t)
58 load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
59 true, NULL);
60 AssertVariableIsOfType(&hstoreCheckValLen, hstoreCheckValLen_t);
61 hstoreCheckValLen_p = (hstoreCheckValLen_t)
62 load_external_function("$libdir/hstore", "hstoreCheckValLen",
63 true, NULL);
67 /* These defines must be after the module init function */
68 #define PLyObject_AsString PLyObject_AsString_p
69 #define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p
70 #define hstoreUpgrade hstoreUpgrade_p
71 #define hstoreUniquePairs hstoreUniquePairs_p
72 #define hstorePairs hstorePairs_p
73 #define hstoreCheckKeyLen hstoreCheckKeyLen_p
74 #define hstoreCheckValLen hstoreCheckValLen_p
77 PG_FUNCTION_INFO_V1(hstore_to_plpython);
79 Datum
80 hstore_to_plpython(PG_FUNCTION_ARGS)
82 HStore *in = PG_GETARG_HSTORE_P(0);
83 int i;
84 int count = HS_COUNT(in);
85 char *base = STRPTR(in);
86 HEntry *entries = ARRPTR(in);
87 PyObject *dict;
89 dict = PyDict_New();
90 if (!dict)
91 ereport(ERROR,
92 (errcode(ERRCODE_OUT_OF_MEMORY),
93 errmsg("out of memory")));
95 for (i = 0; i < count; i++)
97 PyObject *key;
99 key = PLyUnicode_FromStringAndSize(HSTORE_KEY(entries, base, i),
100 HSTORE_KEYLEN(entries, i));
101 if (HSTORE_VALISNULL(entries, i))
102 PyDict_SetItem(dict, key, Py_None);
103 else
105 PyObject *value;
107 value = PLyUnicode_FromStringAndSize(HSTORE_VAL(entries, base, i),
108 HSTORE_VALLEN(entries, i));
109 PyDict_SetItem(dict, key, value);
110 Py_XDECREF(value);
112 Py_XDECREF(key);
115 return PointerGetDatum(dict);
119 PG_FUNCTION_INFO_V1(plpython_to_hstore);
121 Datum
122 plpython_to_hstore(PG_FUNCTION_ARGS)
124 PyObject *dict;
125 PyObject *volatile items;
126 Py_ssize_t pcount;
127 HStore *volatile out;
129 dict = (PyObject *) PG_GETARG_POINTER(0);
132 * As of Python 3, PyMapping_Check() is unreliable unless one first checks
133 * that the object isn't a sequence. (Cleaner solutions exist, but not
134 * before Python 3.10, which we're not prepared to require yet.)
136 if (PySequence_Check(dict) || !PyMapping_Check(dict))
137 ereport(ERROR,
138 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
139 errmsg("not a Python mapping")));
141 pcount = PyMapping_Size(dict);
142 items = PyMapping_Items(dict);
144 PG_TRY();
146 int32 buflen;
147 Py_ssize_t i;
148 Pairs *pairs;
150 pairs = palloc(pcount * sizeof(*pairs));
152 for (i = 0; i < pcount; i++)
154 PyObject *tuple;
155 PyObject *key;
156 PyObject *value;
158 tuple = PyList_GetItem(items, i);
159 key = PyTuple_GetItem(tuple, 0);
160 value = PyTuple_GetItem(tuple, 1);
162 pairs[i].key = PLyObject_AsString(key);
163 pairs[i].keylen = hstoreCheckKeyLen(strlen(pairs[i].key));
164 pairs[i].needfree = true;
166 if (value == Py_None)
168 pairs[i].val = NULL;
169 pairs[i].vallen = 0;
170 pairs[i].isnull = true;
172 else
174 pairs[i].val = PLyObject_AsString(value);
175 pairs[i].vallen = hstoreCheckValLen(strlen(pairs[i].val));
176 pairs[i].isnull = false;
180 pcount = hstoreUniquePairs(pairs, pcount, &buflen);
181 out = hstorePairs(pairs, pcount, buflen);
183 PG_FINALLY();
185 Py_DECREF(items);
187 PG_END_TRY();
189 PG_RETURN_POINTER(out);