X-Git-Url: http://www.sigaev.ru/git/gitweb.cgi?p=hstore.git;a=blobdiff_plain;f=hstore_op.c;fp=hstore_op.c;h=0000000000000000000000000000000000000000;hp=12f783cb256c3ee21cf47484baf941a292fc9d29;hb=77af220c462dd61507d6cca9b9f54ad3e102e1b6;hpb=2ebb5a0f24c70e3b6ee5ac7401eb28f804d01817 diff --git a/hstore_op.c b/hstore_op.c deleted file mode 100644 index 12f783c..0000000 --- a/hstore_op.c +++ /dev/null @@ -1,567 +0,0 @@ -#include "hstore.h" -#include "utils/array.h" -#include "catalog/pg_type.h" -#include "funcapi.h" -#include -#include - - -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); -} - -