Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

btree_interval.c

Blame
    • Peter Eisentraut's avatar
      2eb4a831
      Change TRUE/FALSE to true/false · 2eb4a831
      Peter Eisentraut authored
      
      The lower case spellings are C and C++ standard and are used in most
      parts of the PostgreSQL sources.  The upper case spellings are only used
      in some files/modules.  So standardize on the standard spellings.
      
      The APIs for ICU, Perl, and Windows define their own TRUE and FALSE, so
      those are left as is when using those APIs.
      
      In code comments, we use the lower-case spelling for the C concepts and
      keep the upper-case spelling for the SQL concepts.
      
      Reviewed-by: default avatarMichael Paquier <michael.paquier@gmail.com>
      2eb4a831
      History
      Change TRUE/FALSE to true/false
      Peter Eisentraut authored
      
      The lower case spellings are C and C++ standard and are used in most
      parts of the PostgreSQL sources.  The upper case spellings are only used
      in some files/modules.  So standardize on the standard spellings.
      
      The APIs for ICU, Perl, and Windows define their own TRUE and FALSE, so
      those are left as is when using those APIs.
      
      In code comments, we use the lower-case spelling for the C concepts and
      keep the upper-case spelling for the SQL concepts.
      
      Reviewed-by: default avatarMichael Paquier <michael.paquier@gmail.com>
    btree_interval.c 7.34 KiB
    /*
     * contrib/btree_gist/btree_interval.c
     */
    #include "postgres.h"
    
    #include "btree_gist.h"
    #include "btree_utils_num.h"
    #include "utils/builtins.h"
    #include "utils/timestamp.h"
    
    typedef struct
    {
    	Interval	lower,
    				upper;
    } intvKEY;
    
    
    /*
    ** Interval ops
    */
    PG_FUNCTION_INFO_V1(gbt_intv_compress);
    PG_FUNCTION_INFO_V1(gbt_intv_fetch);
    PG_FUNCTION_INFO_V1(gbt_intv_decompress);
    PG_FUNCTION_INFO_V1(gbt_intv_union);
    PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
    PG_FUNCTION_INFO_V1(gbt_intv_consistent);
    PG_FUNCTION_INFO_V1(gbt_intv_distance);
    PG_FUNCTION_INFO_V1(gbt_intv_penalty);
    PG_FUNCTION_INFO_V1(gbt_intv_same);
    
    
    static bool
    gbt_intvgt(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
    }
    
    static bool
    gbt_intvge(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
    }
    
    static bool
    gbt_intveq(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
    }
    
    static bool
    gbt_intvle(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
    }
    
    static bool
    gbt_intvlt(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
    }
    
    static int
    gbt_intvkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	intvKEY    *ia = (intvKEY *) (((const Nsrt *) a)->t);
    	intvKEY    *ib = (intvKEY *) (((const Nsrt *) b)->t);
    	int			res;
    
    	res = DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->lower), IntervalPGetDatum(&ib->lower)));
    	if (res == 0)
    		return DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->upper), IntervalPGetDatum(&ib->upper)));
    
    	return res;
    }
    
    
    static double
    intr2num(const Interval *i)
    {
    	return INTERVAL_TO_SEC(i);
    }
    
    static float8
    gbt_intv_dist(const void *a, const void *b, FmgrInfo *flinfo)
    {
    	return (float8) Abs(intr2num((const Interval *) a) - intr2num((const Interval *) b));
    }
    
    /*
     * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
     * in pg_type.  This might be less than sizeof(Interval) if the compiler
     * insists on adding alignment padding at the end of the struct.  (Note:
     * this concern is obsolete with the current definition of Interval, but
     * was real before a separate "day" field was added to it.)
     */
    #define INTERVALSIZE 16
    
    static const gbtree_ninfo tinfo =
    {
    	gbt_t_intv,
    	sizeof(Interval),
    	32,							/* sizeof(gbtreekey32) */
    	gbt_intvgt,
    	gbt_intvge,
    	gbt_intveq,
    	gbt_intvle,
    	gbt_intvlt,
    	gbt_intvkey_cmp,
    	gbt_intv_dist
    };
    
    
    Interval *
    abs_interval(Interval *a)
    {
    	static Interval zero = {0, 0, 0};
    
    	if (DatumGetBool(DirectFunctionCall2(interval_lt,
    										 IntervalPGetDatum(a),
    										 IntervalPGetDatum(&zero))))
    		a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
    												  IntervalPGetDatum(a)));
    
    	return a;
    }
    
    PG_FUNCTION_INFO_V1(interval_dist);
    Datum
    interval_dist(PG_FUNCTION_ARGS)
    {
    	Datum		diff = DirectFunctionCall2(interval_mi,
    										   PG_GETARG_DATUM(0),
    										   PG_GETARG_DATUM(1));
    
    	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
    }
    
    
    /**************************************************
     * interval ops
     **************************************************/
    
    
    Datum
    gbt_intv_compress(PG_FUNCTION_ARGS)
    {
    	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    	GISTENTRY  *retval = entry;
    
    	if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
    	{
    		char	   *r = (char *) palloc(2 * INTERVALSIZE);
    
    		retval = palloc(sizeof(GISTENTRY));
    
    		if (entry->leafkey)
    		{
    			Interval   *key = DatumGetIntervalP(entry->key);
    
    			memcpy((void *) r, (void *) key, INTERVALSIZE);
    			memcpy((void *) (r + INTERVALSIZE), (void *) key, INTERVALSIZE);
    		}
    		else
    		{
    			intvKEY    *key = (intvKEY *) DatumGetPointer(entry->key);
    
    			memcpy(r, &key->lower, INTERVALSIZE);
    			memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE);
    		}
    		gistentryinit(*retval, PointerGetDatum(r),
    					  entry->rel, entry->page,
    					  entry->offset, false);
    	}
    
    	PG_RETURN_POINTER(retval);
    
    }
    
    Datum
    gbt_intv_fetch(PG_FUNCTION_ARGS)
    {
    	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    
    	PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
    }
    
    Datum
    gbt_intv_decompress(PG_FUNCTION_ARGS)
    {
    	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    	GISTENTRY  *retval = entry;
    
    	if (INTERVALSIZE != sizeof(Interval))
    	{
    		intvKEY    *r = palloc(sizeof(intvKEY));
    		char	   *key = DatumGetPointer(entry->key);
    
    		retval = palloc(sizeof(GISTENTRY));
    		memcpy(&r->lower, key, INTERVALSIZE);
    		memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
    
    		gistentryinit(*retval, PointerGetDatum(r),
    					  entry->rel, entry->page,
    					  entry->offset, false);
    	}
    	PG_RETURN_POINTER(retval);
    }
    
    
    Datum
    gbt_intv_consistent(PG_FUNCTION_ARGS)
    {
    	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    	Interval   *query = PG_GETARG_INTERVAL_P(1);
    	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
    
    	/* Oid		subtype = PG_GETARG_OID(3); */
    	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
    	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
    	GBT_NUMKEY_R key;
    
    	/* All cases served by this function are exact */
    	*recheck = false;
    
    	key.lower = (GBT_NUMKEY *) &kkk->lower;
    	key.upper = (GBT_NUMKEY *) &kkk->upper;
    
    	PG_RETURN_BOOL(
    				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
    		);
    }
    
    
    Datum
    gbt_intv_distance(PG_FUNCTION_ARGS)
    {
    	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    	Interval   *query = PG_GETARG_INTERVAL_P(1);
    
    	/* Oid		subtype = PG_GETARG_OID(3); */
    	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
    	GBT_NUMKEY_R key;
    
    	key.lower = (GBT_NUMKEY *) &kkk->lower;
    	key.upper = (GBT_NUMKEY *) &kkk->upper;
    
    	PG_RETURN_FLOAT8(
    					 gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
    		);
    }
    
    
    Datum
    gbt_intv_union(PG_FUNCTION_ARGS)
    {
    	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    	void	   *out = palloc(sizeof(intvKEY));
    
    	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
    	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
    }
    
    
    Datum
    gbt_intv_penalty(PG_FUNCTION_ARGS)
    {
    	intvKEY    *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
    	intvKEY    *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
    	float	   *result = (float *) PG_GETARG_POINTER(2);
    	double		iorg[2],
    				inew[2];
    
    	iorg[0] = intr2num(&origentry->lower);
    	iorg[1] = intr2num(&origentry->upper);
    	inew[0] = intr2num(&newentry->lower);
    	inew[1] = intr2num(&newentry->upper);
    
    	penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]);
    
    	PG_RETURN_POINTER(result);
    
    }
    
    Datum
    gbt_intv_picksplit(PG_FUNCTION_ARGS)
    {
    	PG_RETURN_POINTER(gbt_num_picksplit(
    										(GistEntryVector *) PG_GETARG_POINTER(0),
    										(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
    										&tinfo, fcinfo->flinfo
    										));
    }
    
    Datum
    gbt_intv_same(PG_FUNCTION_ARGS)
    {
    	intvKEY    *b1 = (intvKEY *) PG_GETARG_POINTER(0);
    	intvKEY    *b2 = (intvKEY *) PG_GETARG_POINTER(1);
    	bool	   *result = (bool *) PG_GETARG_POINTER(2);
    
    	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    	PG_RETURN_POINTER(result);
    }