4 #include "hstore/hstore.h"
5 #include "plpy_typeio.h"
10 extern void _PG_init(void);
12 /* Linkage to functions in plpython module */
13 typedef char *(*PLyObject_AsString_t
) (PyObject
*plrv
);
14 static PLyObject_AsString_t PLyObject_AsString_p
;
15 #if PY_MAJOR_VERSION >= 3
16 typedef PyObject
*(*PLyUnicode_FromStringAndSize_t
) (const char *s
, Py_ssize_t size
);
17 static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p
;
20 /* Linkage to functions in hstore module */
21 typedef HStore
*(*hstoreUpgrade_t
) (Datum orig
);
22 static hstoreUpgrade_t hstoreUpgrade_p
;
23 typedef int (*hstoreUniquePairs_t
) (Pairs
*a
, int32 l
, int32
*buflen
);
24 static hstoreUniquePairs_t hstoreUniquePairs_p
;
25 typedef HStore
*(*hstorePairs_t
) (Pairs
*pairs
, int32 pcount
, int32 buflen
);
26 static hstorePairs_t hstorePairs_p
;
27 typedef size_t (*hstoreCheckKeyLen_t
) (size_t len
);
28 static hstoreCheckKeyLen_t hstoreCheckKeyLen_p
;
29 typedef size_t (*hstoreCheckValLen_t
) (size_t len
);
30 static hstoreCheckValLen_t hstoreCheckValLen_p
;
34 * Module initialize function: fetch function pointers for cross-module calls.
39 /* Asserts verify that typedefs above match original declarations */
40 AssertVariableIsOfType(&PLyObject_AsString
, PLyObject_AsString_t
);
41 PLyObject_AsString_p
= (PLyObject_AsString_t
)
42 load_external_function("$libdir/" PLPYTHON_LIBNAME
, "PLyObject_AsString",
44 #if PY_MAJOR_VERSION >= 3
45 AssertVariableIsOfType(&PLyUnicode_FromStringAndSize
, PLyUnicode_FromStringAndSize_t
);
46 PLyUnicode_FromStringAndSize_p
= (PLyUnicode_FromStringAndSize_t
)
47 load_external_function("$libdir/" PLPYTHON_LIBNAME
, "PLyUnicode_FromStringAndSize",
50 AssertVariableIsOfType(&hstoreUpgrade
, hstoreUpgrade_t
);
51 hstoreUpgrade_p
= (hstoreUpgrade_t
)
52 load_external_function("$libdir/hstore", "hstoreUpgrade",
54 AssertVariableIsOfType(&hstoreUniquePairs
, hstoreUniquePairs_t
);
55 hstoreUniquePairs_p
= (hstoreUniquePairs_t
)
56 load_external_function("$libdir/hstore", "hstoreUniquePairs",
58 AssertVariableIsOfType(&hstorePairs
, hstorePairs_t
);
59 hstorePairs_p
= (hstorePairs_t
)
60 load_external_function("$libdir/hstore", "hstorePairs",
62 AssertVariableIsOfType(&hstoreCheckKeyLen
, hstoreCheckKeyLen_t
);
63 hstoreCheckKeyLen_p
= (hstoreCheckKeyLen_t
)
64 load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
66 AssertVariableIsOfType(&hstoreCheckValLen
, hstoreCheckValLen_t
);
67 hstoreCheckValLen_p
= (hstoreCheckValLen_t
)
68 load_external_function("$libdir/hstore", "hstoreCheckValLen",
73 /* These defines must be after the module init function */
74 #define PLyObject_AsString PLyObject_AsString_p
75 #define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p
76 #define hstoreUpgrade hstoreUpgrade_p
77 #define hstoreUniquePairs hstoreUniquePairs_p
78 #define hstorePairs hstorePairs_p
79 #define hstoreCheckKeyLen hstoreCheckKeyLen_p
80 #define hstoreCheckValLen hstoreCheckValLen_p
83 PG_FUNCTION_INFO_V1(hstore_to_plpython
);
86 hstore_to_plpython(PG_FUNCTION_ARGS
)
88 HStore
*in
= PG_GETARG_HSTORE_P(0);
90 int count
= HS_COUNT(in
);
91 char *base
= STRPTR(in
);
92 HEntry
*entries
= ARRPTR(in
);
98 (errcode(ERRCODE_OUT_OF_MEMORY
),
99 errmsg("out of memory")));
101 for (i
= 0; i
< count
; i
++)
105 key
= PyString_FromStringAndSize(HSTORE_KEY(entries
, base
, i
),
106 HSTORE_KEYLEN(entries
, i
));
107 if (HSTORE_VALISNULL(entries
, i
))
108 PyDict_SetItem(dict
, key
, Py_None
);
113 value
= PyString_FromStringAndSize(HSTORE_VAL(entries
, base
, i
),
114 HSTORE_VALLEN(entries
, i
));
115 PyDict_SetItem(dict
, key
, value
);
121 return PointerGetDatum(dict
);
125 PG_FUNCTION_INFO_V1(plpython_to_hstore
);
128 plpython_to_hstore(PG_FUNCTION_ARGS
)
131 PyObject
*volatile items
;
133 HStore
*volatile out
;
135 dict
= (PyObject
*) PG_GETARG_POINTER(0);
138 * As of Python 3, PyMapping_Check() is unreliable unless one first checks
139 * that the object isn't a sequence. (Cleaner solutions exist, but not
140 * before Python 3.10, which we're not prepared to require yet.)
142 if (PySequence_Check(dict
) || !PyMapping_Check(dict
))
144 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
145 errmsg("not a Python mapping")));
147 pcount
= PyMapping_Size(dict
);
148 items
= PyMapping_Items(dict
);
156 pairs
= palloc(pcount
* sizeof(*pairs
));
158 for (i
= 0; i
< pcount
; i
++)
164 tuple
= PyList_GetItem(items
, i
);
165 key
= PyTuple_GetItem(tuple
, 0);
166 value
= PyTuple_GetItem(tuple
, 1);
168 pairs
[i
].key
= PLyObject_AsString(key
);
169 pairs
[i
].keylen
= hstoreCheckKeyLen(strlen(pairs
[i
].key
));
170 pairs
[i
].needfree
= true;
172 if (value
== Py_None
)
176 pairs
[i
].isnull
= true;
180 pairs
[i
].val
= PLyObject_AsString(value
);
181 pairs
[i
].vallen
= hstoreCheckValLen(strlen(pairs
[i
].val
));
182 pairs
[i
].isnull
= false;
186 pcount
= hstoreUniquePairs(pairs
, pcount
, &buflen
);
187 out
= hstorePairs(pairs
, pcount
, buflen
);
195 PG_RETURN_POINTER(out
);