Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Functions

hstore.h File Reference

#include "fmgr.h"
#include "utils/array.h"
Include dependency graph for hstore.h:
This graph shows which files directly or indirectly include this file:

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

HStorehstoreUpgrade (Datum orig)
int hstoreUniquePairs (Pairs *a, int32 l, int32 *buflen)
HStorehstorePairs (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)
PairshstoreArrayToPairs (ArrayType *a, int *npairs)

Define Documentation

#define ARRPTR (   x  )     ( (HEntry*) ( (HStore*)(x) + 1 ) )

Definition at line 66 of file hstore.h.

#define CALCDATASIZE (   x,
  lenstr 
)    ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
#define DatumGetHStoreP (   d  )     hstoreUpgrade(d)

Definition at line 143 of file hstore.h.

Referenced by ghstore_compress().

#define HENTRY_ISFIRST   0x80000000

Definition at line 23 of file hstore.h.

#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_ 
)
Value:
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_ 
)
Value:
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)
#define HS_FINALIZE (   hsp_,
  count_,
  buf_,
  ptr_ 
)
Value:
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_ 
)
Value:
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_)]))
#define HS_KEYLEN (   arr_,
  i_ 
)    (HSE_LEN((arr_)[2*(i_)]))
#define HS_SETCOUNT (   hsp_,
  c_ 
)    ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
#define HS_VAL (   arr_,
  str_,
  i_ 
)    ((str_) + HSE_OFF((arr_)[2*(i_)+1]))
#define HS_VALISNULL (   arr_,
  i_ 
)    (HSE_ISNULL((arr_)[2*(i_)+1]))
#define HS_VALLEN (   arr_,
  i_ 
)    (HSE_LEN((arr_)[2*(i_)+1]))
#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_  ) 
Value:
(HSE_ISFIRST(he_)   \
                      ? HSE_ENDPOS(he_) \
                      : HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))

Definition at line 32 of file hstore.h.

#define HSE_OFF (   he_  )     (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1]))

Definition at line 31 of file hstore.h.

#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_ 
)
Value:
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

Definition at line 186 of file hstore.h.

#define HSTORE_POLLUTE_NAMESPACE   1

Definition at line 182 of file hstore.h.

#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))
#define STRPTR (   x  )     ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )

Function Documentation

Pairs* hstoreArrayToPairs ( ArrayType a,
int *  npairs 
)

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;
}

HStore* hstorePairs ( Pairs pairs,
int32  pcount,
int32  buflen 
)

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;
}

int hstoreUniquePairs ( Pairs a,
int32  l,
int32 buflen 
)

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;
}

HStore* hstoreUpgrade ( Datum  orig  ) 

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;
}