mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
754148d81f
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
136 lines
2.7 KiB
C
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);
|
|
}
|
|
|