postgresql/contrib/hstore/hstore_gin.c
Teodor Sigaev 754148d81f Add GIN support for pg_trgm. From Guillaume Smet <guillaume.smet@gmail.com>
with minor editorization by me.

Hstore improvements
* add operation hstore ? text - excat equivalent of exist()
* remove undocumented behaviour of contains operation with NULL value
* now 'key'::text=>NULL returns '"key"=>NULL' instead of NULL
* Add GIN support for contains and exist operations
* Add GiST support for exist operatiion
* improve regression tests
2007-03-14 14:21:53 +00:00

136 lines
2.7 KiB
C

#include "hstore.h"
#include "access/gin.h"
#define KEYFLAG 'K'
#define VALFLAG 'V'
#define NULLFLAG 'N'
PG_FUNCTION_INFO_V1(gin_extract_hstore);
Datum gin_extract_hstore(PG_FUNCTION_ARGS);
static text*
makeitem( char *str, int len )
{
text *item;
item = (text*)palloc( VARHDRSZ + len + 1 );
SET_VARSIZE(item, VARHDRSZ + len + 1);
if ( str && len > 0 )
memcpy( VARDATA(item)+1, str, len );
return item;
}
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);
}
PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
Datum gin_extract_hstore_query(PG_FUNCTION_ARGS);
Datum
gin_extract_hstore_query(PG_FUNCTION_ARGS)
{
StrategyNumber strategy = PG_GETARG_UINT16(2);
if ( strategy == HStoreContainsStrategyNumber )
{
PG_RETURN_DATUM( DirectFunctionCall2(
gin_extract_hstore,
PG_GETARG_DATUM(0),
PG_GETARG_DATUM(1)
));
}
else if ( strategy == HStoreExistsStrategyNumber )
{
text *item, *q = PG_GETARG_TEXT_P(0);
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
Datum *entries = NULL;
*nentries = 1;
entries = (Datum*)palloc( sizeof(Datum) );
item = makeitem( VARDATA(q), VARSIZE(q)-VARHDRSZ );
*VARDATA(item) = KEYFLAG;
entries[0] = PointerGetDatum(item);
PG_RETURN_POINTER(entries);
}
else
elog(ERROR, "Unsupported strategy number: %d", strategy);
PG_RETURN_POINTER(NULL);
}
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
Datum gin_consistent_hstore(PG_FUNCTION_ARGS);
Datum
gin_consistent_hstore(PG_FUNCTION_ARGS)
{
StrategyNumber strategy = PG_GETARG_UINT16(1);
bool res = true;
if ( strategy == HStoreContainsStrategyNumber )
{
bool *check = (bool *) PG_GETARG_POINTER(0);
HStore *query = PG_GETARG_HS(2);
int i;
for(i=0;res && i<2*query->size;i++)
if ( check[i] == false )
res = false;
}
else if ( strategy == HStoreExistsStrategyNumber )
res = true;
else
elog(ERROR, "Unsupported strategy number: %d", strategy);
PG_RETURN_BOOL(res);
}