@ -8,11 +8,24 @@
# include <float.h>
# include "btree_utils_var.h"
# include "catalog/pg_collation.h"
# include "utils/pg_locale.h"
# include "utils/builtins.h"
# include "utils/rel.h"
/* used for key sorting */
typedef struct
{
int i ;
GBT_VARKEY * t ;
} Vsrt ;
typedef struct
{
const gbtree_vinfo * tinfo ;
Oid collation ;
} gbt_vsrt_arg ;
PG_FUNCTION_INFO_V1 ( gbt_var_decompress ) ;
Datum gbt_var_decompress ( PG_FUNCTION_ARGS ) ;
@ -140,13 +153,11 @@ gbt_var_node_cp_len(const GBT_VARKEY *node, const gbtree_vinfo *tinfo)
/*
* returns true , if query matches prefix ( common prefix )
*/
*/
static bool
gbt_bytea_pf_match ( const bytea * pf , const bytea * query , const gbtree_vinfo * tinfo )
{
bool out = FALSE ;
int32 k = 0 ;
int32 qlen = VARSIZE ( query ) - VARHDRSZ ;
int32 nlen = VARSIZE ( pf ) - VARHDRSZ ;
@ -155,27 +166,7 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinf
char * q = VARDATA ( query ) ;
char * n = VARDATA ( pf ) ;
if ( tinfo - > eml > 1 )
{
out = ( varstr_cmp ( q , nlen , n , nlen , DEFAULT_COLLATION_OID ) = = 0 ) ;
}
else
{
out = TRUE ;
for ( k = 0 ; k < nlen ; k + + )
{
if ( * n ! = * q )
{
out = FALSE ;
break ;
}
if ( k < ( nlen - 1 ) )
{
q + + ;
n + + ;
}
}
}
out = ( memcmp ( q , n , nlen ) = = 0 ) ;
}
return out ;
@ -184,17 +175,14 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinf
/*
* returns true , if query matches node using common prefix
*/
*/
static bool
gbt_var_node_pf_match ( const GBT_VARKEY_R * node , const bytea * query , const gbtree_vinfo * tinfo )
{
return ( tinfo - > trnc & & (
gbt_bytea_pf_match ( node - > lower , query , tinfo ) | |
gbt_bytea_pf_match ( node - > upper , query , tinfo )
) ) ;
}
@ -232,9 +220,9 @@ gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vin
void
gbt_var_bin_union ( Datum * u , GBT_VARKEY * e , const gbtree_vinfo * tinfo )
gbt_var_bin_union ( Datum * u , GBT_VARKEY * e , Oid collation ,
const gbtree_vinfo * tinfo )
{
GBT_VARKEY * nk = NULL ;
GBT_VARKEY * tmp = NULL ;
GBT_VARKEY_R nr ;
@ -252,14 +240,14 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, const gbtree_vinfo *tinfo)
GBT_VARKEY_R ro = gbt_var_key_readable ( ( GBT_VARKEY * ) DatumGetPointer ( * u ) ) ;
if ( ( * tinfo - > f_cmp ) ( ( bytea * ) ro . lower , ( bytea * ) eo . lower ) > 0 )
if ( ( * tinfo - > f_cmp ) ( ro . lower , eo . lower , collation ) > 0 )
{
nr . lower = eo . lower ;
nr . upper = ro . upper ;
nk = gbt_var_key_copy ( & nr , TRUE ) ;
}
if ( ( * tinfo - > f_cmp ) ( ( bytea * ) ro . upper , ( bytea * ) eo . upper ) < 0 )
if ( ( * tinfo - > f_cmp ) ( ro . upper , eo . upper , collation ) < 0 )
{
nr . upper = eo . upper ;
nr . lower = ro . lower ;
@ -308,7 +296,8 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
GBT_VARKEY *
gbt_var_union ( const GistEntryVector * entryvec , int32 * size , const gbtree_vinfo * tinfo )
gbt_var_union ( const GistEntryVector * entryvec , int32 * size , Oid collation ,
const gbtree_vinfo * tinfo )
{
int i = 0 ,
@ -326,7 +315,7 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo *
for ( i = 1 ; i < numranges ; i + + )
{
cur = ( GBT_VARKEY * ) DatumGetPointer ( entryvec - > vector [ i ] . key ) ;
gbt_var_bin_union ( & out , cur , tinfo ) ;
gbt_var_bin_union ( & out , cur , collation , tinfo ) ;
}
@ -347,9 +336,10 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo *
bool
gbt_var_same ( bool * result , const Datum d1 , const Datum d2 , const gbtree_vinfo * tinfo )
gbt_var_same ( Datum d1 , Datum d2 , Oid collation ,
const gbtree_vinfo * tinfo )
{
bool result ;
GBT_VARKEY * t1 = ( GBT_VARKEY * ) DatumGetPointer ( d1 ) ;
GBT_VARKEY * t2 = ( GBT_VARKEY * ) DatumGetPointer ( d2 ) ;
GBT_VARKEY_R r1 ,
@ -359,22 +349,19 @@ gbt_var_same(bool *result, const Datum d1, const Datum d2, const gbtree_vinfo *t
r2 = gbt_var_key_readable ( t2 ) ;
if ( t1 & & t2 )
{
* result = ( ( ( * tinfo - > f_cmp ) ( ( bytea * ) r1 . lower , ( bytea * ) r2 . lower ) = = 0
& & ( * tinfo - > f_cmp ) ( ( bytea * ) r1 . upper , ( bytea * ) r2 . upper ) = = 0 ) ? TRUE : FALSE ) ;
}
result = ( ( * tinfo - > f_cmp ) ( r1 . lower , r2 . lower , collation ) = = 0 & &
( * tinfo - > f_cmp ) ( r1 . upper , r2 . upper , collation ) = = 0 ) ;
else
* result = ( t1 = = NULL & & t2 = = NULL ) ? TRUE : FALSE ;
result = ( t1 = = NULL & & t2 = = NULL ) ;
PG_RETURN_POINTER ( result ) ;
return result ;
}
float *
gbt_var_penalty ( float * res , const GISTENTRY * o , const GISTENTRY * n , const gbtree_vinfo * tinfo )
gbt_var_penalty ( float * res , const GISTENTRY * o , const GISTENTRY * n ,
Oid collation , const gbtree_vinfo * tinfo )
{
GBT_VARKEY * orge = ( GBT_VARKEY * ) DatumGetPointer ( o - > key ) ;
GBT_VARKEY * newe = ( GBT_VARKEY * ) DatumGetPointer ( n - > key ) ;
GBT_VARKEY_R ok ,
@ -394,21 +381,19 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree
if ( ( VARSIZE ( ok . lower ) - VARHDRSZ ) = = 0 & & ( VARSIZE ( ok . upper ) - VARHDRSZ ) = = 0 )
* res = 0.0 ;
else if ( ! (
(
( ( * tinfo - > f_cmp ) ( nk . lower , ok . lower ) > = 0 | | gbt_bytea_pf_match ( ok . lower , nk . lower , tinfo ) ) & &
( ( * tinfo - > f_cmp ) ( nk . upper , ok . upper ) < = 0 | | gbt_bytea_pf_match ( ok . upper , nk . upper , tinfo ) )
)
) )
else if ( ! ( ( ( * tinfo - > f_cmp ) ( nk . lower , ok . lower , collation ) > = 0 | |
gbt_bytea_pf_match ( ok . lower , nk . lower , tinfo ) ) & &
( ( * tinfo - > f_cmp ) ( nk . upper , ok . upper , collation ) < = 0 | |
gbt_bytea_pf_match ( ok . upper , nk . upper , tinfo ) ) ) )
{
Datum d = PointerGetDatum ( 0 ) ;
double dres = 0.0 ;
int32 ol ,
ul ;
gbt_var_bin_union ( & d , orge , tinfo ) ;
gbt_var_bin_union ( & d , orge , collation , tinfo ) ;
ol = gbt_var_node_cp_len ( ( GBT_VARKEY * ) DatumGetPointer ( d ) , tinfo ) ;
gbt_var_bin_union ( & d , newe , tinfo ) ;
gbt_var_bin_union ( & d , newe , collation , tinfo ) ;
ul = gbt_var_node_cp_len ( ( GBT_VARKEY * ) DatumGetPointer ( d ) , tinfo ) ;
if ( ul < ol )
@ -444,18 +429,19 @@ gbt_vsrt_cmp(const void *a, const void *b, void *arg)
{
GBT_VARKEY_R ar = gbt_var_key_readable ( ( ( const Vsrt * ) a ) - > t ) ;
GBT_VARKEY_R br = gbt_var_key_readable ( ( ( const Vsrt * ) b ) - > t ) ;
const gbtree_vinfo * tinfo = ( const gbtree_vinfo * ) arg ;
const gbt_vsrt_arg * varg = ( const gbt_vsrt_arg * ) arg ;
int res ;
res = ( * tinfo - > f_cmp ) ( ar . lower , br . lower ) ;
res = ( * varg - > tinfo - > f_cmp ) ( ar . lower , br . lower , varg - > collation ) ;
if ( res = = 0 )
return ( * tinfo - > f_cmp ) ( ar . upper , br . upper ) ;
return ( * varg - > tinfo - > f_cmp ) ( ar . upper , br . upper , varg - > collation ) ;
return res ;
}
GIST_SPLITVEC *
gbt_var_picksplit ( const GistEntryVector * entryvec , GIST_SPLITVEC * v , const gbtree_vinfo * tinfo )
gbt_var_picksplit ( const GistEntryVector * entryvec , GIST_SPLITVEC * v ,
Oid collation , const gbtree_vinfo * tinfo )
{
OffsetNumber i ,
maxoff = entryvec - > n - 1 ;
@ -464,6 +450,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
nbytes ;
char * cur ;
GBT_VARKEY * * sv = NULL ;
gbt_vsrt_arg varg ;
arr = ( Vsrt * ) palloc ( ( maxoff + 1 ) * sizeof ( Vsrt ) ) ;
nbytes = ( maxoff + 2 ) * sizeof ( OffsetNumber ) ;
@ -497,11 +484,13 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
}
/* sort */
varg . tinfo = tinfo ;
varg . collation = collation ;
qsort_arg ( ( void * ) & arr [ FirstOffsetNumber ] ,
maxoff - FirstOffsetNumber + 1 ,
sizeof ( Vsrt ) ,
gbt_vsrt_cmp ,
( void * ) tinfo ) ;
( void * ) & varg ) ;
/* We do simply create two parts */
@ -509,13 +498,13 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
{
if ( i < = ( maxoff - FirstOffsetNumber + 1 ) / 2 )
{
gbt_var_bin_union ( & v - > spl_ldatum , arr [ i ] . t , tinfo ) ;
gbt_var_bin_union ( & v - > spl_ldatum , arr [ i ] . t , collation , tinfo ) ;
v - > spl_left [ v - > spl_nleft ] = arr [ i ] . i ;
v - > spl_nleft + + ;
}
else
{
gbt_var_bin_union ( & v - > spl_rdatum , arr [ i ] . t , tinfo ) ;
gbt_var_bin_union ( & v - > spl_rdatum , arr [ i ] . t , collation , tinfo ) ;
v - > spl_right [ v - > spl_nright ] = arr [ i ] . i ;
v - > spl_nright + + ;
}
@ -546,63 +535,61 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
* The GiST consistent method
*/
bool
gbt_var_consistent (
GBT_VARKEY_R * key ,
gbt_var_consistent ( GBT_VARKEY_R * key ,
const void * query ,
const StrategyNumber * strategy ,
StrategyNumber strategy ,
Oid collation ,
bool is_leaf ,
const gbtree_vinfo * tinfo
)
const gbtree_vinfo * tinfo )
{
bool retval = FALSE ;
switch ( * strategy )
switch ( strategy )
{
case BTLessEqualStrategyNumber :
if ( is_leaf )
retval = ( * tinfo - > f_ge ) ( query , ( void * ) key - > lower ) ;
retval = ( * tinfo - > f_ge ) ( query , key - > lower , collation ) ;
else
retval = ( * tinfo - > f_cmp ) ( ( bytea * ) query , key - > lower ) > = 0
retval = ( * tinfo - > f_cmp ) ( query , key - > lower , collation ) > = 0
| | gbt_var_node_pf_match ( key , query , tinfo ) ;
break ;
case BTLessStrategyNumber :
if ( is_leaf )
retval = ( * tinfo - > f_gt ) ( query , ( void * ) key - > lower ) ;
retval = ( * tinfo - > f_gt ) ( query , key - > lower , collation ) ;
else
retval = ( * tinfo - > f_cmp ) ( ( bytea * ) query , key - > lower ) > = 0
retval = ( * tinfo - > f_cmp ) ( query , key - > lower , collation ) > = 0
| | gbt_var_node_pf_match ( key , query , tinfo ) ;
break ;
case BTEqualStrategyNumber :
if ( is_leaf )
retval = ( * tinfo - > f_eq ) ( query , ( void * ) key - > lower ) ;
retval = ( * tinfo - > f_eq ) ( query , key - > lower , collation ) ;
else
retval = (
(
( * tinfo - > f_cmp ) ( key - > lower , ( bytea * ) query ) < = 0 & &
( * tinfo - > f_cmp ) ( ( bytea * ) query , ( void * ) key - > upper ) < = 0
) | | gbt_var_node_pf_match ( key , query , tinfo )
) ;
retval =
( ( * tinfo - > f_cmp ) ( key - > lower , query , collation ) < = 0 & &
( * tinfo - > f_cmp ) ( query , key - > upper , collation ) < = 0 ) | |
gbt_var_node_pf_match ( key , query , tinfo ) ;
break ;
case BTGreaterStrategyNumber :
if ( is_leaf )
retval = ( * tinfo - > f_lt ) ( query , ( void * ) key - > upper ) ;
retval = ( * tinfo - > f_lt ) ( query , key - > upper , collation ) ;
else
retval = ( * tinfo - > f_cmp ) ( ( bytea * ) query , key - > upper ) < = 0
retval = ( * tinfo - > f_cmp ) ( query , key - > upper , collation ) < = 0
| | gbt_var_node_pf_match ( key , query , tinfo ) ;
break ;
case BTGreaterEqualStrategyNumber :
if ( is_leaf )
retval = ( * tinfo - > f_le ) ( query , ( void * ) key - > upper ) ;
retval = ( * tinfo - > f_le ) ( query , key - > upper , collation ) ;
else
retval = ( * tinfo - > f_cmp ) ( ( bytea * ) query , key - > upper ) < = 0
retval = ( * tinfo - > f_cmp ) ( query , key - > upper , collation ) < = 0
| | gbt_var_node_pf_match ( key , query , tinfo ) ;
break ;
case BtreeGistNotEqualStrategyNumber :
retval = ! ( ( * tinfo - > f_eq ) ( query , key - > lower ) & & ( * tinfo - > f_eq ) ( query , key - > upper ) ) ;
retval = ! ( ( * tinfo - > f_eq ) ( query , key - > lower , collation ) & &
( * tinfo - > f_eq ) ( query , key - > upper , collation ) ) ;
break ;
default :
retval = FALSE ;
}
return ( retval ) ;
return retval ;
}