mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Add cross-type comparisons to contrib/btree_gin.
Extend the infrastructure in btree_gin.c to permit cross-type operators, and add the code to support them for the int2, int4, and int8 opclasses. (To keep this patch digestible, I left the other datatypes for a separate patch.) This improves the usability of btree_gin indexes by allowing them to support the same set of queries that a regular btree index does. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Arseniy Mukhin <arseniy.mukhin.dev@gmail.com> Discussion: https://postgr.es/m/262624.1738460652@sss.pgh.pa.us
This commit is contained in:
@ -7,7 +7,7 @@ OBJS = \
|
|||||||
|
|
||||||
EXTENSION = btree_gin
|
EXTENSION = btree_gin
|
||||||
DATA = btree_gin--1.0.sql btree_gin--1.0--1.1.sql btree_gin--1.1--1.2.sql \
|
DATA = btree_gin--1.0.sql btree_gin--1.0--1.1.sql btree_gin--1.1--1.2.sql \
|
||||||
btree_gin--1.2--1.3.sql
|
btree_gin--1.2--1.3.sql btree_gin--1.3--1.4.sql
|
||||||
PGFILEDESC = "btree_gin - B-tree equivalent GIN operator classes"
|
PGFILEDESC = "btree_gin - B-tree equivalent GIN operator classes"
|
||||||
|
|
||||||
REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \
|
REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \
|
||||||
|
63
contrib/btree_gin/btree_gin--1.3--1.4.sql
Normal file
63
contrib/btree_gin/btree_gin--1.3--1.4.sql
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* contrib/btree_gin/btree_gin--1.3--1.4.sql */
|
||||||
|
|
||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "ALTER EXTENSION btree_gin UPDATE TO '1.4'" to load this file. \quit
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Cross-type operator support is new in 1.4. We only need to worry
|
||||||
|
-- about this for cross-type operators that exist in core.
|
||||||
|
--
|
||||||
|
-- Because the opclass extractQuery and consistent methods don't directly
|
||||||
|
-- get any information about the datatype of the RHS value, we have to
|
||||||
|
-- encode that in the operator strategy numbers. The strategy numbers
|
||||||
|
-- are the operator's normal btree strategy (1-5) plus 16 times a code
|
||||||
|
-- for the RHS datatype.
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER OPERATOR FAMILY int2_ops USING gin
|
||||||
|
ADD
|
||||||
|
-- Code 1: RHS is int4
|
||||||
|
OPERATOR 0x11 < (int2, int4),
|
||||||
|
OPERATOR 0x12 <= (int2, int4),
|
||||||
|
OPERATOR 0x13 = (int2, int4),
|
||||||
|
OPERATOR 0x14 >= (int2, int4),
|
||||||
|
OPERATOR 0x15 > (int2, int4),
|
||||||
|
-- Code 2: RHS is int8
|
||||||
|
OPERATOR 0x21 < (int2, int8),
|
||||||
|
OPERATOR 0x22 <= (int2, int8),
|
||||||
|
OPERATOR 0x23 = (int2, int8),
|
||||||
|
OPERATOR 0x24 >= (int2, int8),
|
||||||
|
OPERATOR 0x25 > (int2, int8)
|
||||||
|
;
|
||||||
|
|
||||||
|
ALTER OPERATOR FAMILY int4_ops USING gin
|
||||||
|
ADD
|
||||||
|
-- Code 1: RHS is int2
|
||||||
|
OPERATOR 0x11 < (int4, int2),
|
||||||
|
OPERATOR 0x12 <= (int4, int2),
|
||||||
|
OPERATOR 0x13 = (int4, int2),
|
||||||
|
OPERATOR 0x14 >= (int4, int2),
|
||||||
|
OPERATOR 0x15 > (int4, int2),
|
||||||
|
-- Code 2: RHS is int8
|
||||||
|
OPERATOR 0x21 < (int4, int8),
|
||||||
|
OPERATOR 0x22 <= (int4, int8),
|
||||||
|
OPERATOR 0x23 = (int4, int8),
|
||||||
|
OPERATOR 0x24 >= (int4, int8),
|
||||||
|
OPERATOR 0x25 > (int4, int8)
|
||||||
|
;
|
||||||
|
|
||||||
|
ALTER OPERATOR FAMILY int8_ops USING gin
|
||||||
|
ADD
|
||||||
|
-- Code 1: RHS is int2
|
||||||
|
OPERATOR 0x11 < (int8, int2),
|
||||||
|
OPERATOR 0x12 <= (int8, int2),
|
||||||
|
OPERATOR 0x13 = (int8, int2),
|
||||||
|
OPERATOR 0x14 >= (int8, int2),
|
||||||
|
OPERATOR 0x15 > (int8, int2),
|
||||||
|
-- Code 2: RHS is int4
|
||||||
|
OPERATOR 0x21 < (int8, int4),
|
||||||
|
OPERATOR 0x22 <= (int8, int4),
|
||||||
|
OPERATOR 0x23 = (int8, int4),
|
||||||
|
OPERATOR 0x24 >= (int8, int4),
|
||||||
|
OPERATOR 0x25 > (int8, int4)
|
||||||
|
;
|
@ -19,14 +19,29 @@ PG_MODULE_MAGIC_EXT(
|
|||||||
.version = PG_VERSION
|
.version = PG_VERSION
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our opclasses use the same strategy numbers as btree (1-5) for same-type
|
||||||
|
* comparison operators. For cross-type comparison operators, the
|
||||||
|
* low 4 bits of our strategy numbers are the btree strategy number,
|
||||||
|
* and the upper bits are a code for the right-hand-side data type.
|
||||||
|
*/
|
||||||
|
#define BTGIN_GET_BTREE_STRATEGY(strat) ((strat) & 0x0F)
|
||||||
|
#define BTGIN_GET_RHS_TYPE_CODE(strat) ((strat) >> 4)
|
||||||
|
|
||||||
|
/* extra data passed from gin_btree_extract_query to gin_btree_compare_prefix */
|
||||||
typedef struct QueryInfo
|
typedef struct QueryInfo
|
||||||
{
|
{
|
||||||
StrategyNumber strategy;
|
StrategyNumber strategy; /* operator strategy number */
|
||||||
Datum datum;
|
Datum orig_datum; /* original query (comparison) datum */
|
||||||
bool is_varlena;
|
Datum entry_datum; /* datum we reported as the entry value */
|
||||||
Datum (*typecmp) (FunctionCallInfo);
|
PGFunction typecmp; /* appropriate btree comparison function */
|
||||||
} QueryInfo;
|
} QueryInfo;
|
||||||
|
|
||||||
|
typedef Datum (*btree_gin_convert_function) (Datum input);
|
||||||
|
|
||||||
|
typedef Datum (*btree_gin_leftmost_function) (void);
|
||||||
|
|
||||||
|
|
||||||
/*** GIN support functions shared by all datatypes ***/
|
/*** GIN support functions shared by all datatypes ***/
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
@ -36,6 +51,7 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
|
|||||||
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
||||||
Datum *entries = (Datum *) palloc(sizeof(Datum));
|
Datum *entries = (Datum *) palloc(sizeof(Datum));
|
||||||
|
|
||||||
|
/* Ensure that values stored in the index are not toasted */
|
||||||
if (is_varlena)
|
if (is_varlena)
|
||||||
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
|
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
|
||||||
entries[0] = datum;
|
entries[0] = datum;
|
||||||
@ -44,19 +60,12 @@ gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
|
|||||||
PG_RETURN_POINTER(entries);
|
PG_RETURN_POINTER(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* For BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, and
|
|
||||||
* BTEqualStrategyNumber we want to start the index scan at the
|
|
||||||
* supplied query datum, and work forward. For BTLessStrategyNumber
|
|
||||||
* and BTLessEqualStrategyNumber, we need to start at the leftmost
|
|
||||||
* key, and work forward until the supplied query datum (which must be
|
|
||||||
* sent along inside the QueryInfo structure).
|
|
||||||
*/
|
|
||||||
static Datum
|
static Datum
|
||||||
gin_btree_extract_query(FunctionCallInfo fcinfo,
|
gin_btree_extract_query(FunctionCallInfo fcinfo,
|
||||||
bool is_varlena,
|
btree_gin_leftmost_function leftmostvalue,
|
||||||
Datum (*leftmostvalue) (void),
|
const bool *rhs_is_varlena,
|
||||||
Datum (*typecmp) (FunctionCallInfo))
|
const btree_gin_convert_function *cvt_fns,
|
||||||
|
const PGFunction *cmp_fns)
|
||||||
{
|
{
|
||||||
Datum datum = PG_GETARG_DATUM(0);
|
Datum datum = PG_GETARG_DATUM(0);
|
||||||
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
||||||
@ -65,21 +74,40 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
|
|||||||
Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
|
Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
|
||||||
Datum *entries = (Datum *) palloc(sizeof(Datum));
|
Datum *entries = (Datum *) palloc(sizeof(Datum));
|
||||||
QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo));
|
QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo));
|
||||||
bool *ptr_partialmatch;
|
bool *ptr_partialmatch = (bool *) palloc(sizeof(bool));
|
||||||
|
int btree_strat,
|
||||||
|
rhs_code;
|
||||||
|
|
||||||
*nentries = 1;
|
/*
|
||||||
ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
|
* Extract the btree strategy code and the RHS data type code from the
|
||||||
*ptr_partialmatch = false;
|
* given strategy number.
|
||||||
if (is_varlena)
|
*/
|
||||||
|
btree_strat = BTGIN_GET_BTREE_STRATEGY(strategy);
|
||||||
|
rhs_code = BTGIN_GET_RHS_TYPE_CODE(strategy);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detoast the comparison datum. This isn't necessary for correctness,
|
||||||
|
* but it can save repeat detoastings within the comparison function.
|
||||||
|
*/
|
||||||
|
if (rhs_is_varlena[rhs_code])
|
||||||
datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
|
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)
|
/* Prep single comparison key with possible partial-match flag */
|
||||||
|
*nentries = 1;
|
||||||
|
*partialmatch = ptr_partialmatch;
|
||||||
|
*ptr_partialmatch = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, and
|
||||||
|
* BTEqualStrategyNumber we want to start the index scan at the supplied
|
||||||
|
* query datum, and work forward. For BTLessStrategyNumber and
|
||||||
|
* BTLessEqualStrategyNumber, we need to start at the leftmost key, and
|
||||||
|
* work forward until the supplied query datum (which we'll send along
|
||||||
|
* inside the QueryInfo structure). Use partial match rules except for
|
||||||
|
* BTEqualStrategyNumber without a conversion function. (If there is a
|
||||||
|
* conversion function, comparison to the entry value is not trustworthy.)
|
||||||
|
*/
|
||||||
|
switch (btree_strat)
|
||||||
{
|
{
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
case BTLessEqualStrategyNumber:
|
case BTLessEqualStrategyNumber:
|
||||||
@ -91,75 +119,106 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
|
|||||||
*ptr_partialmatch = true;
|
*ptr_partialmatch = true;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case BTEqualStrategyNumber:
|
case BTEqualStrategyNumber:
|
||||||
entries[0] = datum;
|
/* If we have a conversion function, apply it */
|
||||||
|
if (cvt_fns && cvt_fns[rhs_code])
|
||||||
|
{
|
||||||
|
entries[0] = (*cvt_fns[rhs_code]) (datum);
|
||||||
|
*ptr_partialmatch = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
entries[0] = datum;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unrecognized strategy number: %d", strategy);
|
elog(ERROR, "unrecognized strategy number: %d", strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill "extra" data */
|
||||||
|
data->strategy = strategy;
|
||||||
|
data->orig_datum = datum;
|
||||||
|
data->entry_datum = entries[0];
|
||||||
|
data->typecmp = cmp_fns[rhs_code];
|
||||||
|
*extra_data = (Pointer *) palloc(sizeof(Pointer));
|
||||||
|
**extra_data = (Pointer) data;
|
||||||
|
|
||||||
PG_RETURN_POINTER(entries);
|
PG_RETURN_POINTER(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Datum a is a value from extract_query method and for BTLess*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static Datum
|
static Datum
|
||||||
gin_btree_compare_prefix(FunctionCallInfo fcinfo)
|
gin_btree_compare_prefix(FunctionCallInfo fcinfo)
|
||||||
{
|
{
|
||||||
Datum a = PG_GETARG_DATUM(0);
|
Datum partial_key PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_DATUM(0);
|
||||||
Datum b = PG_GETARG_DATUM(1);
|
Datum key = PG_GETARG_DATUM(1);
|
||||||
QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3);
|
QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3);
|
||||||
int32 res,
|
int32 res,
|
||||||
cmp;
|
cmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* partial_key is only an approximation to the real comparison value,
|
||||||
|
* especially if it's a leftmost value. We can get an accurate answer by
|
||||||
|
* doing a possibly-cross-type comparison to the real comparison value.
|
||||||
|
* (Note that partial_key and key are of the indexed datatype while
|
||||||
|
* orig_datum is of the query operator's RHS datatype.)
|
||||||
|
*
|
||||||
|
* But just to be sure that things are what we expect, let's assert that
|
||||||
|
* partial_key is indeed what gin_btree_extract_query reported, so that
|
||||||
|
* we'll notice if anyone ever changes the core code in a way that breaks
|
||||||
|
* our assumptions.
|
||||||
|
*/
|
||||||
|
Assert(partial_key == data->entry_datum);
|
||||||
|
|
||||||
cmp = DatumGetInt32(CallerFInfoFunctionCall2(data->typecmp,
|
cmp = DatumGetInt32(CallerFInfoFunctionCall2(data->typecmp,
|
||||||
fcinfo->flinfo,
|
fcinfo->flinfo,
|
||||||
PG_GET_COLLATION(),
|
PG_GET_COLLATION(),
|
||||||
(data->strategy == BTLessStrategyNumber ||
|
data->orig_datum,
|
||||||
data->strategy == BTLessEqualStrategyNumber)
|
key));
|
||||||
? data->datum : a,
|
|
||||||
b));
|
|
||||||
|
|
||||||
switch (data->strategy)
|
/*
|
||||||
|
* Convert the comparison result to the correct thing for the search
|
||||||
|
* operator strategy. When dealing with cross-type comparisons, an
|
||||||
|
* imprecise entry datum could lead GIN to start the scan just before the
|
||||||
|
* first possible match, so we must continue the scan if the current index
|
||||||
|
* entry doesn't satisfy the search condition for >= and > cases. But if
|
||||||
|
* that happens in an = search we can stop, because an imprecise entry
|
||||||
|
* datum means that the search value is unrepresentable in the indexed
|
||||||
|
* data type, so that there will be no exact matches.
|
||||||
|
*/
|
||||||
|
switch (BTGIN_GET_BTREE_STRATEGY(data->strategy))
|
||||||
{
|
{
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
/* If original datum > indexed one then return match */
|
/* If original datum > indexed one then return match */
|
||||||
if (cmp > 0)
|
if (cmp > 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
res = 1;
|
res = 1; /* end scan */
|
||||||
break;
|
break;
|
||||||
case BTLessEqualStrategyNumber:
|
case BTLessEqualStrategyNumber:
|
||||||
/* The same except equality */
|
/* If original datum >= indexed one then return match */
|
||||||
if (cmp >= 0)
|
if (cmp >= 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
res = 1;
|
res = 1; /* end scan */
|
||||||
break;
|
break;
|
||||||
case BTEqualStrategyNumber:
|
case BTEqualStrategyNumber:
|
||||||
if (cmp != 0)
|
/* If original datum = indexed one then return match */
|
||||||
res = 1;
|
/* See above about why we can end scan when cmp < 0 */
|
||||||
else
|
if (cmp == 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
|
else
|
||||||
|
res = 1; /* end scan */
|
||||||
break;
|
break;
|
||||||
case BTGreaterEqualStrategyNumber:
|
case BTGreaterEqualStrategyNumber:
|
||||||
/* If original datum <= indexed one then return match */
|
/* If original datum <= indexed one then return match */
|
||||||
if (cmp <= 0)
|
if (cmp <= 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
res = 1;
|
res = -1; /* keep scanning */
|
||||||
break;
|
break;
|
||||||
case BTGreaterStrategyNumber:
|
case BTGreaterStrategyNumber:
|
||||||
/* If original datum <= indexed one then return match */
|
/* If original datum < indexed one then return match */
|
||||||
/* If original datum == indexed one then continue scan */
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
res = 0;
|
res = 0;
|
||||||
else if (cmp == 0)
|
|
||||||
res = -1;
|
|
||||||
else
|
else
|
||||||
res = 1;
|
res = -1; /* keep scanning */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unrecognized strategy number: %d",
|
elog(ERROR, "unrecognized strategy number: %d",
|
||||||
@ -182,19 +241,20 @@ gin_btree_consistent(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/*** GIN_SUPPORT macro defines the datatype specific functions ***/
|
/*** GIN_SUPPORT macro defines the datatype specific functions ***/
|
||||||
|
|
||||||
#define GIN_SUPPORT(type, is_varlena, leftmostvalue, typecmp) \
|
#define GIN_SUPPORT(type, leftmostvalue, is_varlena, cvtfns, cmpfns) \
|
||||||
PG_FUNCTION_INFO_V1(gin_extract_value_##type); \
|
PG_FUNCTION_INFO_V1(gin_extract_value_##type); \
|
||||||
Datum \
|
Datum \
|
||||||
gin_extract_value_##type(PG_FUNCTION_ARGS) \
|
gin_extract_value_##type(PG_FUNCTION_ARGS) \
|
||||||
{ \
|
{ \
|
||||||
return gin_btree_extract_value(fcinfo, is_varlena); \
|
return gin_btree_extract_value(fcinfo, is_varlena[0]); \
|
||||||
} \
|
} \
|
||||||
PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
|
PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
|
||||||
Datum \
|
Datum \
|
||||||
gin_extract_query_##type(PG_FUNCTION_ARGS) \
|
gin_extract_query_##type(PG_FUNCTION_ARGS) \
|
||||||
{ \
|
{ \
|
||||||
return gin_btree_extract_query(fcinfo, \
|
return gin_btree_extract_query(fcinfo, \
|
||||||
is_varlena, leftmostvalue, typecmp); \
|
leftmostvalue, is_varlena, \
|
||||||
|
cvtfns, cmpfns); \
|
||||||
} \
|
} \
|
||||||
PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \
|
PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \
|
||||||
Datum \
|
Datum \
|
||||||
@ -206,13 +266,66 @@ gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
|
|||||||
|
|
||||||
/*** Datatype specifications ***/
|
/*** Datatype specifications ***/
|
||||||
|
|
||||||
|
/* Function to produce the least possible value of the indexed datatype */
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_int2(void)
|
leftmostvalue_int2(void)
|
||||||
{
|
{
|
||||||
return Int16GetDatum(SHRT_MIN);
|
return Int16GetDatum(SHRT_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(int2, false, leftmostvalue_int2, btint2cmp)
|
/*
|
||||||
|
* For cross-type support, we must provide conversion functions that produce
|
||||||
|
* a Datum of the indexed datatype, since GIN requires the "entry" datums to
|
||||||
|
* be of that type. If an exact conversion is not possible, produce a value
|
||||||
|
* that will lead GIN to find the first index entry that is greater than
|
||||||
|
* or equal to the actual comparison value. (But rounding down is OK, so
|
||||||
|
* sometimes we might find an index entry that's just less than the
|
||||||
|
* comparison value.)
|
||||||
|
*
|
||||||
|
* For integer values, it's sufficient to clamp the input to be in-range.
|
||||||
|
*
|
||||||
|
* Note: for out-of-range input values, we could in theory detect that the
|
||||||
|
* search condition matches all or none of the index, and avoid a useless
|
||||||
|
* index descent in the latter case. Such searches are probably rare though,
|
||||||
|
* so we don't contort this code enough to do that.
|
||||||
|
*/
|
||||||
|
static Datum
|
||||||
|
cvt_int4_int2(Datum input)
|
||||||
|
{
|
||||||
|
int32 val = DatumGetInt32(input);
|
||||||
|
|
||||||
|
val = Max(val, SHRT_MIN);
|
||||||
|
val = Min(val, SHRT_MAX);
|
||||||
|
return Int16GetDatum((int16) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Datum
|
||||||
|
cvt_int8_int2(Datum input)
|
||||||
|
{
|
||||||
|
int64 val = DatumGetInt64(input);
|
||||||
|
|
||||||
|
val = Max(val, SHRT_MIN);
|
||||||
|
val = Min(val, SHRT_MAX);
|
||||||
|
return Int16GetDatum((int16) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RHS-type-is-varlena flags, conversion and comparison function arrays,
|
||||||
|
* indexed by high bits of the operator strategy number. A NULL in the
|
||||||
|
* conversion function array indicates that no conversion is needed, which
|
||||||
|
* will always be the case for the zero'th entry. Note that the cross-type
|
||||||
|
* comparison functions should be the ones with the indexed datatype second.
|
||||||
|
*/
|
||||||
|
static const bool int2_rhs_is_varlena[] =
|
||||||
|
{false, false, false};
|
||||||
|
|
||||||
|
static const btree_gin_convert_function int2_cvt_fns[] =
|
||||||
|
{NULL, cvt_int4_int2, cvt_int8_int2};
|
||||||
|
|
||||||
|
static const PGFunction int2_cmp_fns[] =
|
||||||
|
{btint2cmp, btint42cmp, btint82cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(int2, leftmostvalue_int2, int2_rhs_is_varlena, int2_cvt_fns, int2_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_int4(void)
|
leftmostvalue_int4(void)
|
||||||
@ -220,7 +333,34 @@ leftmostvalue_int4(void)
|
|||||||
return Int32GetDatum(INT_MIN);
|
return Int32GetDatum(INT_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(int4, false, leftmostvalue_int4, btint4cmp)
|
static Datum
|
||||||
|
cvt_int2_int4(Datum input)
|
||||||
|
{
|
||||||
|
int16 val = DatumGetInt16(input);
|
||||||
|
|
||||||
|
return Int32GetDatum((int32) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Datum
|
||||||
|
cvt_int8_int4(Datum input)
|
||||||
|
{
|
||||||
|
int64 val = DatumGetInt64(input);
|
||||||
|
|
||||||
|
val = Max(val, INT_MIN);
|
||||||
|
val = Min(val, INT_MAX);
|
||||||
|
return Int32GetDatum((int32) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool int4_rhs_is_varlena[] =
|
||||||
|
{false, false, false};
|
||||||
|
|
||||||
|
static const btree_gin_convert_function int4_cvt_fns[] =
|
||||||
|
{NULL, cvt_int2_int4, cvt_int8_int4};
|
||||||
|
|
||||||
|
static const PGFunction int4_cmp_fns[] =
|
||||||
|
{btint4cmp, btint24cmp, btint84cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(int4, leftmostvalue_int4, int4_rhs_is_varlena, int4_cvt_fns, int4_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_int8(void)
|
leftmostvalue_int8(void)
|
||||||
@ -228,7 +368,32 @@ leftmostvalue_int8(void)
|
|||||||
return Int64GetDatum(PG_INT64_MIN);
|
return Int64GetDatum(PG_INT64_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(int8, false, leftmostvalue_int8, btint8cmp)
|
static Datum
|
||||||
|
cvt_int2_int8(Datum input)
|
||||||
|
{
|
||||||
|
int16 val = DatumGetInt16(input);
|
||||||
|
|
||||||
|
return Int64GetDatum((int64) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Datum
|
||||||
|
cvt_int4_int8(Datum input)
|
||||||
|
{
|
||||||
|
int32 val = DatumGetInt32(input);
|
||||||
|
|
||||||
|
return Int64GetDatum((int64) val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool int8_rhs_is_varlena[] =
|
||||||
|
{false, false, false};
|
||||||
|
|
||||||
|
static const btree_gin_convert_function int8_cvt_fns[] =
|
||||||
|
{NULL, cvt_int2_int8, cvt_int4_int8};
|
||||||
|
|
||||||
|
static const PGFunction int8_cmp_fns[] =
|
||||||
|
{btint8cmp, btint28cmp, btint48cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(int8, leftmostvalue_int8, int8_rhs_is_varlena, int8_cvt_fns, int8_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_float4(void)
|
leftmostvalue_float4(void)
|
||||||
@ -236,7 +401,13 @@ leftmostvalue_float4(void)
|
|||||||
return Float4GetDatum(-get_float4_infinity());
|
return Float4GetDatum(-get_float4_infinity());
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(float4, false, leftmostvalue_float4, btfloat4cmp)
|
static const bool float4_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction float4_cmp_fns[] =
|
||||||
|
{btfloat4cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(float4, leftmostvalue_float4, float4_rhs_is_varlena, NULL, float4_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_float8(void)
|
leftmostvalue_float8(void)
|
||||||
@ -244,7 +415,13 @@ leftmostvalue_float8(void)
|
|||||||
return Float8GetDatum(-get_float8_infinity());
|
return Float8GetDatum(-get_float8_infinity());
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(float8, false, leftmostvalue_float8, btfloat8cmp)
|
static const bool float8_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction float8_cmp_fns[] =
|
||||||
|
{btfloat8cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(float8, leftmostvalue_float8, float8_rhs_is_varlena, NULL, float8_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_money(void)
|
leftmostvalue_money(void)
|
||||||
@ -252,7 +429,13 @@ leftmostvalue_money(void)
|
|||||||
return Int64GetDatum(PG_INT64_MIN);
|
return Int64GetDatum(PG_INT64_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(money, false, leftmostvalue_money, cash_cmp)
|
static const bool money_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction money_cmp_fns[] =
|
||||||
|
{cash_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(money, leftmostvalue_money, money_rhs_is_varlena, NULL, money_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_oid(void)
|
leftmostvalue_oid(void)
|
||||||
@ -260,7 +443,13 @@ leftmostvalue_oid(void)
|
|||||||
return ObjectIdGetDatum(0);
|
return ObjectIdGetDatum(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(oid, false, leftmostvalue_oid, btoidcmp)
|
static const bool oid_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction oid_cmp_fns[] =
|
||||||
|
{btoidcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(oid, leftmostvalue_oid, oid_rhs_is_varlena, NULL, oid_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_timestamp(void)
|
leftmostvalue_timestamp(void)
|
||||||
@ -268,9 +457,21 @@ leftmostvalue_timestamp(void)
|
|||||||
return TimestampGetDatum(DT_NOBEGIN);
|
return TimestampGetDatum(DT_NOBEGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(timestamp, false, leftmostvalue_timestamp, timestamp_cmp)
|
static const bool timestamp_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
GIN_SUPPORT(timestamptz, false, leftmostvalue_timestamp, timestamp_cmp)
|
static const PGFunction timestamp_cmp_fns[] =
|
||||||
|
{timestamp_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(timestamp, leftmostvalue_timestamp, timestamp_rhs_is_varlena, NULL, timestamp_cmp_fns)
|
||||||
|
|
||||||
|
static const bool timestamptz_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction timestamptz_cmp_fns[] =
|
||||||
|
{timestamp_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(timestamptz, leftmostvalue_timestamp, timestamptz_rhs_is_varlena, NULL, timestamptz_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_time(void)
|
leftmostvalue_time(void)
|
||||||
@ -278,7 +479,13 @@ leftmostvalue_time(void)
|
|||||||
return TimeADTGetDatum(0);
|
return TimeADTGetDatum(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(time, false, leftmostvalue_time, time_cmp)
|
static const bool time_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction time_cmp_fns[] =
|
||||||
|
{time_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(time, leftmostvalue_time, time_rhs_is_varlena, NULL, time_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_timetz(void)
|
leftmostvalue_timetz(void)
|
||||||
@ -291,7 +498,13 @@ leftmostvalue_timetz(void)
|
|||||||
return TimeTzADTPGetDatum(v);
|
return TimeTzADTPGetDatum(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(timetz, false, leftmostvalue_timetz, timetz_cmp)
|
static const bool timetz_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction timetz_cmp_fns[] =
|
||||||
|
{timetz_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(timetz, leftmostvalue_timetz, timetz_rhs_is_varlena, NULL, timetz_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_date(void)
|
leftmostvalue_date(void)
|
||||||
@ -299,7 +512,13 @@ leftmostvalue_date(void)
|
|||||||
return DateADTGetDatum(DATEVAL_NOBEGIN);
|
return DateADTGetDatum(DATEVAL_NOBEGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(date, false, leftmostvalue_date, date_cmp)
|
static const bool date_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction date_cmp_fns[] =
|
||||||
|
{date_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(date, leftmostvalue_date, date_rhs_is_varlena, NULL, date_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_interval(void)
|
leftmostvalue_interval(void)
|
||||||
@ -311,7 +530,13 @@ leftmostvalue_interval(void)
|
|||||||
return IntervalPGetDatum(v);
|
return IntervalPGetDatum(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(interval, false, leftmostvalue_interval, interval_cmp)
|
static const bool interval_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction interval_cmp_fns[] =
|
||||||
|
{interval_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(interval, leftmostvalue_interval, interval_rhs_is_varlena, NULL, interval_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_macaddr(void)
|
leftmostvalue_macaddr(void)
|
||||||
@ -321,7 +546,13 @@ leftmostvalue_macaddr(void)
|
|||||||
return MacaddrPGetDatum(v);
|
return MacaddrPGetDatum(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(macaddr, false, leftmostvalue_macaddr, macaddr_cmp)
|
static const bool macaddr_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction macaddr_cmp_fns[] =
|
||||||
|
{macaddr_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(macaddr, leftmostvalue_macaddr, macaddr_rhs_is_varlena, NULL, macaddr_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_macaddr8(void)
|
leftmostvalue_macaddr8(void)
|
||||||
@ -331,7 +562,13 @@ leftmostvalue_macaddr8(void)
|
|||||||
return Macaddr8PGetDatum(v);
|
return Macaddr8PGetDatum(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(macaddr8, false, leftmostvalue_macaddr8, macaddr8_cmp)
|
static const bool macaddr8_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction macaddr8_cmp_fns[] =
|
||||||
|
{macaddr8_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(macaddr8, leftmostvalue_macaddr8, macaddr8_rhs_is_varlena, NULL, macaddr8_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_inet(void)
|
leftmostvalue_inet(void)
|
||||||
@ -339,9 +576,21 @@ leftmostvalue_inet(void)
|
|||||||
return DirectFunctionCall1(inet_in, CStringGetDatum("0.0.0.0/0"));
|
return DirectFunctionCall1(inet_in, CStringGetDatum("0.0.0.0/0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(inet, true, leftmostvalue_inet, network_cmp)
|
static const bool inet_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
GIN_SUPPORT(cidr, true, leftmostvalue_inet, network_cmp)
|
static const PGFunction inet_cmp_fns[] =
|
||||||
|
{network_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(inet, leftmostvalue_inet, inet_rhs_is_varlena, NULL, inet_cmp_fns)
|
||||||
|
|
||||||
|
static const bool cidr_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction cidr_cmp_fns[] =
|
||||||
|
{network_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(cidr, leftmostvalue_inet, cidr_rhs_is_varlena, NULL, cidr_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_text(void)
|
leftmostvalue_text(void)
|
||||||
@ -349,9 +598,21 @@ leftmostvalue_text(void)
|
|||||||
return PointerGetDatum(cstring_to_text_with_len("", 0));
|
return PointerGetDatum(cstring_to_text_with_len("", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(text, true, leftmostvalue_text, bttextcmp)
|
static const bool text_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
GIN_SUPPORT(bpchar, true, leftmostvalue_text, bpcharcmp)
|
static const PGFunction text_cmp_fns[] =
|
||||||
|
{bttextcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(text, leftmostvalue_text, text_rhs_is_varlena, NULL, text_cmp_fns)
|
||||||
|
|
||||||
|
static const bool bpchar_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction bpchar_cmp_fns[] =
|
||||||
|
{bpcharcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(bpchar, leftmostvalue_text, bpchar_rhs_is_varlena, NULL, bpchar_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_char(void)
|
leftmostvalue_char(void)
|
||||||
@ -359,9 +620,21 @@ leftmostvalue_char(void)
|
|||||||
return CharGetDatum(0);
|
return CharGetDatum(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(char, false, leftmostvalue_char, btcharcmp)
|
static const bool char_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
GIN_SUPPORT(bytea, true, leftmostvalue_text, byteacmp)
|
static const PGFunction char_cmp_fns[] =
|
||||||
|
{btcharcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(char, leftmostvalue_char, char_rhs_is_varlena, NULL, char_cmp_fns)
|
||||||
|
|
||||||
|
static const bool bytea_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction bytea_cmp_fns[] =
|
||||||
|
{byteacmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(bytea, leftmostvalue_text, bytea_rhs_is_varlena, NULL, bytea_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_bit(void)
|
leftmostvalue_bit(void)
|
||||||
@ -372,7 +645,13 @@ leftmostvalue_bit(void)
|
|||||||
Int32GetDatum(-1));
|
Int32GetDatum(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(bit, true, leftmostvalue_bit, bitcmp)
|
static const bool bit_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction bit_cmp_fns[] =
|
||||||
|
{bitcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(bit, leftmostvalue_bit, bit_rhs_is_varlena, NULL, bit_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_varbit(void)
|
leftmostvalue_varbit(void)
|
||||||
@ -383,7 +662,13 @@ leftmostvalue_varbit(void)
|
|||||||
Int32GetDatum(-1));
|
Int32GetDatum(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(varbit, true, leftmostvalue_varbit, bitcmp)
|
static const bool varbit_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction varbit_cmp_fns[] =
|
||||||
|
{bitcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(varbit, leftmostvalue_varbit, varbit_rhs_is_varlena, NULL, varbit_cmp_fns)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
@ -428,7 +713,13 @@ leftmostvalue_numeric(void)
|
|||||||
return PointerGetDatum(NULL);
|
return PointerGetDatum(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(numeric, true, leftmostvalue_numeric, gin_numeric_cmp)
|
static const bool numeric_rhs_is_varlena[] =
|
||||||
|
{true};
|
||||||
|
|
||||||
|
static const PGFunction numeric_cmp_fns[] =
|
||||||
|
{gin_numeric_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(numeric, leftmostvalue_numeric, numeric_rhs_is_varlena, NULL, numeric_cmp_fns)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use a similar trick to that used for numeric for enums, since we don't
|
* Use a similar trick to that used for numeric for enums, since we don't
|
||||||
@ -477,7 +768,13 @@ leftmostvalue_enum(void)
|
|||||||
return ObjectIdGetDatum(InvalidOid);
|
return ObjectIdGetDatum(InvalidOid);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(anyenum, false, leftmostvalue_enum, gin_enum_cmp)
|
static const bool enum_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction enum_cmp_fns[] =
|
||||||
|
{gin_enum_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(anyenum, leftmostvalue_enum, enum_rhs_is_varlena, NULL, enum_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_uuid(void)
|
leftmostvalue_uuid(void)
|
||||||
@ -491,7 +788,13 @@ leftmostvalue_uuid(void)
|
|||||||
return UUIDPGetDatum(retval);
|
return UUIDPGetDatum(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(uuid, false, leftmostvalue_uuid, uuid_cmp)
|
static const bool uuid_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction uuid_cmp_fns[] =
|
||||||
|
{uuid_cmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(uuid, leftmostvalue_uuid, uuid_rhs_is_varlena, NULL, uuid_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_name(void)
|
leftmostvalue_name(void)
|
||||||
@ -501,7 +804,13 @@ leftmostvalue_name(void)
|
|||||||
return NameGetDatum(result);
|
return NameGetDatum(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(name, false, leftmostvalue_name, btnamecmp)
|
static const bool name_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction name_cmp_fns[] =
|
||||||
|
{btnamecmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(name, leftmostvalue_name, name_rhs_is_varlena, NULL, name_cmp_fns)
|
||||||
|
|
||||||
static Datum
|
static Datum
|
||||||
leftmostvalue_bool(void)
|
leftmostvalue_bool(void)
|
||||||
@ -509,4 +818,10 @@ leftmostvalue_bool(void)
|
|||||||
return BoolGetDatum(false);
|
return BoolGetDatum(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
GIN_SUPPORT(bool, false, leftmostvalue_bool, btboolcmp)
|
static const bool bool_rhs_is_varlena[] =
|
||||||
|
{false};
|
||||||
|
|
||||||
|
static const PGFunction bool_cmp_fns[] =
|
||||||
|
{btboolcmp};
|
||||||
|
|
||||||
|
GIN_SUPPORT(bool, leftmostvalue_bool, bool_rhs_is_varlena, NULL, bool_cmp_fns)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# btree_gin extension
|
# btree_gin extension
|
||||||
comment = 'support for indexing common datatypes in GIN'
|
comment = 'support for indexing common datatypes in GIN'
|
||||||
default_version = '1.3'
|
default_version = '1.4'
|
||||||
module_pathname = '$libdir/btree_gin'
|
module_pathname = '$libdir/btree_gin'
|
||||||
relocatable = true
|
relocatable = true
|
||||||
trusted = true
|
trusted = true
|
||||||
|
@ -42,3 +42,193 @@ SELECT * FROM test_int2 WHERE i>1::int2 ORDER BY i;
|
|||||||
3
|
3
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int4 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int2
|
||||||
|
Recheck Cond: (i < 1)
|
||||||
|
-> Bitmap Index Scan on idx_int2
|
||||||
|
Index Cond: (i < 1)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int8 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int2
|
||||||
|
Recheck Cond: (i < '1'::bigint)
|
||||||
|
-> Bitmap Index Scan on idx_int2
|
||||||
|
Index Cond: (i < '1'::bigint)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
-- Check endpoint and out-of-range cases
|
||||||
|
INSERT INTO test_int2 VALUES ((-32768)::int2),(32767);
|
||||||
|
SELECT gin_clean_pending_list('idx_int2');
|
||||||
|
gin_clean_pending_list
|
||||||
|
------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<(-32769)::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<=(-32769)::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i=(-32769)::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>=(-32769)::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
32767
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>(-32769)::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
32767
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<32768::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
32767
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<=32768::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
--------
|
||||||
|
-32768
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
32767
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i=32768::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>=32768::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i>32768::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
@ -42,3 +42,103 @@ SELECT * FROM test_int4 WHERE i>1::int4 ORDER BY i;
|
|||||||
3
|
3
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int2 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
-----------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int4
|
||||||
|
Recheck Cond: (i < '1'::smallint)
|
||||||
|
-> Bitmap Index Scan on idx_int4
|
||||||
|
Index Cond: (i < '1'::smallint)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i>=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i>1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int8 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int4
|
||||||
|
Recheck Cond: (i < '1'::bigint)
|
||||||
|
-> Bitmap Index Scan on idx_int4
|
||||||
|
Index Cond: (i < '1'::bigint)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i>=1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i>1::int8 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
@ -42,3 +42,103 @@ SELECT * FROM test_int8 WHERE i>1::int8 ORDER BY i;
|
|||||||
3
|
3
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int2 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
-----------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int8
|
||||||
|
Recheck Cond: (i < '1'::smallint)
|
||||||
|
-> Bitmap Index Scan on idx_int8
|
||||||
|
Index Cond: (i < '1'::smallint)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i>=1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i>1::int2 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int4 ORDER BY i;
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------------------
|
||||||
|
Sort
|
||||||
|
Sort Key: i
|
||||||
|
-> Bitmap Heap Scan on test_int8
|
||||||
|
Recheck Cond: (i < 1)
|
||||||
|
-> Bitmap Index Scan on idx_int8
|
||||||
|
Index Cond: (i < 1)
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
----
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i>=1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i>1::int4 ORDER BY i;
|
||||||
|
i
|
||||||
|
---
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ install_data(
|
|||||||
'btree_gin--1.0--1.1.sql',
|
'btree_gin--1.0--1.1.sql',
|
||||||
'btree_gin--1.1--1.2.sql',
|
'btree_gin--1.1--1.2.sql',
|
||||||
'btree_gin--1.2--1.3.sql',
|
'btree_gin--1.2--1.3.sql',
|
||||||
|
'btree_gin--1.3--1.4.sql',
|
||||||
kwargs: contrib_data_args,
|
kwargs: contrib_data_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,3 +13,38 @@ SELECT * FROM test_int2 WHERE i<=1::int2 ORDER BY i;
|
|||||||
SELECT * FROM test_int2 WHERE i=1::int2 ORDER BY i;
|
SELECT * FROM test_int2 WHERE i=1::int2 ORDER BY i;
|
||||||
SELECT * FROM test_int2 WHERE i>=1::int2 ORDER BY i;
|
SELECT * FROM test_int2 WHERE i>=1::int2 ORDER BY i;
|
||||||
SELECT * FROM test_int2 WHERE i>1::int2 ORDER BY i;
|
SELECT * FROM test_int2 WHERE i>1::int2 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int4 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i<=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>1::int4 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int8 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i<=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>1::int8 ORDER BY i;
|
||||||
|
|
||||||
|
-- Check endpoint and out-of-range cases
|
||||||
|
|
||||||
|
INSERT INTO test_int2 VALUES ((-32768)::int2),(32767);
|
||||||
|
SELECT gin_clean_pending_list('idx_int2');
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<(-32769)::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i<=(-32769)::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i=(-32769)::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>=(-32769)::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>(-32769)::int4 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int2 WHERE i<32768::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i<=32768::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i=32768::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>=32768::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int2 WHERE i>32768::int4 ORDER BY i;
|
||||||
|
@ -13,3 +13,21 @@ SELECT * FROM test_int4 WHERE i<=1::int4 ORDER BY i;
|
|||||||
SELECT * FROM test_int4 WHERE i=1::int4 ORDER BY i;
|
SELECT * FROM test_int4 WHERE i=1::int4 ORDER BY i;
|
||||||
SELECT * FROM test_int4 WHERE i>=1::int4 ORDER BY i;
|
SELECT * FROM test_int4 WHERE i>=1::int4 ORDER BY i;
|
||||||
SELECT * FROM test_int4 WHERE i>1::int4 ORDER BY i;
|
SELECT * FROM test_int4 WHERE i>1::int4 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int2 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i<=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i>=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i>1::int2 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int8 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int4 WHERE i<1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i<=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i>=1::int8 ORDER BY i;
|
||||||
|
SELECT * FROM test_int4 WHERE i>1::int8 ORDER BY i;
|
||||||
|
@ -13,3 +13,21 @@ SELECT * FROM test_int8 WHERE i<=1::int8 ORDER BY i;
|
|||||||
SELECT * FROM test_int8 WHERE i=1::int8 ORDER BY i;
|
SELECT * FROM test_int8 WHERE i=1::int8 ORDER BY i;
|
||||||
SELECT * FROM test_int8 WHERE i>=1::int8 ORDER BY i;
|
SELECT * FROM test_int8 WHERE i>=1::int8 ORDER BY i;
|
||||||
SELECT * FROM test_int8 WHERE i>1::int8 ORDER BY i;
|
SELECT * FROM test_int8 WHERE i>1::int8 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int2 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i<=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i>=1::int2 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i>1::int2 ORDER BY i;
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int4 ORDER BY i;
|
||||||
|
|
||||||
|
SELECT * FROM test_int8 WHERE i<1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i<=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i>=1::int4 ORDER BY i;
|
||||||
|
SELECT * FROM test_int8 WHERE i>1::int4 ORDER BY i;
|
||||||
|
@ -394,7 +394,11 @@
|
|||||||
Pointer extra_data)</function></term>
|
Pointer extra_data)</function></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Compare a partial-match query key to an index key. Returns an integer
|
Compare a partial-match query key to an index key.
|
||||||
|
<literal>partial_key</literal> is a query key that was returned
|
||||||
|
by <function>extractQuery</function> with an indication that it
|
||||||
|
requires partial match, and <literal>key</literal> is an index entry.
|
||||||
|
Returns an integer
|
||||||
whose sign indicates the result: less than zero means the index key
|
whose sign indicates the result: less than zero means the index key
|
||||||
does not match the query, but the index scan should continue; zero
|
does not match the query, but the index scan should continue; zero
|
||||||
means that the index key does match the query; greater than zero
|
means that the index key does match the query; greater than zero
|
||||||
|
@ -3481,6 +3481,8 @@ bloom_filter
|
|||||||
boolKEY
|
boolKEY
|
||||||
brin_column_state
|
brin_column_state
|
||||||
brin_serialize_callback_type
|
brin_serialize_callback_type
|
||||||
|
btree_gin_convert_function
|
||||||
|
btree_gin_leftmost_function
|
||||||
bytea
|
bytea
|
||||||
cached_re_str
|
cached_re_str
|
||||||
canonicalize_state
|
canonicalize_state
|
||||||
|
Reference in New Issue
Block a user