+++ /dev/null
-#include "hstore.h"
-#include "utils/array.h"
-#include "catalog/pg_type.h"
-#include "funcapi.h"
-#include <access/heapam.h>
-#include <fmgr.h>
-
-
-static HEntry *
-findkey(HStore *hs, char *key, int keylen) {
- HEntry *StopLow = ARRPTR(hs);
- HEntry *StopHigh = StopLow + hs->size;
- HEntry *StopMiddle;
- int difference;
- char *base = STRPTR(hs);
-
- while (StopLow < StopHigh) {
- StopMiddle = StopLow + (StopHigh - StopLow) / 2;
-
- if ( StopMiddle->keylen == keylen )
- difference=strncmp(base+StopMiddle->pos, key, StopMiddle->keylen);
- else
- difference=(StopMiddle->keylen > keylen) ? 1 : -1;
-
- if (difference == 0)
- return StopMiddle;
- else if (difference < 0)
- StopLow = StopMiddle + 1;
- else
- StopHigh = StopMiddle;
- }
-
- return NULL;
-}
-
-PG_FUNCTION_INFO_V1(fetchval);
-Datum fetchval(PG_FUNCTION_ARGS);
-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);
- VARATT_SIZEP(out) = VARHDRSZ+entry->vallen;
-
- PG_FREE_IF_COPY(hs,0);
- PG_FREE_IF_COPY(key,1);
- PG_RETURN_POINTER(out);
-}
-
-PG_FUNCTION_INFO_V1(exists);
-Datum exists(PG_FUNCTION_ARGS);
-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);
-}
-
-PG_FUNCTION_INFO_V1(defined);
-Datum defined(PG_FUNCTION_ARGS);
-Datum
-defined(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 && !entry->valisnull ) ? true : false;
-
- PG_FREE_IF_COPY(hs,0);
- PG_FREE_IF_COPY(key,1);
-
- PG_RETURN_BOOL(res);
-}
-
-PG_FUNCTION_INFO_V1(delete);
-Datum delete(PG_FUNCTION_ARGS);
-Datum
-delete(PG_FUNCTION_ARGS) {
- HStore *hs = PG_GETARG_HS(0);
- text *key = PG_GETARG_TEXT_P(1);
- HStore *out = palloc(hs->len);
- char *ptrs, *ptrd;
- HEntry *es, *ed;
-
- out->len=hs->len;
- out->size=hs->size; /* temprorary! */
-
- ptrs=STRPTR(hs);
- es =ARRPTR(hs);
- ptrd=STRPTR(out);
- ed =ARRPTR(out);
-
- while( es - ARRPTR(hs) < hs->size ) {
- if ( !(es->keylen == VARSIZE(key) - VARHDRSZ && strncmp(ptrs, VARDATA(key), es->keylen)==0) ) {
- memcpy( ed, es, sizeof(HEntry) );
- memcpy( ptrd, ptrs, es->keylen + ( (es->valisnull) ? 0 : es->vallen ) );
- ed->pos = ptrd - STRPTR(out);
- ptrd += es->keylen + ( (es->valisnull) ? 0 : es->vallen );
- ed++;
- }
- ptrs += es->keylen + ( (es->valisnull) ? 0 : es->vallen );
- es++;
- }
-
- if ( ed - ARRPTR(out) != out->size ) {
- int buflen=ptrd-STRPTR(out);
- ptrd = STRPTR(out);
-
- out->size = ed - ARRPTR(out);
-
- memmove( STRPTR(out), ptrd, buflen);
- out->len = CALCDATASIZE(out->size, buflen);
- }
-
-
- PG_FREE_IF_COPY(hs,0);
- PG_FREE_IF_COPY(key,1);
-
- PG_RETURN_POINTER(out);
-}
-
-PG_FUNCTION_INFO_V1(hs_concat);
-Datum hs_concat(PG_FUNCTION_ARGS);
-Datum
-hs_concat(PG_FUNCTION_ARGS) {
- HStore *s1 = PG_GETARG_HS(0);
- HStore *s2 = PG_GETARG_HS(1);
- HStore *out = palloc( s1->len + s2->len );
- char *ps1, *ps2, *pd;
- HEntry *es1, *es2, *ed;
-
- out->len = s1->len + s2->len;
- out->size = s1->size + s2->size;
-
- ps1=STRPTR(s1);
- ps2=STRPTR(s2);
- pd=STRPTR(out);
- es1=ARRPTR(s1);
- es2=ARRPTR(s2);
- ed=ARRPTR(out);
-
- while( es1 - ARRPTR(s1) < s1->size && es2 - ARRPTR(s2) < s2->size ) {
- int difference;
- if ( es1->keylen == es2->keylen )
- difference=strncmp(ps1, ps2, es1->keylen);
- else
- difference=(es1->keylen > es2->keylen) ? 1 : -1;
-
- if ( difference == 0 ) {
- memcpy( ed, es2, sizeof(HEntry) );
- memcpy( pd, ps2, es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen ) );
- ed->pos = pd - STRPTR(out);
- pd += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- ed++;
-
- ps1 += es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen );
- es1++;
- ps2 += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- es2++;
- } else if ( difference > 0 ) {
- memcpy( ed, es2, sizeof(HEntry) );
- memcpy( pd, ps2, es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen ) );
- ed->pos = pd - STRPTR(out);
- pd += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- ed++;
-
- ps2 += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- es2++;
- } else {
- memcpy( ed, es1, sizeof(HEntry) );
- memcpy( pd, ps1, es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen ) );
- ed->pos = pd - STRPTR(out);
- pd += es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen );
- ed++;
-
- ps1 += es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen );
- es1++;
- }
- }
-
- while( es1 - ARRPTR(s1) < s1->size ) {
- memcpy( ed, es1, sizeof(HEntry) );
- memcpy( pd, ps1, es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen ) );
- ed->pos = pd - STRPTR(out);
- pd += es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen );
- ed++;
-
- ps1 += es1->keylen + ( (es1->valisnull) ? 0 : es1->vallen );
- es1++;
- }
-
- while( es2 - ARRPTR(s2) < s2->size ) {
- memcpy( ed, es2, sizeof(HEntry) );
- memcpy( pd, ps2, es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen ) );
- ed->pos = pd - STRPTR(out);
- pd += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- ed++;
-
- ps2 += es2->keylen + ( (es2->valisnull) ? 0 : es2->vallen );
- es2++;
- }
-
- if ( ed - ARRPTR(out) != out->size ) {
- int buflen=pd-STRPTR(out);
- pd = STRPTR(out);
-
- out->size = ed - ARRPTR(out);
-
- memmove( STRPTR(out), pd, buflen);
- out->len = CALCDATASIZE(out->size, buflen);
- }
-
- PG_FREE_IF_COPY(s1,0);
- PG_FREE_IF_COPY(s2,1);
-
- PG_RETURN_POINTER(out);
-}
-
-PG_FUNCTION_INFO_V1(tconvert);
-Datum tconvert(PG_FUNCTION_ARGS);
-Datum
-tconvert(PG_FUNCTION_ARGS) {
- text *key = PG_GETARG_TEXT_P(0);
- text *val = PG_GETARG_TEXT_P(1);
- int len;
- HStore *out;
-
- len=CALCDATASIZE(1, VARSIZE(key) + VARSIZE(val) - 2*VARHDRSZ);
- out = palloc(len);
- out->len=len;
- out->size=1;
-
- ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
- ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
- ARRPTR(out)->valisnull = false;
- ARRPTR(out)->pos=0;
-
- memcpy( STRPTR(out), VARDATA(key), ARRPTR(out)->keylen );
- memcpy( STRPTR(out) + ARRPTR(out)->keylen, VARDATA(val), ARRPTR(out)->vallen );
-
- PG_FREE_IF_COPY(key,0);
- PG_FREE_IF_COPY(val,1);
-
- PG_RETURN_POINTER(out);
-}
-
-PG_FUNCTION_INFO_V1(akeys);
-Datum akeys(PG_FUNCTION_ARGS);
-Datum
-akeys(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 ) {
- text *item=(text*)palloc(VARHDRSZ + ptr->keylen);
- VARATT_SIZEP(item) = VARHDRSZ+ptr->keylen;
- memcpy(VARDATA(item), base + ptr->pos, ptr->keylen);
- 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);
-}
-
-PG_FUNCTION_INFO_V1(avals);
-Datum avals(PG_FUNCTION_ARGS);
-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);
- VARATT_SIZEP(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);
-}
-
-typedef struct {
- HStore *hs;
- int i;
-} AKStore;
-
-static void
-setup_firstcall(FuncCallContext *funcctx, HStore *hs) {
- MemoryContext oldcontext;
- AKStore *st;
-
- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-
- st=(AKStore*)palloc( sizeof(AKStore) );
- st->i=0;
- st->hs = (HStore*)palloc(hs->len);
- memcpy( st->hs, hs, hs->len );
-
- funcctx->user_fctx = (void*)st;
- MemoryContextSwitchTo(oldcontext);
-}
-
-PG_FUNCTION_INFO_V1(skeys);
-Datum skeys(PG_FUNCTION_ARGS);
-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);
-
- VARATT_SIZEP(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);
-}
-
-PG_FUNCTION_INFO_V1(svals);
-Datum svals(PG_FUNCTION_ARGS);
-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);
-
- VARATT_SIZEP(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);
-}
-
-PG_FUNCTION_INFO_V1(hs_contains);
-Datum hs_contains(PG_FUNCTION_ARGS);
-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 ) {
- if ( entry->valisnull || !(
- te->vallen==entry->vallen &&
- strncmp(
- vv + entry->pos + entry->keylen,
- tv + te->pos + te->keylen,
- te->vallen ) == 0
- ) )
- res=false;
- }
- } else
- res = false;
- te++;
- }
-
- PG_FREE_IF_COPY(val,0);
- PG_FREE_IF_COPY(tmpl,1);
-
- PG_RETURN_BOOL(res);
-}
-
-PG_FUNCTION_INFO_V1(hs_contained);
-Datum hs_contained(PG_FUNCTION_ARGS);
-Datum
-hs_contained(PG_FUNCTION_ARGS) {
- PG_RETURN_DATUM( DirectFunctionCall2(
- hs_contains,
- PG_GETARG_DATUM(1),
- PG_GETARG_DATUM(0)
- ));
-}
-
-PG_FUNCTION_INFO_V1(each);
-Datum each(PG_FUNCTION_ARGS);
-Datum
-each(PG_FUNCTION_ARGS) {
- FuncCallContext *funcctx;
- AKStore *st;
-
- if (SRF_IS_FIRSTCALL()) {
- TupleDesc tupdesc;
- MemoryContext oldcontext;
- HStore *hs = PG_GETARG_HS(0);
-
- funcctx = SRF_FIRSTCALL_INIT();
- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- st=(AKStore*)palloc( sizeof(AKStore) );
- st->i=0;
- st->hs = (HStore*)palloc(hs->len);
- memcpy( st->hs, hs, hs->len );
- funcctx->user_fctx = (void*)st;
-
- tupdesc = RelationNameGetTupleDesc("hs_each");
- funcctx->slot = TupleDescGetSlot(tupdesc);
- funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
-
- MemoryContextSwitchTo(oldcontext);
- 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]);
- Datum res, dvalues[2];
- char nulls[] = {' ', ' '};
- text *item;
- HeapTuple tuple;
-
- item=(text*)palloc(VARHDRSZ + ptr->keylen);
- VARATT_SIZEP(item) = VARHDRSZ+ptr->keylen;
- memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos, ptr->keylen);
- dvalues[0] = PointerGetDatum(item);
-
- if ( ptr->valisnull ) {
- dvalues[1]=(Datum)0;
- nulls[1]='n';
- } else {
- int vallen = ptr->vallen;
-
- item=(text*)palloc(VARHDRSZ + vallen);
- VARATT_SIZEP(item) = VARHDRSZ+vallen;
- memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos + ptr->keylen, vallen);
- dvalues[1] = PointerGetDatum(item);
- }
- st->i++;
-
- tuple = heap_formtuple(funcctx->attinmeta->tupdesc, dvalues, nulls);
- res = TupleGetDatum(funcctx->slot, tuple);
-
- pfree( DatumGetPointer(dvalues[0]) );
- if ( nulls[1] != 'n' )
- pfree( DatumGetPointer(dvalues[1]) );
-
- SRF_RETURN_NEXT(funcctx, PointerGetDatum(res));
- }
-
- pfree( st->hs );
- pfree( st );
-
- SRF_RETURN_DONE(funcctx);
-}
-
-