Navigation Menu

Skip to content

Commit

Permalink
Support index only scan
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Oct 4, 2015
1 parent ec21237 commit 7598568
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 1 deletion.
8 changes: 8 additions & 0 deletions pgroonga--0.9.0--1.0.0.sql
@@ -0,0 +1,8 @@
CREATE FUNCTION pgroonga.canreturn(internal)
RETURNS internal
AS 'MODULE_PATHNAME', 'pgroonga_canreturn'
LANGUAGE C;

UPDATE pg_catalog.pg_am
SET amcanreturn = 'pgroonga.canreturn'
WHERE amname = 'pgroonga';
206 changes: 206 additions & 0 deletions pgroonga.c
Expand Up @@ -124,6 +124,7 @@ typedef PGrnBuildStateData *PGrnBuildState;

typedef struct PGrnScanOpaqueData
{
Relation index;
slist_node node;
Oid dataTableID;
struct
Expand Down Expand Up @@ -184,6 +185,7 @@ PG_FUNCTION_INFO_V1(pgroonga_build);
PG_FUNCTION_INFO_V1(pgroonga_buildempty);
PG_FUNCTION_INFO_V1(pgroonga_bulkdelete);
PG_FUNCTION_INFO_V1(pgroonga_vacuumcleanup);
PG_FUNCTION_INFO_V1(pgroonga_canreturn);
PG_FUNCTION_INFO_V1(pgroonga_costestimate);
PG_FUNCTION_INFO_V1(pgroonga_options);

Expand Down Expand Up @@ -828,6 +830,130 @@ PGrnConvertDatum(Datum datum, Oid typeID, grn_obj *buffer)
}
}

static Datum
PGrnConvertToDatumArrayType(grn_obj *vector, Oid typeID)
{
Oid elementTypeID;
int i, n;
Datum *values;

if (typeID == VARCHARARRAYOID)
elementTypeID = VARCHAROID;
else
elementTypeID = TEXTOID;

n = grn_vector_size(ctx, vector);
if (n == 0)
PG_RETURN_POINTER(construct_empty_array(elementTypeID));

values = palloc(sizeof(Datum) * n);
for (i = 0; i < n; i++)
{
const char *element;
unsigned int elementSize;
text *value;

elementSize = grn_vector_get_element(ctx, vector, i,
&element,
NULL,
NULL);
value = cstring_to_text_with_len(element, elementSize);
values[i] = PointerGetDatum(value);
}

{
int dims[1];
int lbs[1];

dims[0] = n;
lbs[0] = 1;
PG_RETURN_POINTER(construct_md_array(values, NULL,
1, dims, lbs,
elementTypeID,
-1, false, 'i'));
}
}

static Datum
PGrnConvertToDatum(grn_obj *value, Oid typeID)
{
switch (typeID)
{
case BOOLOID:
PG_RETURN_BOOL(GRN_BOOL_VALUE(value));
break;
case INT2OID:
PG_RETURN_INT16(GRN_INT16_VALUE(value));
break;
case INT4OID:
PG_RETURN_INT32(GRN_INT32_VALUE(value));
break;
case INT8OID:
PG_RETURN_INT64(GRN_INT64_VALUE(value));
break;
case FLOAT4OID:
PG_RETURN_FLOAT4(GRN_FLOAT_VALUE(value));
break;
case FLOAT8OID:
PG_RETURN_FLOAT8(GRN_FLOAT_VALUE(value));
break;
case TIMESTAMPOID:
case TIMESTAMPTZOID:
{
int64 grnTime;
int64 sec;
int64 usec;
pg_time_t unixTime;
TimestampTz timestamp;

grnTime = GRN_TIME_VALUE(value);
GRN_TIME_UNPACK(grnTime, sec, usec);
unixTime = sec;
timestamp = time_t_to_timestamptz(unixTime);
#ifdef HAVE_INT64_TIMESTAMP
timestamp += usec;
#else
timestamp += ((double) used) / USECS_PER_SEC;
#endif
if (typeID == TIMESTAMPOID)
PG_RETURN_TIMESTAMP(timestamp);
else
PG_RETURN_TIMESTAMPTZ(timestamp);
break;
}
case TEXTOID:
case XMLOID:
{
text *text = cstring_to_text_with_len(GRN_TEXT_VALUE(value),
GRN_TEXT_LEN(value));
PG_RETURN_TEXT_P(text);
break;
}
case VARCHAROID:
{
text *text = cstring_to_text_with_len(GRN_TEXT_VALUE(value),
GRN_TEXT_LEN(value));
PG_RETURN_VARCHAR_P((VarChar *) text);
break;
}
#ifdef NOT_USED
case POINTOID:
/* GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT; */
break;
#endif
case VARCHARARRAYOID:
case TEXTARRAYOID:
return PGrnConvertToDatumArrayType(value, typeID);
break;
default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("pgroonga: unsupported datum type: %u",
typeID)));
break;
}
}

#ifdef JSONBOID

static const unsigned int PGRN_JSON_GENERATE_PATH_IS_ABSOLUTE = 1 << 0;
Expand Down Expand Up @@ -2685,6 +2811,7 @@ PGrnScanOpaqueInitPrimaryKey(PGrnScanOpaque so, Relation index)
static void
PGrnScanOpaqueInit(PGrnScanOpaque so, Relation index)
{
so->index = index;
so->dataTableID = index->rd_index->indrelid;
PGrnScanOpaqueInitPrimaryKey(so, index);
so->sourcesTable = PGrnLookupSourcesTable(index, ERROR);
Expand Down Expand Up @@ -3544,6 +3671,57 @@ PGrnEnsureCursorOpened(IndexScanDesc scan, ScanDirection dir)
}
}

static void
PGrnGetTupleFillIndexTuple(PGrnScanOpaque so,
IndexScanDesc scan)
{
TupleDesc desc;
Datum *values;
bool *isNulls;
grn_id recordID;
unsigned int i;

desc = RelationGetDescr(so->index);
scan->xs_itupdesc = desc;

values = palloc(sizeof(Datum) * desc->natts);
isNulls = palloc(sizeof(bool) * desc->natts);

recordID = so->currentID;
if (so->sorted)
{
GRN_BULK_REWIND(&buffer);
grn_obj_get_value(ctx, so->sorted, recordID, &buffer);
recordID = GRN_RECORD_VALUE(&buffer);
}
if (so->searched)
{
grn_table_get_key(ctx, so->searched, recordID,
&recordID, sizeof(grn_id));
}

for (i = 0; i < desc->natts; i++)
{
Form_pg_attribute attribute = desc->attrs[i];
NameData *name;
grn_obj *dataColumn;

name = &(attribute->attname);
dataColumn = PGrnLookupColumn(so->sourcesTable, name->data, ERROR);
GRN_BULK_REWIND(&buffer);
grn_obj_get_value(ctx, dataColumn, recordID, &buffer);
values[i] = PGrnConvertToDatum(&buffer, attribute->atttypid);
isNulls[i] = false;
grn_obj_unlink(ctx, dataColumn);
}

scan->xs_itup = index_form_tuple(scan->xs_itupdesc,
values,
isNulls);

pfree(values);
pfree(isNulls);
}

/**
* pgroonga.gettuple() -- amgettuple
Expand Down Expand Up @@ -3589,6 +3767,9 @@ pgroonga_gettuple(PG_FUNCTION_ARGS)
grn_obj_get_value(ctx, so->ctidAccessor, so->currentID, &ctidBuffer);
scan->xs_ctup.t_self = UInt64ToCtid(GRN_UINT64_VALUE(&ctidBuffer));

if (scan->xs_want_itup)
PGrnGetTupleFillIndexTuple(so, scan);

PG_RETURN_BOOL(true);
}

Expand Down Expand Up @@ -4185,6 +4366,31 @@ pgroonga_vacuumcleanup(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(stats);
}

/**
* pgroonga.canreturn() -- amcanreturn
*/
Datum
pgroonga_canreturn(PG_FUNCTION_ARGS)
{
#ifdef JSONBOID
Relation index = (Relation) PG_GETARG_POINTER(0);
TupleDesc desc;
unsigned int i;

desc = RelationGetDescr(index);
for (i = 0; i < desc->natts; i++)
{
Form_pg_attribute attribute = desc->attrs[i];
if (attribute->atttypid == JSONBOID)
{
PG_RETURN_BOOL(false);
}
}
#endif

PG_RETURN_BOOL(true);
}

/**
* pgroonga.costestimate() -- amcostestimate
*/
Expand Down
1 change: 1 addition & 0 deletions pgroonga.h
Expand Up @@ -64,6 +64,7 @@ extern Datum PGDLLEXPORT pgroonga_build(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_buildempty(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_bulkdelete(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_vacuumcleanup(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_canreturn(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_costestimate(PG_FUNCTION_ARGS);
extern Datum PGDLLEXPORT pgroonga_options(PG_FUNCTION_ARGS);

Expand Down
6 changes: 5 additions & 1 deletion pgroonga.sql
Expand Up @@ -163,6 +163,10 @@ CREATE FUNCTION pgroonga.vacuumcleanup(internal)
RETURNS internal
AS 'MODULE_PATHNAME', 'pgroonga_vacuumcleanup'
LANGUAGE C;
CREATE FUNCTION pgroonga.canreturn(internal)
RETURNS internal
AS 'MODULE_PATHNAME', 'pgroonga_canreturn'
LANGUAGE C;
CREATE FUNCTION pgroonga.costestimate(internal)
RETURNS internal
AS 'MODULE_PATHNAME', 'pgroonga_costestimate'
Expand Down Expand Up @@ -201,7 +205,7 @@ INSERT INTO pg_catalog.pg_am VALUES(
'pgroonga.buildempty', -- ambuildempty
'pgroonga.bulkdelete', -- ambulkdelete
'pgroonga.vacuumcleanup', -- amvacuumcleanup
0, -- amcanreturn
'pgroonga.canreturn', -- amcanreturn
'pgroonga.costestimate', -- amcostestimate
'pgroonga.options' -- amoptions
);
Expand Down

0 comments on commit 7598568

Please sign in to comment.