Age Owner TLA Line data Source code
1 : #include "postgres.h"
2 :
3 : #include "fmgr.h"
4 : #include "hstore/hstore.h"
5 : #include "plperl.h"
2905 peter_e 6 ECB :
2905 peter_e 7 GIC 3 : PG_MODULE_MAGIC;
8 :
9 : /* Linkage to functions in hstore module */
10 : typedef HStore *(*hstoreUpgrade_t) (Datum orig);
11 : static hstoreUpgrade_t hstoreUpgrade_p;
12 : typedef int (*hstoreUniquePairs_t) (Pairs *a, int32 l, int32 *buflen);
13 : static hstoreUniquePairs_t hstoreUniquePairs_p;
14 : typedef HStore *(*hstorePairs_t) (Pairs *pairs, int32 pcount, int32 buflen);
15 : static hstorePairs_t hstorePairs_p;
16 : typedef size_t (*hstoreCheckKeyLen_t) (size_t len);
17 : static hstoreCheckKeyLen_t hstoreCheckKeyLen_p;
18 : typedef size_t (*hstoreCheckValLen_t) (size_t len);
19 : static hstoreCheckValLen_t hstoreCheckValLen_p;
20 :
21 :
22 : /*
2378 tgl 23 ECB : * Module initialize function: fetch function pointers for cross-module calls.
24 : */
25 : void
2378 tgl 26 GIC 3 : _PG_init(void)
2378 tgl 27 ECB : {
28 : /* Asserts verify that typedefs above match original declarations */
29 : AssertVariableIsOfType(&hstoreUpgrade, hstoreUpgrade_t);
2378 tgl 30 GIC 3 : hstoreUpgrade_p = (hstoreUpgrade_t)
2378 tgl 31 CBC 3 : load_external_function("$libdir/hstore", "hstoreUpgrade",
2378 tgl 32 ECB : true, NULL);
33 : AssertVariableIsOfType(&hstoreUniquePairs, hstoreUniquePairs_t);
2378 tgl 34 GIC 3 : hstoreUniquePairs_p = (hstoreUniquePairs_t)
2378 tgl 35 CBC 3 : load_external_function("$libdir/hstore", "hstoreUniquePairs",
2378 tgl 36 ECB : true, NULL);
37 : AssertVariableIsOfType(&hstorePairs, hstorePairs_t);
2378 tgl 38 GIC 3 : hstorePairs_p = (hstorePairs_t)
2378 tgl 39 CBC 3 : load_external_function("$libdir/hstore", "hstorePairs",
2378 tgl 40 ECB : true, NULL);
41 : AssertVariableIsOfType(&hstoreCheckKeyLen, hstoreCheckKeyLen_t);
2378 tgl 42 GIC 3 : hstoreCheckKeyLen_p = (hstoreCheckKeyLen_t)
2378 tgl 43 CBC 3 : load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
2378 tgl 44 ECB : true, NULL);
45 : AssertVariableIsOfType(&hstoreCheckValLen, hstoreCheckValLen_t);
2378 tgl 46 CBC 3 : hstoreCheckValLen_p = (hstoreCheckValLen_t)
2378 tgl 47 GIC 3 : load_external_function("$libdir/hstore", "hstoreCheckValLen",
48 : true, NULL);
49 3 : }
50 :
51 :
52 : /* These defines must be after the module init function */
53 : #define hstoreUpgrade hstoreUpgrade_p
54 : #define hstoreUniquePairs hstoreUniquePairs_p
55 : #define hstorePairs hstorePairs_p
56 : #define hstoreCheckKeyLen hstoreCheckKeyLen_p
2378 tgl 57 ECB : #define hstoreCheckValLen hstoreCheckValLen_p
58 :
59 :
2905 peter_e 60 CBC 5 : PG_FUNCTION_INFO_V1(hstore_to_plperl);
61 :
2905 peter_e 62 ECB : Datum
2905 peter_e 63 CBC 7 : hstore_to_plperl(PG_FUNCTION_ARGS)
64 : {
2081 tgl 65 7 : dTHX;
2029 66 7 : HStore *in = PG_GETARG_HSTORE_P(0);
2905 peter_e 67 ECB : int i;
2905 peter_e 68 GIC 7 : int count = HS_COUNT(in);
69 7 : char *base = STRPTR(in);
2905 peter_e 70 CBC 7 : HEntry *entries = ARRPTR(in);
71 : HV *hv;
2905 peter_e 72 ECB :
2905 peter_e 73 GIC 7 : hv = newHV();
74 :
75 20 : for (i = 0; i < count; i++)
76 : {
2905 peter_e 77 ECB : const char *key;
2878 bruce 78 : SV *value;
2905 peter_e 79 :
2698 tgl 80 CBC 13 : key = pnstrdup(HSTORE_KEY(entries, base, i),
81 13 : HSTORE_KEYLEN(entries, i));
2698 tgl 82 GIC 13 : value = HSTORE_VALISNULL(entries, i) ? newSV(0) :
2698 tgl 83 CBC 7 : cstr2sv(pnstrdup(HSTORE_VAL(entries, base, i),
2698 tgl 84 GIC 7 : HSTORE_VALLEN(entries, i)));
85 :
2905 peter_e 86 CBC 13 : (void) hv_store(hv, key, strlen(key), value, 0);
87 : }
88 :
2905 peter_e 89 GIC 7 : return PointerGetDatum(newRV((SV *) hv));
2905 peter_e 90 ECB : }
91 :
92 :
2905 peter_e 93 CBC 6 : PG_FUNCTION_INFO_V1(plperl_to_hstore);
94 :
2905 peter_e 95 ECB : Datum
2905 peter_e 96 CBC 7 : plperl_to_hstore(PG_FUNCTION_ARGS)
97 : {
2081 tgl 98 GIC 7 : dTHX;
1756 99 7 : SV *in = (SV *) PG_GETARG_POINTER(0);
100 : HV *hv;
101 : HE *he;
102 : int32 buflen;
103 : int32 i;
104 : int32 pcount;
105 : HStore *out;
2905 peter_e 106 ECB : Pairs *pairs;
107 :
108 : /* Dereference references recursively. */
1756 tgl 109 GIC 13 : while (SvROK(in))
1756 tgl 110 CBC 6 : in = SvRV(in);
1756 tgl 111 ECB :
112 : /* Now we must have a hash. */
1756 tgl 113 GIC 7 : if (SvTYPE(in) != SVt_PVHV)
1756 tgl 114 CBC 2 : ereport(ERROR,
115 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1165 alvherre 116 ECB : errmsg("cannot transform non-hash Perl value to hstore")));
1756 tgl 117 GIC 5 : hv = (HV *) in;
1756 tgl 118 ECB :
2905 peter_e 119 GIC 5 : pcount = hv_iterinit(hv);
2905 peter_e 120 ECB :
2905 peter_e 121 CBC 5 : pairs = palloc(pcount * sizeof(Pairs));
122 :
123 5 : i = 0;
124 18 : while ((he = hv_iternext(hv)))
125 : {
2878 bruce 126 13 : char *key = sv2cstr(HeSVKEY_force(he));
127 13 : SV *value = HeVAL(he);
2905 peter_e 128 ECB :
2905 peter_e 129 GIC 13 : pairs[i].key = pstrdup(key);
2905 peter_e 130 CBC 13 : pairs[i].keylen = hstoreCheckKeyLen(strlen(pairs[i].key));
2905 peter_e 131 GIC 13 : pairs[i].needfree = true;
2905 peter_e 132 ECB :
2905 peter_e 133 CBC 13 : if (!SvOK(value))
2905 peter_e 134 ECB : {
2905 peter_e 135 GIC 4 : pairs[i].val = NULL;
136 4 : pairs[i].vallen = 0;
137 4 : pairs[i].isnull = true;
2905 peter_e 138 ECB : }
139 : else
140 : {
2905 peter_e 141 GIC 9 : pairs[i].val = pstrdup(sv2cstr(value));
142 9 : pairs[i].vallen = hstoreCheckValLen(strlen(pairs[i].val));
2905 peter_e 143 CBC 9 : pairs[i].isnull = false;
144 : }
145 :
146 13 : i++;
2905 peter_e 147 ECB : }
148 :
2905 peter_e 149 GIC 5 : pcount = hstoreUniquePairs(pairs, pcount, &buflen);
150 5 : out = hstorePairs(pairs, pcount, buflen);
151 5 : PG_RETURN_POINTER(out);
152 : }
|