Datum hstore_to_plpython(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); PyObject *dict; dict = PyDict_New(); for (i = 0; i < count; i++) { PyObject *key; key = PyString_FromStringAndSize(HSTORE_KEY(entries, base, i), HSTORE_KEYLEN(entries, i)); if (HSTORE_VALISNULL(entries, i)) PyDict_SetItem(dict, key, Py_None); else { PyObject *value; value = PyString_FromStringAndSize(HSTORE_VAL(entries, base, i), HSTORE_VALLEN(entries, i)); PyDict_SetItem(dict, key, value); Py_XDECREF(value); } Py_XDECREF(key); } return PointerGetDatum(dict); }
Datum gin_extract_hstore(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); Datum *entries = NULL; HEntry *hsent = ARRPTR(hs); char *ptr = STRPTR(hs); int count = HS_COUNT(hs); int i; *nentries = 2 * count; if (count) entries = (Datum *) palloc(sizeof(Datum) * 2 * count); for (i = 0; i < count; ++i) { text *item; item = makeitem(HS_KEY(hsent, ptr, i), HS_KEYLEN(hsent, i), KEYFLAG); entries[2 * i] = PointerGetDatum(item); if (HS_VALISNULL(hsent, i)) item = makeitem(NULL, 0, NULLFLAG); else item = makeitem(HS_VAL(hsent, ptr, i), HS_VALLEN(hsent, i), VALFLAG); entries[2 * i + 1] = PointerGetDatum(item); } PG_RETURN_POINTER(entries); }
Datum hstore_exists_all(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1); int nkeys; Pairs *key_pairs = hstoreArrayToPairs(keys, &nkeys); int i; int lowbound = 0; bool res = true; /* * we exploit the fact that the pairs list is already sorted into strictly * increasing order to narrow the hstoreFindKey search; each search can * start one entry past the previous "found" entry, or at the lower bound * of the last search. */ for (i = 0; i < nkeys; i++) { int idx = hstoreFindKey(hs, &lowbound, key_pairs[i].key, key_pairs[i].keylen); if (idx < 0) { res = false; break; } } PG_RETURN_BOOL(res); }
Datum hstore_send(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); StringInfoData buf; pq_begintypsend(&buf); pq_sendint(&buf, count, 4); for (i = 0; i < count; i++) { int32 keylen = HS_KEYLEN(entries, i); pq_sendint(&buf, keylen, 4); pq_sendtext(&buf, HS_KEY(entries, base, i), keylen); if (HS_VALISNULL(entries, i)) { pq_sendint(&buf, -1, 4); } else { int32 vallen = HS_VALLEN(entries, i); pq_sendint(&buf, vallen, 4); pq_sendtext(&buf, HS_VAL(entries, base, i), vallen); } } PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum hstore_slice_to_array(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); HEntry *entries = ARRPTR(hs); char *ptr = STRPTR(hs); ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(1); ArrayType *aout; Datum *key_datums; bool *key_nulls; Datum *out_datums; bool *out_nulls; int key_count; int i; deconstruct_array(key_array, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); if (key_count == 0) { aout = construct_empty_array(TEXTOID); PG_RETURN_POINTER(aout); } out_datums = palloc(sizeof(Datum) * key_count); out_nulls = palloc(sizeof(bool) * key_count); for (i = 0; i < key_count; ++i) { text *key = (text *) DatumGetPointer(key_datums[i]); int idx; if (key_nulls[i]) idx = -1; else idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ); if (idx < 0 || HS_VALISNULL(entries, idx)) { out_nulls[i] = true; out_datums[i] = (Datum) 0; } else { out_datums[i] = PointerGetDatum( cstring_to_text_with_len(HS_VAL(entries, ptr, idx), HS_VALLEN(entries, idx))); out_nulls[i] = false; } } aout = construct_md_array(out_datums, out_nulls, ARR_NDIM(key_array), ARR_DIMS(key_array), ARR_LBOUND(key_array), TEXTOID, -1, false, 'i'); PG_RETURN_POINTER(aout); }
Datum hstore_skeys(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; HStore *hs; int i; if (SRF_IS_FIRSTCALL()) { hs = PG_GETARG_HS(0); funcctx = SRF_FIRSTCALL_INIT(); setup_firstcall(funcctx, hs, NULL); } funcctx = SRF_PERCALL_SETUP(); hs = (HStore *) funcctx->user_fctx; i = funcctx->call_cntr; if (i < HS_COUNT(hs)) { HEntry *entries = ARRPTR(hs); text *item; item = cstring_to_text_with_len(HS_KEY(entries, STRPTR(hs), i), HS_KEYLEN(entries, i)); SRF_RETURN_NEXT(funcctx, PointerGetDatum(item)); } SRF_RETURN_DONE(funcctx); }
Datum hstore_to_plperl(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); HV *hv; hv = newHV(); for (i = 0; i < count; i++) { const char *key; SV *value; key = pnstrdup(HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); value = HS_VALISNULL(entries, i) ? newSV(0) : cstr2sv(pnstrdup(HS_VAL(entries, base, i), HS_VALLEN(entries, i))); (void) hv_store(hv, key, strlen(key), value, 0); } return PointerGetDatum(newRV((SV *) hv)); }
Datum skeys(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; AKStore *st; if (SRF_IS_FIRSTCALL()) { HStore *hs = PG_GETARG_HS(0); funcctx = SRF_FIRSTCALL_INIT(); setup_firstcall(funcctx, hs); PG_FREE_IF_COPY(hs, 0); } funcctx = SRF_PERCALL_SETUP(); st = (AKStore *) funcctx->user_fctx; if (st->i < st->hs->size) { HEntry *ptr = &(ARRPTR(st->hs)[st->i]); text *item = (text *) palloc(VARHDRSZ + ptr->keylen); SET_VARSIZE(item, VARHDRSZ + ptr->keylen); memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos, ptr->keylen); st->i++; SRF_RETURN_NEXT(funcctx, PointerGetDatum(item)); } pfree(st->hs); pfree(st); SRF_RETURN_DONE(funcctx); }
Datum hstore_akeys(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); Datum *d; ArrayType *a; HEntry *entries = ARRPTR(hs); char *base = STRPTR(hs); int count = HS_COUNT(hs); int i; if (count == 0) { a = construct_empty_array(TEXTOID); PG_RETURN_POINTER(a); } d = (Datum *) palloc(sizeof(Datum) * count); for (i = 0; i < count; ++i) { text *item = cstring_to_text_with_len(HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); d[i] = PointerGetDatum(item); } a = construct_array(d, count, TEXTOID, -1, false, 'i'); PG_RETURN_POINTER(a); }
Datum hstore_to_matrix(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); ArrayType *out = hstore_to_array_internal(hs, 2); PG_RETURN_POINTER(out); }
Datum hstore_slice_to_hstore(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); HEntry *entries = ARRPTR(hs); char *ptr = STRPTR(hs); ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(1); HStore *out; int nkeys; Pairs *key_pairs = hstoreArrayToPairs(key_array, &nkeys); Pairs *out_pairs; int bufsiz; int lastidx = 0; int i; int out_count = 0; if (nkeys == 0) { out = hstorePairs(NULL, 0, 0); PG_RETURN_POINTER(out); } out_pairs = palloc(sizeof(Pairs) * nkeys); bufsiz = 0; /* * we exploit the fact that the pairs list is already sorted into strictly * increasing order to narrow the hstoreFindKey search; each search can * start one entry past the previous "found" entry, or at the lower bound * of the last search. */ for (i = 0; i < nkeys; ++i) { int idx = hstoreFindKey(hs, &lastidx, key_pairs[i].key, key_pairs[i].keylen); if (idx >= 0) { out_pairs[out_count].key = key_pairs[i].key; bufsiz += (out_pairs[out_count].keylen = key_pairs[i].keylen); out_pairs[out_count].val = HS_VAL(entries, ptr, idx); bufsiz += (out_pairs[out_count].vallen = HS_VALLEN(entries, idx)); out_pairs[out_count].isnull = HS_VALISNULL(entries, idx); out_pairs[out_count].needfree = false; ++out_count; } } /* * we don't use uniquePairs here because we know that the pairs list is * already sorted and uniq'ed. */ out = hstorePairs(out_pairs, out_count, bufsiz); PG_RETURN_POINTER(out); }
Datum hstore_exists(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_PP(1); int idx = hstoreFindKey(hs, NULL, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); PG_RETURN_BOOL(idx >= 0); }
Datum hstore_contains(PG_FUNCTION_ARGS) { HStore *val = PG_GETARG_HS(0); HStore *tmpl = PG_GETARG_HS(1); bool res = true; HEntry *te = ARRPTR(tmpl); char *tstr = STRPTR(tmpl); HEntry *ve = ARRPTR(val); char *vstr = STRPTR(val); int tcount = HS_COUNT(tmpl); int lastidx = 0; int i; /* * we exploit the fact that keys in "tmpl" are in strictly increasing * order to narrow the hstoreFindKey search; each search can start one * entry past the previous "found" entry, or at the lower bound of the * search */ for (i = 0; res && i < tcount; ++i) { int idx = hstoreFindKey(val, &lastidx, HS_KEY(te, tstr, i), HS_KEYLEN(te, i)); if (idx >= 0) { bool nullval = HS_VALISNULL(te, i); int vallen = HS_VALLEN(te, i); if (nullval != HS_VALISNULL(ve, idx) || (!nullval && (vallen != HS_VALLEN(ve, idx) || memcmp(HS_VAL(te, tstr, i), HS_VAL(ve, vstr, idx), vallen)))) res = false; } else res = false; } PG_RETURN_BOOL(res); }
Datum hstore_out(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int buflen, i; char *out, *ptr; char *base = STRPTR(in); HEntry *entries = ARRPTR(in); if (in->size == 0) { out = palloc(1); *out = '\0'; PG_FREE_IF_COPY(in, 0); PG_RETURN_CSTRING(out); } buflen = (4 /* " */ + 2 /* => */ + 2 /* , */ ) * in->size + 2 /* esc */ * (in->len - CALCDATASIZE(in->size, 0)); out = ptr = palloc(buflen); for (i = 0; i < in->size; i++) { *ptr++ = '"'; ptr = cpw(ptr, base + entries[i].pos, entries[i].keylen); *ptr++ = '"'; *ptr++ = '='; *ptr++ = '>'; if (entries[i].valisnull) { *ptr++ = 'N'; *ptr++ = 'U'; *ptr++ = 'L'; *ptr++ = 'L'; } else { *ptr++ = '"'; ptr = cpw(ptr, base + entries[i].pos + entries[i].keylen, entries[i].vallen); *ptr++ = '"'; } if (i + 1 != in->size) { *ptr++ = ','; *ptr++ = ' '; } } *ptr = '\0'; PG_FREE_IF_COPY(in, 0); PG_RETURN_CSTRING(out); }
Datum hstore_defined(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_PP(1); HEntry *entries = ARRPTR(hs); int idx = hstoreFindKey(hs, NULL, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); bool res = (idx >= 0 && !HS_VALISNULL(entries, idx)); PG_RETURN_BOOL(res); }
Datum hstore_each(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; HStore *hs; int i; if (SRF_IS_FIRSTCALL()) { hs = PG_GETARG_HS(0); funcctx = SRF_FIRSTCALL_INIT(); setup_firstcall(funcctx, hs, fcinfo); } funcctx = SRF_PERCALL_SETUP(); hs = (HStore *) funcctx->user_fctx; i = funcctx->call_cntr; if (i < HS_COUNT(hs)) { HEntry *entries = ARRPTR(hs); char *ptr = STRPTR(hs); Datum res, dvalues[2]; bool nulls[2] = {false, false}; text *item; HeapTuple tuple; item = cstring_to_text_with_len(HS_KEY(entries, ptr, i), HS_KEYLEN(entries, i)); dvalues[0] = PointerGetDatum(item); if (HS_VALISNULL(entries, i)) { dvalues[1] = (Datum) 0; nulls[1] = true; } else { item = cstring_to_text_with_len(HS_VAL(entries, ptr, i), HS_VALLEN(entries, i)); dvalues[1] = PointerGetDatum(item); } tuple = heap_form_tuple(funcctx->tuple_desc, dvalues, nulls); res = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, PointerGetDatum(res)); } SRF_RETURN_DONE(funcctx); }
Datum svals(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; AKStore *st; if (SRF_IS_FIRSTCALL()) { HStore *hs = PG_GETARG_HS(0); funcctx = SRF_FIRSTCALL_INIT(); setup_firstcall(funcctx, hs); PG_FREE_IF_COPY(hs, 0); } funcctx = SRF_PERCALL_SETUP(); st = (AKStore *) funcctx->user_fctx; if (st->i < st->hs->size) { HEntry *ptr = &(ARRPTR(st->hs)[st->i]); if (ptr->valisnull) { ReturnSetInfo *rsi; st->i++; (funcctx)->call_cntr++; rsi = (ReturnSetInfo *) fcinfo->resultinfo; rsi->isDone = ExprMultipleResult; PG_RETURN_NULL(); } else { int vallen = ptr->vallen; text *item = (text *) palloc(VARHDRSZ + vallen); SET_VARSIZE(item, VARHDRSZ + vallen); memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos + ptr->keylen, vallen); st->i++; SRF_RETURN_NEXT(funcctx, PointerGetDatum(item)); } } pfree(st->hs); pfree(st); SRF_RETURN_DONE(funcctx); }
Datum exists(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_P(1); HEntry *entry; entry = findkey(hs, VARDATA(key), VARSIZE(key) - VARHDRSZ); PG_FREE_IF_COPY(hs, 0); PG_FREE_IF_COPY(key, 1); PG_RETURN_BOOL(entry); }
Datum hs_contains(PG_FUNCTION_ARGS) { HStore *val = PG_GETARG_HS(0); HStore *tmpl = PG_GETARG_HS(1); bool res = true; HEntry *te = ARRPTR(tmpl); char *vv = STRPTR(val); char *tv = STRPTR(tmpl); while (res && te - ARRPTR(tmpl) < tmpl->size) { HEntry *entry = findkey(val, tv + te->pos, te->keylen); if (entry) { if (te->valisnull || entry->valisnull) { if (!(te->valisnull && entry->valisnull)) res = false; } else if (te->vallen != entry->vallen || strncmp(vv + entry->pos + entry->keylen, tv + te->pos + te->keylen, te->vallen)) res = false; } else res = false; te++; } PG_FREE_IF_COPY(val, 0); PG_FREE_IF_COPY(tmpl, 1); PG_RETURN_BOOL(res); }
Datum exists(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_P(1); HEntry *entry; bool res; entry = findkey(hs, VARDATA(key), VARSIZE(key) - VARHDRSZ); res = (entry != NULL) ? true : false; PG_FREE_IF_COPY(hs, 0); PG_FREE_IF_COPY(key, 1); PG_RETURN_BOOL(res); }
Datum hstore_to_jsonb(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); JsonbParseState *state = NULL; JsonbValue *res; res = pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL); for (i = 0; i < count; i++) { JsonbValue key, val; key.estSize = sizeof(JEntry); key.type = jbvString; key.val.string.len = HS_KEYLEN(entries, i); key.val.string.val = pnstrdup(HS_KEY(entries, base, i), key.val.string.len); key.estSize += key.val.string.len; res = pushJsonbValue(&state, WJB_KEY, &key); if (HS_VALISNULL(entries, i)) { val.estSize = sizeof(JEntry); val.type = jbvNull; } else { val.estSize = sizeof(JEntry); val.type = jbvString; val.val.string.len = HS_VALLEN(entries, i); val.val.string.val = pnstrdup(HS_VAL(entries, base, i), val.val.string.len); val.estSize += val.val.string.len; } res = pushJsonbValue(&state, WJB_VALUE, &val); } res = pushJsonbValue(&state, WJB_END_OBJECT, NULL); PG_RETURN_POINTER(JsonbValueToJsonb(res)); }
Datum gin_extract_hstore(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); Datum *entries = NULL; *nentries = 2 * hs->size; if (hs->size > 0) { HEntry *ptr = ARRPTR(hs); char *words = STRPTR(hs); int i = 0; entries = (Datum *) palloc(sizeof(Datum) * 2 * hs->size); while (ptr - ARRPTR(hs) < hs->size) { text *item; item = makeitem(words + ptr->pos, ptr->keylen); *VARDATA(item) = KEYFLAG; entries[i++] = PointerGetDatum(item); if (ptr->valisnull) { item = makeitem(NULL, 0); *VARDATA(item) = NULLFLAG; } else { item = makeitem(words + ptr->pos + ptr->keylen, ptr->vallen); *VARDATA(item) = VALFLAG; } entries[i++] = PointerGetDatum(item); ptr++; } } PG_FREE_IF_COPY(hs, 0); PG_RETURN_POINTER(entries); }
Datum hstore_svals(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; HStore *hs; int i; if (SRF_IS_FIRSTCALL()) { hs = PG_GETARG_HS(0); funcctx = SRF_FIRSTCALL_INIT(); setup_firstcall(funcctx, hs, NULL); } funcctx = SRF_PERCALL_SETUP(); hs = (HStore *) funcctx->user_fctx; i = funcctx->call_cntr; if (i < HS_COUNT(hs)) { HEntry *entries = ARRPTR(hs); if (HS_VALISNULL(entries, i)) { ReturnSetInfo *rsi; /* ugly ugly ugly. why no macro for this? */ (funcctx)->call_cntr++; rsi = (ReturnSetInfo *) fcinfo->resultinfo; rsi->isDone = ExprMultipleResult; PG_RETURN_NULL(); } else { text *item; item = cstring_to_text_with_len(HS_VAL(entries, STRPTR(hs), i), HS_VALLEN(entries, i)); SRF_RETURN_NEXT(funcctx, PointerGetDatum(item)); } } SRF_RETURN_DONE(funcctx); }
Datum hstore_fetchval(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_PP(1); HEntry *entries = ARRPTR(hs); text *out; int idx = hstoreFindKey(hs, NULL, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); if (idx < 0 || HS_VALISNULL(entries, idx)) PG_RETURN_NULL(); out = cstring_to_text_with_len(HS_VAL(entries, STRPTR(hs), idx), HS_VALLEN(entries, idx)); PG_RETURN_TEXT_P(out); }
Datum hstore_avals(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); Datum *d; bool *nulls; ArrayType *a; HEntry *entries = ARRPTR(hs); char *base = STRPTR(hs); int count = HS_COUNT(hs); int lb = 1; int i; if (count == 0) { a = construct_empty_array(TEXTOID); PG_RETURN_POINTER(a); } d = (Datum *) palloc(sizeof(Datum) * count); nulls = (bool *) palloc(sizeof(bool) * count); for (i = 0; i < count; ++i) { if (HS_VALISNULL(entries, i)) { d[i] = (Datum) 0; nulls[i] = true; } else { text *item = cstring_to_text_with_len(HS_VAL(entries, base, i), HS_VALLEN(entries, i)); d[i] = PointerGetDatum(item); nulls[i] = false; } } a = construct_md_array(d, nulls, 1, &count, &lb, TEXTOID, -1, false, 'i'); PG_RETURN_POINTER(a); }
Datum hstore_delete(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_PP(1); char *keyptr = VARDATA_ANY(key); int keylen = VARSIZE_ANY_EXHDR(key); HStore *out = palloc(VARSIZE(hs)); char *bufs, *bufd, *ptrd; HEntry *es, *ed; int i; int count = HS_COUNT(hs); int outcount = 0; SET_VARSIZE(out, VARSIZE(hs)); HS_SETCOUNT(out, count); /* temporary! */ bufs = STRPTR(hs); es = ARRPTR(hs); bufd = ptrd = STRPTR(out); ed = ARRPTR(out); for (i = 0; i < count; ++i) { int len = HS_KEYLEN(es, i); char *ptrs = HS_KEY(es, bufs, i); if (!(len == keylen && memcmp(ptrs, keyptr, keylen) == 0)) { int vallen = HS_VALLEN(es, i); HS_COPYITEM(ed, bufd, ptrd, ptrs, len, vallen, HS_VALISNULL(es, i)); ++outcount; } } HS_FINALIZE(out, outcount, bufd, ptrd); PG_RETURN_POINTER(out); }
Datum avals(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); Datum *d; ArrayType *a; HEntry *ptr = ARRPTR(hs); char *base = STRPTR(hs); d = (Datum *) palloc(sizeof(Datum) * (hs->size + 1)); while (ptr - ARRPTR(hs) < hs->size) { int vallen = (ptr->valisnull) ? 0 : ptr->vallen; text *item = (text *) palloc(VARHDRSZ + vallen); SET_VARSIZE(item, VARHDRSZ + vallen); memcpy(VARDATA(item), base + ptr->pos + ptr->keylen, vallen); d[ptr - ARRPTR(hs)] = PointerGetDatum(item); ptr++; } a = construct_array( d, hs->size, TEXTOID, -1, false, 'i' ); ptr = ARRPTR(hs); while (ptr - ARRPTR(hs) < hs->size) { pfree(DatumGetPointer(d[ptr - ARRPTR(hs)])); ptr++; } pfree(d); PG_FREE_IF_COPY(hs, 0); PG_RETURN_POINTER(a); }
Datum hstore_to_json(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); StringInfoData tmp, dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2)); initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); escape_json(&dst, tmp.data); appendStringInfoString(&dst, ": "); if (HS_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); else { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); escape_json(&dst, tmp.data); } if (i + 1 != count) appendStringInfoString(&dst, ", "); } appendStringInfoChar(&dst, '}'); PG_RETURN_TEXT_P(cstring_to_text(dst.data)); }
Datum hstore_hash(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); Datum hval = hash_any((unsigned char *) VARDATA(hs), VARSIZE(hs) - VARHDRSZ); /* * this is the only place in the code that cares whether the overall * varlena size exactly matches the true data size; this assertion should * be maintained by all the other code, but we make it explicit here. */ Assert(VARSIZE(hs) == (HS_COUNT(hs) != 0 ? CALCDATASIZE(HS_COUNT(hs), HSE_ENDPOS(ARRPTR(hs)[2 * HS_COUNT(hs) - 1])) : HSHRDSIZE)); PG_FREE_IF_COPY(hs, 0); PG_RETURN_DATUM(hval); }
Datum fetchval(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); text *key = PG_GETARG_TEXT_P(1); HEntry *entry; text *out; if ((entry = findkey(hs, VARDATA(key), VARSIZE(key) - VARHDRSZ)) == NULL || entry->valisnull) { PG_FREE_IF_COPY(hs, 0); PG_FREE_IF_COPY(key, 1); PG_RETURN_NULL(); } out = palloc(VARHDRSZ + entry->vallen); memcpy(VARDATA(out), STRPTR(hs) + entry->pos + entry->keylen, entry->vallen); SET_VARSIZE(out, VARHDRSZ + entry->vallen); PG_FREE_IF_COPY(hs, 0); PG_FREE_IF_COPY(key, 1); PG_RETURN_POINTER(out); }