#include "fmgr.h"#include "utils/array.h"

Go to the source code of this file.
Data Structures | |
| struct | HEntry |
| struct | HStore |
| struct | Pairs |
Defines | |
| #define | HENTRY_ISFIRST 0x80000000 |
| #define | HENTRY_ISNULL 0x40000000 |
| #define | HENTRY_POSMASK 0x3FFFFFFF |
| #define | HSE_ISFIRST(he_) (((he_).entry & HENTRY_ISFIRST) != 0) |
| #define | HSE_ISNULL(he_) (((he_).entry & HENTRY_ISNULL) != 0) |
| #define | HSE_ENDPOS(he_) ((he_).entry & HENTRY_POSMASK) |
| #define | HSE_OFF(he_) (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1])) |
| #define | HSE_LEN(he_) |
| #define | HSTORE_MAX_KEY_LEN 0x3FFFFFFF |
| #define | HSTORE_MAX_VALUE_LEN 0x3FFFFFFF |
| #define | HS_FLAG_NEWVERSION 0x80000000 |
| #define | HS_COUNT(hsp_) ((hsp_)->size_ & 0x0FFFFFFF) |
| #define | HS_SETCOUNT(hsp_, c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION) |
| #define | HSHRDSIZE (sizeof(HStore)) |
| #define | CALCDATASIZE(x, lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) ) |
| #define | ARRPTR(x) ( (HEntry*) ( (HStore*)(x) + 1 ) ) |
| #define | STRPTR(x) ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) ) |
| #define | HS_KEY(arr_, str_, i_) ((str_) + HSE_OFF((arr_)[2*(i_)])) |
| #define | HS_VAL(arr_, str_, i_) ((str_) + HSE_OFF((arr_)[2*(i_)+1])) |
| #define | HS_KEYLEN(arr_, i_) (HSE_LEN((arr_)[2*(i_)])) |
| #define | HS_VALLEN(arr_, i_) (HSE_LEN((arr_)[2*(i_)+1])) |
| #define | HS_VALISNULL(arr_, i_) (HSE_ISNULL((arr_)[2*(i_)+1])) |
| #define | HS_COPYITEM(dent_, dbuf_, dptr_, sptr_, klen_, vlen_, vnull_) |
| #define | HS_ADDITEM(dent_, dbuf_, dptr_, pair_) |
| #define | HS_FINALIZE(hsp_, count_, buf_, ptr_) |
| #define | HS_FIXSIZE(hsp_, count_) |
| #define | DatumGetHStoreP(d) hstoreUpgrade(d) |
| #define | PG_GETARG_HS(x) DatumGetHStoreP(PG_GETARG_DATUM(x)) |
| #define | HStoreContainsStrategyNumber 7 |
| #define | HStoreExistsStrategyNumber 9 |
| #define | HStoreExistsAnyStrategyNumber 10 |
| #define | HStoreExistsAllStrategyNumber 11 |
| #define | HStoreOldContainsStrategyNumber 13 |
| #define | HSTORE_POLLUTE_NAMESPACE 1 |
| #define | HSTORE_POLLUTE(newname_, oldname_) |
Functions | |
| HStore * | hstoreUpgrade (Datum orig) |
| int | hstoreUniquePairs (Pairs *a, int32 l, int32 *buflen) |
| HStore * | hstorePairs (Pairs *pairs, int32 pcount, int32 buflen) |
| size_t | hstoreCheckKeyLen (size_t len) |
| size_t | hstoreCheckValLen (size_t len) |
| int | hstoreFindKey (HStore *hs, int *lowbound, char *key, int keylen) |
| Pairs * | hstoreArrayToPairs (ArrayType *a, int *npairs) |
| #define CALCDATASIZE | ( | x, | ||
| lenstr | ||||
| ) | ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) ) |
Definition at line 63 of file hstore.h.
Referenced by hstore_hash(), hstorePairs(), hstoreValidNewFormat(), hstoreValidOldFormat(), make_tsvector(), to_tsvector_byid(), tsvector_concat(), tsvector_strip(), tsvector_update_trigger(), and tsvectorin().
| #define DatumGetHStoreP | ( | d | ) | hstoreUpgrade(d) |
Definition at line 143 of file hstore.h.
Referenced by ghstore_compress().
| #define HENTRY_ISNULL 0x40000000 |
Definition at line 24 of file hstore.h.
Referenced by hstoreUpgrade().
| #define HENTRY_POSMASK 0x3FFFFFFF |
Definition at line 25 of file hstore.h.
Referenced by hstoreUpgrade().
| #define HS_ADDITEM | ( | dent_, | ||
| dbuf_, | ||||
| dptr_, | ||||
| pair_ | ||||
| ) |
do { \ memcpy((dptr_), (pair_).key, (pair_).keylen); \ (dptr_) += (pair_).keylen; \ (dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \ if ((pair_).isnull) \ (dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \ | HENTRY_ISNULL); \ else \ { \ memcpy((dptr_), (pair_).val, (pair_).vallen); \ (dptr_) += (pair_).vallen; \ (dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \ } \ } while (0)
Definition at line 103 of file hstore.h.
Referenced by hstorePairs().
| #define HS_COPYITEM | ( | dent_, | ||
| dbuf_, | ||||
| dptr_, | ||||
| sptr_, | ||||
| klen_, | ||||
| vlen_, | ||||
| vnull_ | ||||
| ) |
do { \ memcpy((dptr_), (sptr_), (klen_)+(vlen_)); \ (dptr_) += (klen_)+(vlen_); \ (dent_)++->entry = ((dptr_) - (dbuf_) - (vlen_)) & HENTRY_POSMASK; \ (dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \ | ((vnull_) ? HENTRY_ISNULL : 0)); \ } while(0)
Definition at line 90 of file hstore.h.
Referenced by hstore_concat(), hstore_delete(), hstore_delete_array(), and hstore_delete_hstore().
| #define HS_COUNT | ( | hsp_ | ) | ((hsp_)->size_ & 0x0FFFFFFF) |
Definition at line 58 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_akeys(), hstore_avals(), hstore_cmp(), hstore_concat(), hstore_contains(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_hash(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_skeys(), hstore_svals(), hstore_to_array_internal(), hstore_to_json(), hstore_to_json_loose(), hstoreFindKey(), hstoreUpgrade(), and hstoreValidNewFormat().
| #define HS_FINALIZE | ( | hsp_, | ||
| count_, | ||||
| buf_, | ||||
| ptr_ | ||||
| ) |
do { \ int buflen = (ptr_) - (buf_); \ if ((count_)) \ ARRPTR(hsp_)[0].entry |= HENTRY_ISFIRST; \ if ((count_) != HS_COUNT((hsp_))) \ { \ HS_SETCOUNT((hsp_),(count_)); \ memmove(STRPTR(hsp_), (buf_), buflen); \ } \ SET_VARSIZE((hsp_), CALCDATASIZE((count_), buflen)); \ } while (0)
Definition at line 120 of file hstore.h.
Referenced by hstore_concat(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), and hstorePairs().
| #define HS_FIXSIZE | ( | hsp_, | ||
| count_ | ||||
| ) |
do { \ int bl = (count_) ? HSE_ENDPOS(ARRPTR(hsp_)[2*(count_)-1]) : 0; \ SET_VARSIZE((hsp_), CALCDATASIZE((count_),bl)); \ } while (0)
Definition at line 134 of file hstore.h.
Referenced by hstore_concat(), hstore_delete_array(), hstore_delete_hstore(), and hstoreUpgrade().
| #define HS_FLAG_NEWVERSION 0x80000000 |
Definition at line 56 of file hstore.h.
Referenced by hstoreUpgrade(), hstoreValidNewFormat(), and hstoreValidOldFormat().
| #define HS_KEY | ( | arr_, | ||
| str_, | ||||
| i_ | ||||
| ) | ((str_) + HSE_OFF((arr_)[2*(i_)])) |
Definition at line 70 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_akeys(), hstore_concat(), hstore_contains(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_out(), hstore_send(), hstore_skeys(), hstore_to_array_internal(), hstore_to_json(), hstore_to_json_loose(), and hstoreFindKey().
| #define HS_KEYLEN | ( | arr_, | ||
| i_ | ||||
| ) | (HSE_LEN((arr_)[2*(i_)])) |
Definition at line 72 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_akeys(), hstore_concat(), hstore_contains(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_out(), hstore_send(), hstore_skeys(), hstore_to_array_internal(), hstore_to_json(), hstore_to_json_loose(), hstoreFindKey(), and hstoreValidNewFormat().
| #define HS_SETCOUNT | ( | hsp_, | ||
| c_ | ||||
| ) | ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION) |
Definition at line 59 of file hstore.h.
Referenced by hstore_concat(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstorePairs(), and hstoreUpgrade().
| #define HS_VAL | ( | arr_, | ||
| str_, | ||||
| i_ | ||||
| ) | ((str_) + HSE_OFF((arr_)[2*(i_)+1])) |
Definition at line 71 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_avals(), hstore_contains(), hstore_delete_hstore(), hstore_each(), hstore_fetchval(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_slice_to_array(), hstore_slice_to_hstore(), hstore_svals(), hstore_to_array_internal(), hstore_to_json(), and hstore_to_json_loose().
| #define HS_VALISNULL | ( | arr_, | ||
| i_ | ||||
| ) | (HSE_ISNULL((arr_)[2*(i_)+1])) |
Definition at line 74 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_avals(), hstore_concat(), hstore_contains(), hstore_defined(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_fetchval(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_slice_to_array(), hstore_slice_to_hstore(), hstore_svals(), hstore_to_array_internal(), hstore_to_json(), and hstore_to_json_loose().
| #define HS_VALLEN | ( | arr_, | ||
| i_ | ||||
| ) | (HSE_LEN((arr_)[2*(i_)+1])) |
Definition at line 73 of file hstore.h.
Referenced by ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), hstore_avals(), hstore_concat(), hstore_contains(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_fetchval(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_slice_to_array(), hstore_slice_to_hstore(), hstore_svals(), hstore_to_array_internal(), hstore_to_json(), and hstore_to_json_loose().
| #define HSE_ENDPOS | ( | he_ | ) | ((he_).entry & HENTRY_POSMASK) |
Definition at line 30 of file hstore.h.
Referenced by hstore_cmp(), hstore_hash(), and hstoreValidNewFormat().
| #define HSE_ISFIRST | ( | he_ | ) | (((he_).entry & HENTRY_ISFIRST) != 0) |
Definition at line 28 of file hstore.h.
Referenced by hstoreUpgrade(), and hstoreValidNewFormat().
| #define HSE_ISNULL | ( | he_ | ) | (((he_).entry & HENTRY_ISNULL) != 0) |
Definition at line 29 of file hstore.h.
Referenced by hstore_cmp(), and hstoreValidNewFormat().
| #define HSE_LEN | ( | he_ | ) |
(HSE_ISFIRST(he_) \ ? HSE_ENDPOS(he_) \ : HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))
| #define HSE_OFF | ( | he_ | ) | (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1])) |
| #define HSHRDSIZE (sizeof(HStore)) |
Definition at line 62 of file hstore.h.
Referenced by hstore_concat(), and hstore_hash().
| #define HSTORE_MAX_KEY_LEN 0x3FFFFFFF |
Definition at line 41 of file hstore.h.
Referenced by hstoreCheckKeyLen().
| #define HSTORE_MAX_VALUE_LEN 0x3FFFFFFF |
Definition at line 42 of file hstore.h.
Referenced by hstoreCheckValLen().
| #define HSTORE_POLLUTE | ( | newname_, | ||
| oldname_ | ||||
| ) |
PG_FUNCTION_INFO_V1(oldname_); \ Datum oldname_(PG_FUNCTION_ARGS); \ Datum newname_(PG_FUNCTION_ARGS); \ Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \ extern int no_such_variable
| #define HStoreContainsStrategyNumber 7 |
Definition at line 171 of file hstore.h.
Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().
| #define HStoreExistsAllStrategyNumber 11 |
Definition at line 174 of file hstore.h.
Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().
| #define HStoreExistsAnyStrategyNumber 10 |
Definition at line 173 of file hstore.h.
Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().
| #define HStoreExistsStrategyNumber 9 |
Definition at line 172 of file hstore.h.
Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().
| #define HStoreOldContainsStrategyNumber 13 |
Definition at line 175 of file hstore.h.
Referenced by ghstore_consistent().
| #define PG_GETARG_HS | ( | x | ) | DatumGetHStoreP(PG_GETARG_DATUM(x)) |
Definition at line 145 of file hstore.h.
Referenced by ghstore_consistent(), gin_extract_hstore(), hstore_akeys(), hstore_avals(), hstore_cmp(), hstore_concat(), hstore_contains(), hstore_defined(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_exists(), hstore_exists_all(), hstore_exists_any(), hstore_fetchval(), hstore_hash(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_skeys(), hstore_slice_to_array(), hstore_slice_to_hstore(), hstore_svals(), hstore_to_array(), hstore_to_json(), hstore_to_json_loose(), and hstore_to_matrix().
| #define STRPTR | ( | x | ) | ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) ) |
Definition at line 67 of file hstore.h.
Referenced by cnt_length(), compute_tsvector_stats(), find_wordentry(), ghstore_compress(), ghstore_consistent(), gin_extract_hstore(), gin_extract_tsvector(), gtsvector_compress(), hstore_akeys(), hstore_avals(), hstore_cmp(), hstore_concat(), hstore_contains(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), hstore_each(), hstore_fetchval(), hstore_out(), hstore_populate_record(), hstore_send(), hstore_skeys(), hstore_slice_to_array(), hstore_slice_to_hstore(), hstore_svals(), hstore_to_array_internal(), hstore_to_json(), hstore_to_json_loose(), hstoreFindKey(), hstorePairs(), insertStatEntry(), make_tsvector(), silly_cmp_tsvector(), ts_match_vq(), tsvector_concat(), tsvector_strip(), tsvectorin(), tsvectorout(), tsvectorrecv(), and tsvectorsend().
Definition at line 73 of file hstore_op.c.
References deconstruct_array(), hstoreUniquePairs(), i, Pairs::isnull, Pairs::key, Pairs::keylen, Pairs::needfree, palloc(), TEXTOID, Pairs::val, Pairs::vallen, VARDATA, and VARSIZE.
Referenced by hstore_delete_array(), hstore_exists_all(), hstore_exists_any(), and hstore_slice_to_hstore().
{
Datum *key_datums;
bool *key_nulls;
int key_count;
Pairs *key_pairs;
int bufsiz;
int i,
j;
deconstruct_array(a,
TEXTOID, -1, false, 'i',
&key_datums, &key_nulls, &key_count);
if (key_count == 0)
{
*npairs = 0;
return NULL;
}
key_pairs = palloc(sizeof(Pairs) * key_count);
for (i = 0, j = 0; i < key_count; i++)
{
if (!key_nulls[i])
{
key_pairs[j].key = VARDATA(key_datums[i]);
key_pairs[j].keylen = VARSIZE(key_datums[i]) - VARHDRSZ;
key_pairs[j].val = NULL;
key_pairs[j].vallen = 0;
key_pairs[j].needfree = 0;
key_pairs[j].isnull = 1;
j++;
}
}
*npairs = hstoreUniquePairs(key_pairs, j, &bufsiz);
return key_pairs;
}
| size_t hstoreCheckKeyLen | ( | size_t | len | ) |
Definition at line 351 of file hstore_io.c.
References ereport, errcode(), errmsg(), ERROR, and HSTORE_MAX_KEY_LEN.
Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().
{
if (len > HSTORE_MAX_KEY_LEN)
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("string too long for hstore key")));
return len;
}
| size_t hstoreCheckValLen | ( | size_t | len | ) |
Definition at line 361 of file hstore_io.c.
References ereport, errcode(), errmsg(), ERROR, and HSTORE_MAX_VALUE_LEN.
Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().
{
if (len > HSTORE_MAX_VALUE_LEN)
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("string too long for hstore value")));
return len;
}
| int hstoreFindKey | ( | HStore * | hs, | |
| int * | lowbound, | |||
| char * | key, | |||
| int | keylen | |||
| ) |
Definition at line 36 of file hstore_op.c.
References ARRPTR, HS_COUNT, HS_KEY, HS_KEYLEN, memcmp(), and STRPTR.
Referenced by hstore_contains(), hstore_defined(), hstore_exists(), hstore_exists_all(), hstore_exists_any(), hstore_fetchval(), hstore_populate_record(), hstore_slice_to_array(), and hstore_slice_to_hstore().
{
HEntry *entries = ARRPTR(hs);
int stopLow = lowbound ? *lowbound : 0;
int stopHigh = HS_COUNT(hs);
int stopMiddle;
char *base = STRPTR(hs);
while (stopLow < stopHigh)
{
int difference;
stopMiddle = stopLow + (stopHigh - stopLow) / 2;
if (HS_KEYLEN(entries, stopMiddle) == keylen)
difference = memcmp(HS_KEY(entries, base, stopMiddle), key, keylen);
else
difference = (HS_KEYLEN(entries, stopMiddle) > keylen) ? 1 : -1;
if (difference == 0)
{
if (lowbound)
*lowbound = stopMiddle + 1;
return stopMiddle;
}
else if (difference < 0)
stopLow = stopMiddle + 1;
else
stopHigh = stopMiddle;
}
if (lowbound)
*lowbound = stopLow;
return -1;
}
Definition at line 372 of file hstore_io.c.
References ARRPTR, buf, CALCDATASIZE, HS_ADDITEM, HS_FINALIZE, HS_SETCOUNT, i, palloc(), SET_VARSIZE, and STRPTR.
Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_in(), hstore_recv(), and hstore_slice_to_hstore().
{
HStore *out;
HEntry *entry;
char *ptr;
char *buf;
int32 len;
int32 i;
len = CALCDATASIZE(pcount, buflen);
out = palloc(len);
SET_VARSIZE(out, len);
HS_SETCOUNT(out, pcount);
if (pcount == 0)
return out;
entry = ARRPTR(out);
buf = ptr = STRPTR(out);
for (i = 0; i < pcount; i++)
HS_ADDITEM(entry, buf, ptr, pairs[i]);
HS_FINALIZE(out, pcount, buf, ptr);
return out;
}
Definition at line 309 of file hstore_io.c.
References comparePairs(), Pairs::isnull, Pairs::key, Pairs::keylen, memcmp(), Pairs::needfree, pfree(), qsort, Pairs::val, and Pairs::vallen.
Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_in(), hstore_recv(), and hstoreArrayToPairs().
{
Pairs *ptr,
*res;
*buflen = 0;
if (l < 2)
{
if (l == 1)
*buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
return l;
}
qsort((void *) a, l, sizeof(Pairs), comparePairs);
ptr = a + 1;
res = a;
while (ptr - a < l)
{
if (ptr->keylen == res->keylen &&
memcmp(ptr->key, res->key, res->keylen) == 0)
{
if (ptr->needfree)
{
pfree(ptr->key);
pfree(ptr->val);
}
}
else
{
*buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
res++;
memcpy(res, ptr, sizeof(Pairs));
}
ptr++;
}
*buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
return res + 1 - a;
}
Definition at line 236 of file hstore_compat.c.
References ARRPTR, DatumGetPointer, elog, HEntry::entry, ERROR, HENTRY_ISNULL, HENTRY_POSMASK, HS_COUNT, HS_FIXSIZE, HS_FLAG_NEWVERSION, HS_SETCOUNT, HSE_ISFIRST, hstoreValidNewFormat(), hstoreValidOldFormat(), i, HOldEntry::keylen, PG_DETOAST_DATUM, PG_DETOAST_DATUM_COPY, HOldEntry::pos, HStore::size_, HOldEntry::valisnull, HOldEntry::vallen, VARSIZE, and WARNING.
{
HStore *hs = (HStore *) PG_DETOAST_DATUM(orig);
int valid_new;
int valid_old;
bool writable;
/* Return immediately if no conversion needed */
if ((hs->size_ & HS_FLAG_NEWVERSION) ||
hs->size_ == 0 ||
(VARSIZE(hs) < 32768 && HSE_ISFIRST((ARRPTR(hs)[0]))))
return hs;
valid_new = hstoreValidNewFormat(hs);
valid_old = hstoreValidOldFormat(hs);
/* Do we have a writable copy? */
writable = ((void *) hs != (void *) DatumGetPointer(orig));
if (!valid_old || hs->size_ == 0)
{
if (valid_new)
{
/*
* force the "new version" flag and the correct varlena length,
* but only if we have a writable copy already (which we almost
* always will, since short new-format values won't come through
* here)
*/
if (writable)
{
HS_SETCOUNT(hs, HS_COUNT(hs));
HS_FIXSIZE(hs, HS_COUNT(hs));
}
return hs;
}
else
{
elog(ERROR, "invalid hstore value found");
}
}
/*
* this is the tricky edge case. It is only possible in some quite extreme
* cases (the hstore must have had a lot of wasted padding space at the
* end). But the only way a "new" hstore value could get here is if we're
* upgrading in place from a pre-release version of hstore-new (NOT
* contrib/hstore), so we work off the following assumptions: 1. If you're
* moving from old contrib/hstore to hstore-new, you're required to fix up
* any potential conflicts first, e.g. by running ALTER TABLE ... USING
* col::text::hstore; on all hstore columns before upgrading. 2. If you're
* moving from old contrib/hstore to new contrib/hstore, then "new" values
* are impossible here 3. If you're moving from pre-release hstore-new to
* hstore-new, then "old" values are impossible here 4. If you're moving
* from pre-release hstore-new to new contrib/hstore, you're not doing so
* as an in-place upgrade, so there is no issue So the upshot of all this
* is that we can treat all the edge cases as "new" if we're being built
* as hstore-new, and "old" if we're being built as contrib/hstore.
*
* XXX the WARNING can probably be downgraded to DEBUG1 once this has been
* beta-tested. But for now, it would be very useful to know if anyone can
* actually reach this case in a non-contrived setting.
*/
if (valid_new)
{
#if HSTORE_IS_HSTORE_NEW
elog(WARNING, "ambiguous hstore value resolved as hstore-new");
/*
* force the "new version" flag and the correct varlena length, but
* only if we have a writable copy already (which we almost always
* will, since short new-format values won't come through here)
*/
if (writable)
{
HS_SETCOUNT(hs, HS_COUNT(hs));
HS_FIXSIZE(hs, HS_COUNT(hs));
}
return hs;
#else
elog(WARNING, "ambiguous hstore value resolved as hstore-old");
#endif
}
/*
* must have an old-style value. Overwrite it in place as a new-style one,
* making sure we have a writable copy first.
*/
if (!writable)
hs = (HStore *) PG_DETOAST_DATUM_COPY(orig);
{
int count = hs->size_;
HEntry *new_entries = ARRPTR(hs);
HOldEntry *old_entries = (HOldEntry *) ARRPTR(hs);
int i;
for (i = 0; i < count; ++i)
{
uint32 pos = old_entries[i].pos;
uint32 keylen = old_entries[i].keylen;
uint32 vallen = old_entries[i].vallen;
bool isnull = old_entries[i].valisnull;
if (isnull)
vallen = 0;
new_entries[2 * i].entry = (pos + keylen) & HENTRY_POSMASK;
new_entries[2 * i + 1].entry = (((pos + keylen + vallen) & HENTRY_POSMASK)
| ((isnull) ? HENTRY_ISNULL : 0));
}
if (count)
new_entries[0].entry |= HENTRY_ISFIRST;
HS_SETCOUNT(hs, count);
HS_FIXSIZE(hs, count);
}
return hs;
}
1.7.1