4 #include "hstore/hstore.h"
5 #include "plpy_typeio.h"
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.
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",
40 AssertVariableIsOfType(&PLyUnicode_FromStringAndSize
, PLyUnicode_FromStringAndSize_t
);
41 PLyUnicode_FromStringAndSize_p
= (PLyUnicode_FromStringAndSize_t
)
42 load_external_function("$libdir/" PLPYTHON_LIBNAME
, "PLyUnicode_FromStringAndSize",
44 AssertVariableIsOfType(&hstoreUpgrade
, hstoreUpgrade_t
);
45 hstoreUpgrade_p
= (hstoreUpgrade_t
)
46 load_external_function("$libdir/hstore", "hstoreUpgrade",
48 AssertVariableIsOfType(&hstoreUniquePairs
, hstoreUniquePairs_t
);
49 hstoreUniquePairs_p
= (hstoreUniquePairs_t
)
50 load_external_function("$libdir/hstore", "hstoreUniquePairs",
52 AssertVariableIsOfType(&hstorePairs
, hstorePairs_t
);
53 hstorePairs_p
= (hstorePairs_t
)
54 load_external_function("$libdir/hstore", "hstorePairs",
56 AssertVariableIsOfType(&hstoreCheckKeyLen
, hstoreCheckKeyLen_t
);
57 hstoreCheckKeyLen_p
= (hstoreCheckKeyLen_t
)
58 load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
60 AssertVariableIsOfType(&hstoreCheckValLen
, hstoreCheckValLen_t
);
61 hstoreCheckValLen_p
= (hstoreCheckValLen_t
)
62 load_external_function("$libdir/hstore", "hstoreCheckValLen",
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
);
80 hstore_to_plpython(PG_FUNCTION_ARGS
)
82 HStore
*in
= PG_GETARG_HSTORE_P(0);
84 int count
= HS_COUNT(in
);
85 char *base
= STRPTR(in
);
86 HEntry
*entries
= ARRPTR(in
);
92 (errcode(ERRCODE_OUT_OF_MEMORY
),
93 errmsg("out of memory")));
95 for (i
= 0; i
< count
; i
++)
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
);
107 value
= PLyUnicode_FromStringAndSize(HSTORE_VAL(entries
, base
, i
),
108 HSTORE_VALLEN(entries
, i
));
109 PyDict_SetItem(dict
, key
, value
);
115 return PointerGetDatum(dict
);
119 PG_FUNCTION_INFO_V1(plpython_to_hstore
);
122 plpython_to_hstore(PG_FUNCTION_ARGS
)
125 PyObject
*volatile items
;
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
))
138 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
139 errmsg("not a Python mapping")));
141 pcount
= PyMapping_Size(dict
);
142 items
= PyMapping_Items(dict
);
150 pairs
= palloc(pcount
* sizeof(*pairs
));
152 for (i
= 0; i
< pcount
; i
++)
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
)
170 pairs
[i
].isnull
= true;
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
);
189 PG_RETURN_POINTER(out
);