Commit 7f0dccae authored by Heikki Linnakangas's avatar Heikki Linnakangas

Turn much of the btree_gin macros into real functions.

This makes the functions much nicer to read and edit, and also makes
debugging easier.
parent e7032610
...@@ -17,34 +17,30 @@ ...@@ -17,34 +17,30 @@
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
typedef struct TypeInfo
{
bool is_varlena;
Datum (*leftmostvalue) (void);
Datum (*typecmp) (FunctionCallInfo);
} TypeInfo;
typedef struct QueryInfo typedef struct QueryInfo
{ {
StrategyNumber strategy; StrategyNumber strategy;
Datum datum; Datum datum;
bool is_varlena;
Datum (*typecmp) (FunctionCallInfo);
} QueryInfo; } QueryInfo;
#define GIN_EXTRACT_VALUE(type) \
PG_FUNCTION_INFO_V1(gin_extract_value_##type); \ /*** GIN support functions shared by all datatypes ***/
Datum \
gin_extract_value_##type(PG_FUNCTION_ARGS) \ static Datum
{ \ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
Datum datum = PG_GETARG_DATUM(0); \ {
int32 *nentries = (int32 *) PG_GETARG_POINTER(1); \ Datum datum = PG_GETARG_DATUM(0);
Datum *entries = (Datum *) palloc(sizeof(Datum)); \ int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
\ Datum *entries = (Datum *) palloc(sizeof(Datum));
if ( TypeInfo_##type.is_varlena ) \
datum = PointerGetDatum(PG_DETOAST_DATUM(datum)); \ if (is_varlena)
entries[0] = datum; \ datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
*nentries = 1; \ entries[0] = datum;
\ *nentries = 1;
PG_RETURN_POINTER(entries); \
PG_RETURN_POINTER(entries);
} }
/* /*
...@@ -55,49 +51,51 @@ gin_extract_value_##type(PG_FUNCTION_ARGS) \ ...@@ -55,49 +51,51 @@ gin_extract_value_##type(PG_FUNCTION_ARGS) \
* key, and work forward until the supplied query datum (which must be * key, and work forward until the supplied query datum (which must be
* sent along inside the QueryInfo structure). * sent along inside the QueryInfo structure).
*/ */
static Datum
gin_btree_extract_query(FunctionCallInfo fcinfo,
bool is_varlena,
Datum (*leftmostvalue) (void),
Datum (*typecmp) (FunctionCallInfo))
{
Datum datum = PG_GETARG_DATUM(0);
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
StrategyNumber strategy = PG_GETARG_UINT16(2);
bool **partialmatch = (bool **) PG_GETARG_POINTER(3);
Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
Datum *entries = (Datum *) palloc(sizeof(Datum));
QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo));
bool *ptr_partialmatch;
*nentries = 1;
ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
*ptr_partialmatch = false;
if (is_varlena)
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
data->strategy = strategy;
data->datum = datum;
data->is_varlena = is_varlena;
data->typecmp = typecmp;
*extra_data = (Pointer *) palloc(sizeof(Pointer));
**extra_data = (Pointer) data;
switch (strategy)
{
case BTLessStrategyNumber:
case BTLessEqualStrategyNumber:
entries[0] = leftmostvalue();
*ptr_partialmatch = true;
break;
case BTGreaterEqualStrategyNumber:
case BTGreaterStrategyNumber:
*ptr_partialmatch = true;
case BTEqualStrategyNumber:
entries[0] = datum;
break;
default:
elog(ERROR, "unrecognized strategy number: %d", strategy);
}
#define GIN_EXTRACT_QUERY(type) \ PG_RETURN_POINTER(entries);
PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
Datum \
gin_extract_query_##type(PG_FUNCTION_ARGS) \
{ \
Datum datum = PG_GETARG_DATUM(0); \
int32 *nentries = (int32 *) PG_GETARG_POINTER(1); \
StrategyNumber strategy = PG_GETARG_UINT16(2); \
bool **partialmatch = (bool **) PG_GETARG_POINTER(3); \
Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); \
Datum *entries = (Datum *) palloc(sizeof(Datum)); \
QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo)); \
bool *ptr_partialmatch; \
\
*nentries = 1; \
ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool)); \
*ptr_partialmatch = false; \
if ( TypeInfo_##type.is_varlena ) \
datum = PointerGetDatum(PG_DETOAST_DATUM(datum)); \
data->strategy = strategy; \
data->datum = datum; \
*extra_data = (Pointer *) palloc(sizeof(Pointer)); \
**extra_data = (Pointer) data; \
\
switch (strategy) \
{ \
case BTLessStrategyNumber: \
case BTLessEqualStrategyNumber: \
entries[0] = TypeInfo_##type.leftmostvalue(); \
*ptr_partialmatch = true; \
break; \
case BTGreaterEqualStrategyNumber: \
case BTGreaterStrategyNumber: \
*ptr_partialmatch = true; \
case BTEqualStrategyNumber: \
entries[0] = datum; \
break; \
default: \
elog(ERROR, "unrecognized strategy number: %d", strategy); \
} \
\
PG_RETURN_POINTER(entries); \
} }
/* /*
...@@ -105,78 +103,70 @@ gin_extract_query_##type(PG_FUNCTION_ARGS) \ ...@@ -105,78 +103,70 @@ gin_extract_query_##type(PG_FUNCTION_ARGS) \
* strategy it is a left-most value. So, use original datum from QueryInfo * strategy it is a left-most value. So, use original datum from QueryInfo
* to decide to stop scanning or not. Datum b is always from index. * to decide to stop scanning or not. Datum b is always from index.
*/ */
#define GIN_COMPARE_PREFIX(type) \ static Datum
PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
Datum \ {
gin_compare_prefix_##type(PG_FUNCTION_ARGS) \ Datum a = PG_GETARG_DATUM(0);
{ \ Datum b = PG_GETARG_DATUM(1);
Datum a = PG_GETARG_DATUM(0); \ QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3);
Datum b = PG_GETARG_DATUM(1); \ int32 res,
QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3); \ cmp;
int32 res, \
cmp; \ cmp = DatumGetInt32(DirectFunctionCall2Coll(
\ data->typecmp,
cmp = DatumGetInt32(DirectFunctionCall2Coll( \ PG_GET_COLLATION(),
TypeInfo_##type.typecmp, \ (data->strategy == BTLessStrategyNumber ||
PG_GET_COLLATION(), \ data->strategy == BTLessEqualStrategyNumber)
(data->strategy == BTLessStrategyNumber || \ ? data->datum : a,
data->strategy == BTLessEqualStrategyNumber) \ b));
? data->datum : a, \
b)); \ switch (data->strategy)
\ {
switch (data->strategy) \ case BTLessStrategyNumber:
{ \ /* If original datum > indexed one then return match */
case BTLessStrategyNumber: \ if (cmp > 0)
/* If original datum > indexed one then return match */ \ res = 0;
if (cmp > 0) \ else
res = 0; \ res = 1;
else \ break;
res = 1; \ case BTLessEqualStrategyNumber:
break; \ /* The same except equality */
case BTLessEqualStrategyNumber: \ if (cmp >= 0)
/* The same except equality */ \ res = 0;
if (cmp >= 0) \ else
res = 0; \ res = 1;
else \ break;
res = 1; \ case BTEqualStrategyNumber:
break; \ if (cmp != 0)
case BTEqualStrategyNumber: \ res = 1;
if (cmp != 0) \ else
res = 1; \ res = 0;
else \ break;
res = 0; \ case BTGreaterEqualStrategyNumber:
break; \ /* If original datum <= indexed one then return match */
case BTGreaterEqualStrategyNumber: \ if (cmp <= 0)
/* If original datum <= indexed one then return match */ \ res = 0;
if (cmp <= 0) \ else
res = 0; \ res = 1;
else \ break;
res = 1; \ case BTGreaterStrategyNumber:
break; \ /* If original datum <= indexed one then return match */
case BTGreaterStrategyNumber: \ /* If original datum == indexed one then continue scan */
/* If original datum <= indexed one then return match */ \ if (cmp < 0)
/* If original datum == indexed one then continue scan */ \ res = 0;
if (cmp < 0) \ else if (cmp == 0)
res = 0; \ res = -1;
else if (cmp == 0) \ else
res = -1; \ res = 1;
else \ break;
res = 1; \ default:
break; \ elog(ERROR, "unrecognized strategy number: %d",
default: \ data->strategy);
elog(ERROR, "unrecognized strategy number: %d", \ res = 0;
data->strategy); \ }
res = 0; \
} \
\
PG_RETURN_INT32(res); \
}
#define GIN_SUPPORT(type) \
GIN_EXTRACT_VALUE(type) \
GIN_EXTRACT_QUERY(type) \
GIN_COMPARE_PREFIX(type)
PG_RETURN_INT32(res);
}
PG_FUNCTION_INFO_V1(gin_btree_consistent); PG_FUNCTION_INFO_V1(gin_btree_consistent);
Datum Datum
...@@ -188,23 +178,45 @@ gin_btree_consistent(PG_FUNCTION_ARGS) ...@@ -188,23 +178,45 @@ gin_btree_consistent(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
} }
/*** GIN_SUPPORT macro defines the datatype specific functions ***/
#define GIN_SUPPORT(type, is_varlena, leftmostvalue, typecmp) \
PG_FUNCTION_INFO_V1(gin_extract_value_##type); \
Datum \
gin_extract_value_##type(PG_FUNCTION_ARGS) \
{ \
return gin_btree_extract_value(fcinfo, is_varlena); \
} \
PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
Datum \
gin_extract_query_##type(PG_FUNCTION_ARGS) \
{ \
return gin_btree_extract_query(fcinfo, \
is_varlena, leftmostvalue, typecmp); \
} \
PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \
Datum \
gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
{ \
return gin_btree_compare_prefix(fcinfo); \
}
/*** Datatype specifications ***/
static Datum static Datum
leftmostvalue_int2(void) leftmostvalue_int2(void)
{ {
return Int16GetDatum(SHRT_MIN); return Int16GetDatum(SHRT_MIN);
} }
static TypeInfo TypeInfo_int2 = {false, leftmostvalue_int2, btint2cmp}; GIN_SUPPORT(int2, false, leftmostvalue_int2, btint2cmp)
GIN_SUPPORT(int2)
static Datum static Datum
leftmostvalue_int4(void) leftmostvalue_int4(void)
{ {
return Int32GetDatum(INT_MIN); return Int32GetDatum(INT_MIN);
} }
static TypeInfo TypeInfo_int4 = {false, leftmostvalue_int4, btint4cmp}; GIN_SUPPORT(int4, false, leftmostvalue_int4, btint4cmp)
GIN_SUPPORT(int4)
static Datum static Datum
leftmostvalue_int8(void) leftmostvalue_int8(void)
...@@ -214,27 +226,21 @@ leftmostvalue_int8(void) ...@@ -214,27 +226,21 @@ leftmostvalue_int8(void)
*/ */
return Int64GetDatum(SEQ_MINVALUE); return Int64GetDatum(SEQ_MINVALUE);
} }
static TypeInfo TypeInfo_int8 = {false, leftmostvalue_int8, btint8cmp}; GIN_SUPPORT(int8, false, leftmostvalue_int8, btint8cmp)
GIN_SUPPORT(int8)
static Datum static Datum
leftmostvalue_float4(void) leftmostvalue_float4(void)
{ {
return Float4GetDatum(-get_float4_infinity()); return Float4GetDatum(-get_float4_infinity());
} }
static TypeInfo TypeInfo_float4 = {false, leftmostvalue_float4, btfloat4cmp}; GIN_SUPPORT(float4, false, leftmostvalue_float4, btfloat4cmp)
GIN_SUPPORT(float4)
static Datum static Datum
leftmostvalue_float8(void) leftmostvalue_float8(void)
{ {
return Float8GetDatum(-get_float8_infinity()); return Float8GetDatum(-get_float8_infinity());
} }
static TypeInfo TypeInfo_float8 = {false, leftmostvalue_float8, btfloat8cmp}; GIN_SUPPORT(float8, false, leftmostvalue_float8, btfloat8cmp)
GIN_SUPPORT(float8)
static Datum static Datum
leftmostvalue_money(void) leftmostvalue_money(void)
...@@ -244,40 +250,30 @@ leftmostvalue_money(void) ...@@ -244,40 +250,30 @@ leftmostvalue_money(void)
*/ */
return Int64GetDatum(SEQ_MINVALUE); return Int64GetDatum(SEQ_MINVALUE);
} }
static TypeInfo TypeInfo_money = {false, leftmostvalue_money, cash_cmp}; GIN_SUPPORT(money, false, leftmostvalue_money, cash_cmp)
GIN_SUPPORT(money)
static Datum static Datum
leftmostvalue_oid(void) leftmostvalue_oid(void)
{ {
return ObjectIdGetDatum(0); return ObjectIdGetDatum(0);
} }
static TypeInfo TypeInfo_oid = {false, leftmostvalue_oid, btoidcmp}; GIN_SUPPORT(oid, false, leftmostvalue_oid, btoidcmp)
GIN_SUPPORT(oid)
static Datum static Datum
leftmostvalue_timestamp(void) leftmostvalue_timestamp(void)
{ {
return TimestampGetDatum(DT_NOBEGIN); return TimestampGetDatum(DT_NOBEGIN);
} }
static TypeInfo TypeInfo_timestamp = {false, leftmostvalue_timestamp, timestamp_cmp}; GIN_SUPPORT(timestamp, false, leftmostvalue_timestamp, timestamp_cmp)
GIN_SUPPORT(timestamp)
static TypeInfo TypeInfo_timestamptz = {false, leftmostvalue_timestamp, timestamp_cmp}; GIN_SUPPORT(timestamptz, false, leftmostvalue_timestamp, timestamp_cmp)
GIN_SUPPORT(timestamptz)
static Datum static Datum
leftmostvalue_time(void) leftmostvalue_time(void)
{ {
return TimeADTGetDatum(0); return TimeADTGetDatum(0);
} }
static TypeInfo TypeInfo_time = {false, leftmostvalue_time, time_cmp}; GIN_SUPPORT(time, false, leftmostvalue_time, time_cmp)
GIN_SUPPORT(time)
static Datum static Datum
leftmostvalue_timetz(void) leftmostvalue_timetz(void)
...@@ -289,18 +285,14 @@ leftmostvalue_timetz(void) ...@@ -289,18 +285,14 @@ leftmostvalue_timetz(void)
return TimeTzADTPGetDatum(v); return TimeTzADTPGetDatum(v);
} }
static TypeInfo TypeInfo_timetz = {false, leftmostvalue_timetz, timetz_cmp}; GIN_SUPPORT(timetz, false, leftmostvalue_timetz, timetz_cmp)
GIN_SUPPORT(timetz)
static Datum static Datum
leftmostvalue_date(void) leftmostvalue_date(void)
{ {
return DateADTGetDatum(DATEVAL_NOBEGIN); return DateADTGetDatum(DATEVAL_NOBEGIN);
} }
static TypeInfo TypeInfo_date = {false, leftmostvalue_date, date_cmp}; GIN_SUPPORT(date, false, leftmostvalue_date, date_cmp)
GIN_SUPPORT(date)
static Datum static Datum
leftmostvalue_interval(void) leftmostvalue_interval(void)
...@@ -312,9 +304,7 @@ leftmostvalue_interval(void) ...@@ -312,9 +304,7 @@ leftmostvalue_interval(void)
v->month = 0; v->month = 0;
return IntervalPGetDatum(v); return IntervalPGetDatum(v);
} }
static TypeInfo TypeInfo_interval = {false, leftmostvalue_interval, interval_cmp}; GIN_SUPPORT(interval, false, leftmostvalue_interval, interval_cmp)
GIN_SUPPORT(interval)
static Datum static Datum
leftmostvalue_macaddr(void) leftmostvalue_macaddr(void)
...@@ -323,9 +313,7 @@ leftmostvalue_macaddr(void) ...@@ -323,9 +313,7 @@ leftmostvalue_macaddr(void)
return MacaddrPGetDatum(v); return MacaddrPGetDatum(v);
} }
static TypeInfo TypeInfo_macaddr = {false, leftmostvalue_macaddr, macaddr_cmp}; GIN_SUPPORT(macaddr, false, leftmostvalue_macaddr, macaddr_cmp)
GIN_SUPPORT(macaddr)
static Datum static Datum
leftmostvalue_inet(void) leftmostvalue_inet(void)
...@@ -335,35 +323,25 @@ leftmostvalue_inet(void) ...@@ -335,35 +323,25 @@ leftmostvalue_inet(void)
ObjectIdGetDatum(0), ObjectIdGetDatum(0),
Int32GetDatum(-1)); Int32GetDatum(-1));
} }
static TypeInfo TypeInfo_inet = {true, leftmostvalue_inet, network_cmp}; GIN_SUPPORT(inet, true, leftmostvalue_inet, network_cmp)
GIN_SUPPORT(inet)
static TypeInfo TypeInfo_cidr = {true, leftmostvalue_inet, network_cmp};
GIN_SUPPORT(cidr) GIN_SUPPORT(cidr, true, leftmostvalue_inet, network_cmp)
static Datum static Datum
leftmostvalue_text(void) leftmostvalue_text(void)
{ {
return PointerGetDatum(cstring_to_text_with_len("", 0)); return PointerGetDatum(cstring_to_text_with_len("", 0));
} }
static TypeInfo TypeInfo_text = {true, leftmostvalue_text, bttextcmp}; GIN_SUPPORT(text, true, leftmostvalue_text, bttextcmp)
GIN_SUPPORT(text)
static Datum static Datum
leftmostvalue_char(void) leftmostvalue_char(void)
{ {
return CharGetDatum(SCHAR_MIN); return CharGetDatum(SCHAR_MIN);
} }
static TypeInfo TypeInfo_char = {false, leftmostvalue_char, btcharcmp}; GIN_SUPPORT(char, false, leftmostvalue_char, btcharcmp)
GIN_SUPPORT(char)
static TypeInfo TypeInfo_bytea = {true, leftmostvalue_text, byteacmp}; GIN_SUPPORT(bytea, true, leftmostvalue_text, byteacmp)
GIN_SUPPORT(bytea)
static Datum static Datum
leftmostvalue_bit(void) leftmostvalue_bit(void)
...@@ -373,9 +351,7 @@ leftmostvalue_bit(void) ...@@ -373,9 +351,7 @@ leftmostvalue_bit(void)
ObjectIdGetDatum(0), ObjectIdGetDatum(0),
Int32GetDatum(-1)); Int32GetDatum(-1));
} }
static TypeInfo TypeInfo_bit = {true, leftmostvalue_bit, bitcmp}; GIN_SUPPORT(bit, true, leftmostvalue_bit, bitcmp)
GIN_SUPPORT(bit)
static Datum static Datum
leftmostvalue_varbit(void) leftmostvalue_varbit(void)
...@@ -385,9 +361,7 @@ leftmostvalue_varbit(void) ...@@ -385,9 +361,7 @@ leftmostvalue_varbit(void)
ObjectIdGetDatum(0), ObjectIdGetDatum(0),
Int32GetDatum(-1)); Int32GetDatum(-1));
} }
static TypeInfo TypeInfo_varbit = {true, leftmostvalue_varbit, bitcmp}; GIN_SUPPORT(varbit, true, leftmostvalue_varbit, bitcmp)
GIN_SUPPORT(varbit)
/* /*
* Numeric type hasn't a real left-most value, so we use PointerGetDatum(NULL) * Numeric type hasn't a real left-most value, so we use PointerGetDatum(NULL)
...@@ -431,7 +405,4 @@ leftmostvalue_numeric(void) ...@@ -431,7 +405,4 @@ leftmostvalue_numeric(void)
{ {
return PointerGetDatum(NULL); return PointerGetDatum(NULL);
} }
GIN_SUPPORT(numeric, true, leftmostvalue_numeric, gin_numeric_cmp)
static TypeInfo TypeInfo_numeric = {true, leftmostvalue_numeric, gin_numeric_cmp};
GIN_SUPPORT(numeric)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment