mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
Pgindent run for 8.0.
This commit is contained in:
parent
90cb9c3051
commit
b6b71b85bc
@ -14,92 +14,99 @@ PG_FUNCTION_INFO_V1(gbt_bit_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_bit_penalty);
|
PG_FUNCTION_INFO_V1(gbt_bit_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_bit_same);
|
PG_FUNCTION_INFO_V1(gbt_bit_same);
|
||||||
|
|
||||||
Datum gbt_bit_compress(PG_FUNCTION_ARGS);
|
Datum gbt_bit_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bit_union(PG_FUNCTION_ARGS);
|
Datum gbt_bit_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bit_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_bit_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bit_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_bit_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bit_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_bit_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bit_same(PG_FUNCTION_ARGS);
|
Datum gbt_bit_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* define for comparison */
|
/* define for comparison */
|
||||||
|
|
||||||
static bool gbt_bitgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_bitgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( bitgt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(bitgt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_bitge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_bitge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( bitge ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(bitge, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_biteq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_biteq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( biteq ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(biteq, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_bitle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_bitle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( bitle ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(bitle, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_bitlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_bitlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( bitlt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(bitlt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 gbt_bitcmp ( const bytea * a , const bytea * b )
|
static int32
|
||||||
|
gbt_bitcmp(const bytea *a, const bytea *b)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
( DatumGetInt32(DirectFunctionCall2(byteacmp,PointerGetDatum(a),PointerGetDatum(b) ) ) );
|
(DatumGetInt32(DirectFunctionCall2(byteacmp, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bytea *
|
static bytea *
|
||||||
gbt_bit_xfrm ( bytea * leaf )
|
gbt_bit_xfrm(bytea *leaf)
|
||||||
{
|
{
|
||||||
bytea * out = leaf;
|
bytea *out = leaf;
|
||||||
int s = VARBITBYTES(leaf) + VARHDRSZ;
|
int s = VARBITBYTES(leaf) + VARHDRSZ;
|
||||||
|
|
||||||
out = palloc ( s );
|
out = palloc(s);
|
||||||
VARATT_SIZEP(out) = s;
|
VARATT_SIZEP(out) = s;
|
||||||
memcpy ( (void*)VARDATA(out), (void*)VARBITS(leaf), VARBITBYTES(leaf) );
|
memcpy((void *) VARDATA(out), (void *) VARBITS(leaf), VARBITBYTES(leaf));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static GBT_VARKEY * gbt_bit_l2n ( GBT_VARKEY * leaf )
|
static GBT_VARKEY *
|
||||||
|
gbt_bit_l2n(GBT_VARKEY * leaf)
|
||||||
{
|
{
|
||||||
|
|
||||||
GBT_VARKEY *out = leaf ;
|
GBT_VARKEY *out = leaf;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( leaf );
|
GBT_VARKEY_R r = gbt_var_key_readable(leaf);
|
||||||
bytea *o ;
|
bytea *o;
|
||||||
|
|
||||||
o = gbt_bit_xfrm (r.lower);
|
o = gbt_bit_xfrm(r.lower);
|
||||||
r.upper = r.lower = o;
|
r.upper = r.lower = o;
|
||||||
out = gbt_var_key_copy( &r, TRUE );
|
out = gbt_var_key_copy(&r, TRUE);
|
||||||
pfree(o);
|
pfree(o);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gbtree_vinfo tinfo =
|
static const gbtree_vinfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_bit,
|
gbt_t_bit,
|
||||||
FALSE,
|
FALSE,
|
||||||
TRUE,
|
TRUE,
|
||||||
gbt_bitgt,
|
gbt_bitgt,
|
||||||
gbt_bitge,
|
gbt_bitge,
|
||||||
gbt_biteq,
|
gbt_biteq,
|
||||||
gbt_bitle,
|
gbt_bitle,
|
||||||
gbt_bitlt,
|
gbt_bitlt,
|
||||||
gbt_bitcmp,
|
gbt_bitcmp,
|
||||||
gbt_bit_l2n
|
gbt_bit_l2n
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -108,40 +115,40 @@ static const gbtree_vinfo tinfo =
|
|||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bit_compress (PG_FUNCTION_ARGS)
|
gbt_bit_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
PG_RETURN_POINTER ( gbt_var_compress( entry, &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bit_consistent(PG_FUNCTION_ARGS)
|
gbt_bit_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer ( entry->key ) ;
|
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer ( PG_DETOAST_DATUM( entry->key ) );
|
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
void *qtst = ( void * ) DatumGetPointer( PG_GETARG_DATUM(1) );
|
void *qtst = (void *) DatumGetPointer(PG_GETARG_DATUM(1));
|
||||||
void *query = ( void * ) DatumGetByteaP ( PG_GETARG_DATUM(1) );
|
void *query = (void *) DatumGetByteaP(PG_GETARG_DATUM(1));
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( key );
|
GBT_VARKEY_R r = gbt_var_key_readable(key);
|
||||||
|
|
||||||
if ( GIST_LEAF(entry) )
|
if (GIST_LEAF(entry))
|
||||||
{
|
retval = gbt_var_consistent(&r, query, &strategy, TRUE, &tinfo);
|
||||||
retval = gbt_var_consistent( &r, query, &strategy, TRUE, &tinfo );
|
else
|
||||||
} else {
|
{
|
||||||
bytea * q = gbt_bit_xfrm ( ( bytea * ) query );
|
bytea *q = gbt_bit_xfrm((bytea *) query);
|
||||||
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo );
|
|
||||||
pfree(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ktst != key ){
|
retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
|
||||||
pfree ( key );
|
pfree(q);
|
||||||
}
|
}
|
||||||
if ( qtst != query ){
|
|
||||||
pfree ( query );
|
if (ktst != key)
|
||||||
}
|
pfree(key);
|
||||||
PG_RETURN_BOOL(retval);
|
if (qtst != query)
|
||||||
|
pfree(query);
|
||||||
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,37 +156,40 @@ gbt_bit_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_bit_union(PG_FUNCTION_ARGS)
|
gbt_bit_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector * entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int32 * size = (int *) PG_GETARG_POINTER(1);
|
int32 *size = (int *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_union ( entryvec , size , &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bit_picksplit(PG_FUNCTION_ARGS)
|
gbt_bit_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
gbt_var_picksplit ( entryvec, v, &tinfo );
|
|
||||||
PG_RETURN_POINTER(v);
|
gbt_var_picksplit(entryvec, v, &tinfo);
|
||||||
|
PG_RETURN_POINTER(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bit_same(PG_FUNCTION_ARGS)
|
gbt_bit_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum d1 = PG_GETARG_DATUM(0);
|
Datum d1 = PG_GETARG_DATUM(0);
|
||||||
Datum d2 = PG_GETARG_DATUM(1);
|
Datum d2 = PG_GETARG_DATUM(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
PG_RETURN_POINTER( gbt_var_same ( result, d1 , d2 , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bit_penalty(PG_FUNCTION_ARGS)
|
gbt_bit_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
GISTENTRY * o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY * n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_penalty ( result ,o , n, &tinfo ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
|
||||||
|
}
|
||||||
|
@ -13,61 +13,67 @@ PG_FUNCTION_INFO_V1(gbt_bytea_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_bytea_penalty);
|
PG_FUNCTION_INFO_V1(gbt_bytea_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_bytea_same);
|
PG_FUNCTION_INFO_V1(gbt_bytea_same);
|
||||||
|
|
||||||
Datum gbt_bytea_compress(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bytea_union(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bytea_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bytea_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bytea_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bytea_same(PG_FUNCTION_ARGS);
|
Datum gbt_bytea_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
/* define for comparison */
|
/* define for comparison */
|
||||||
|
|
||||||
static bool gbt_byteagt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_byteagt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( byteagt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(byteagt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_byteage (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_byteage(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( byteage ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(byteage, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_byteaeq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_byteaeq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( byteaeq ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(byteaeq, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_byteale (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_byteale(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( byteale ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(byteale, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_bytealt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_bytealt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( bytealt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(bytealt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32 gbt_byteacmp ( const bytea * a , const bytea * b )
|
static int32
|
||||||
|
gbt_byteacmp(const bytea *a, const bytea *b)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
( DatumGetInt32(DirectFunctionCall2(byteacmp,PointerGetDatum(a),PointerGetDatum(b) ) ) );
|
(DatumGetInt32(DirectFunctionCall2(byteacmp, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_vinfo tinfo =
|
static const gbtree_vinfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_bytea,
|
gbt_t_bytea,
|
||||||
FALSE,
|
FALSE,
|
||||||
TRUE,
|
TRUE,
|
||||||
gbt_byteagt,
|
gbt_byteagt,
|
||||||
gbt_byteage,
|
gbt_byteage,
|
||||||
gbt_byteaeq,
|
gbt_byteaeq,
|
||||||
gbt_byteale,
|
gbt_byteale,
|
||||||
gbt_bytealt,
|
gbt_bytealt,
|
||||||
gbt_byteacmp,
|
gbt_byteacmp,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -77,10 +83,11 @@ static const gbtree_vinfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bytea_compress (PG_FUNCTION_ARGS)
|
gbt_bytea_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
PG_RETURN_POINTER ( gbt_var_compress( entry, &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,24 +95,22 @@ gbt_bytea_compress (PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_bytea_consistent(PG_FUNCTION_ARGS)
|
gbt_bytea_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer ( entry->key ) ;
|
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer ( PG_DETOAST_DATUM( entry->key ) );
|
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
void *qtst = ( void * ) DatumGetPointer( PG_GETARG_DATUM(1) );
|
void *qtst = (void *) DatumGetPointer(PG_GETARG_DATUM(1));
|
||||||
void *query = ( void * ) DatumGetByteaP ( PG_GETARG_DATUM(1) );
|
void *query = (void *) DatumGetByteaP(PG_GETARG_DATUM(1));
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( key );
|
GBT_VARKEY_R r = gbt_var_key_readable(key);
|
||||||
|
|
||||||
retval = gbt_var_consistent( &r, query, &strategy, GIST_LEAF(entry), &tinfo );
|
retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo);
|
||||||
|
|
||||||
if ( ktst != key ){
|
if (ktst != key)
|
||||||
pfree ( key );
|
pfree(key);
|
||||||
}
|
if (qtst != query)
|
||||||
if ( qtst != query ){
|
pfree(query);
|
||||||
pfree ( query );
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
|
||||||
PG_RETURN_BOOL(retval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -113,37 +118,40 @@ gbt_bytea_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_bytea_union(PG_FUNCTION_ARGS)
|
gbt_bytea_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector * entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int32 * size = (int *) PG_GETARG_POINTER(1);
|
int32 *size = (int *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_union ( entryvec , size , &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bytea_picksplit(PG_FUNCTION_ARGS)
|
gbt_bytea_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
gbt_var_picksplit ( entryvec, v, &tinfo );
|
|
||||||
PG_RETURN_POINTER(v);
|
gbt_var_picksplit(entryvec, v, &tinfo);
|
||||||
|
PG_RETURN_POINTER(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bytea_same(PG_FUNCTION_ARGS)
|
gbt_bytea_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum d1 = PG_GETARG_DATUM(0);
|
Datum d1 = PG_GETARG_DATUM(0);
|
||||||
Datum d2 = PG_GETARG_DATUM(1);
|
Datum d2 = PG_GETARG_DATUM(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
PG_RETURN_POINTER( gbt_var_same ( result, d1 , d2 , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bytea_penalty(PG_FUNCTION_ARGS)
|
gbt_bytea_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
GISTENTRY * o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY * n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_penalty ( result ,o , n, &tinfo ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
|
||||||
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Cash lower;
|
Cash lower;
|
||||||
Cash upper;
|
Cash upper;
|
||||||
} cashKEY;
|
} cashKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Cash ops
|
** Cash ops
|
||||||
@ -18,59 +18,62 @@ PG_FUNCTION_INFO_V1(gbt_cash_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_cash_penalty);
|
PG_FUNCTION_INFO_V1(gbt_cash_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_cash_same);
|
PG_FUNCTION_INFO_V1(gbt_cash_same);
|
||||||
|
|
||||||
Datum gbt_cash_compress(PG_FUNCTION_ARGS);
|
Datum gbt_cash_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cash_union(PG_FUNCTION_ARGS);
|
Datum gbt_cash_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cash_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_cash_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cash_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_cash_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cash_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_cash_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cash_same(PG_FUNCTION_ARGS);
|
Datum gbt_cash_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
static bool gbt_cashgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_cashgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Cash*)a) > *((Cash*)b) );
|
return (*((Cash *) a) > *((Cash *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_cashge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_cashge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Cash*)a) >= *((Cash*)b) );
|
return (*((Cash *) a) >= *((Cash *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_casheq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_casheq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Cash*)a) == *((Cash*)b) );
|
return (*((Cash *) a) == *((Cash *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_cashle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_cashle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Cash*)a) <= *((Cash*)b) );
|
return (*((Cash *) a) <= *((Cash *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_cashlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_cashlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Cash*)a) < *((Cash*)b) );
|
return (*((Cash *) a) < *((Cash *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_cashkey_cmp(const void *a, const void *b)
|
gbt_cashkey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(Cash*)&(((Nsrt *) a)->t[0]) > *(Cash*)&(((Nsrt *) b)->t[0]) ){
|
if (*(Cash *) &(((Nsrt *) a)->t[0]) > *(Cash *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(Cash *) &(((Nsrt *) a)->t[0]) < *(Cash *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(Cash*)&(((Nsrt *) a)->t[0]) < *(Cash*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_cash,
|
gbt_t_cash,
|
||||||
sizeof(Cash),
|
sizeof(Cash),
|
||||||
gbt_cashgt,
|
gbt_cashgt,
|
||||||
gbt_cashge,
|
gbt_cashge,
|
||||||
gbt_casheq,
|
gbt_casheq,
|
||||||
gbt_cashle,
|
gbt_cashle,
|
||||||
gbt_cashlt,
|
gbt_cashlt,
|
||||||
gbt_cashkey_cmp
|
gbt_cashkey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -82,81 +85,83 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_cash_compress(PG_FUNCTION_ARGS)
|
gbt_cash_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cash_consistent(PG_FUNCTION_ARGS)
|
gbt_cash_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
Cash query = (*((Cash *) PG_GETARG_POINTER(1)));
|
Cash query = (*((Cash *) PG_GETARG_POINTER(1)));
|
||||||
cashKEY *kkk = (cashKEY *) DatumGetPointer(entry->key);
|
cashKEY *kkk = (cashKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cash_union(PG_FUNCTION_ARGS)
|
gbt_cash_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(cashKEY));
|
void *out = palloc(sizeof(cashKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cash_penalty(PG_FUNCTION_ARGS)
|
gbt_cash_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
cashKEY *origentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
cashKEY *origentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
cashKEY *newentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
cashKEY *newentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
Cash res ;
|
Cash res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cash_picksplit(PG_FUNCTION_ARGS)
|
gbt_cash_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cash_same(PG_FUNCTION_ARGS)
|
gbt_cash_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
cashKEY *b1 = (cashKEY *) PG_GETARG_POINTER(0);
|
cashKEY *b1 = (cashKEY *) PG_GETARG_POINTER(0);
|
||||||
cashKEY *b2 = (cashKEY *) PG_GETARG_POINTER(1);
|
cashKEY *b2 = (cashKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
DateADT lower;
|
DateADT lower;
|
||||||
DateADT upper;
|
DateADT upper;
|
||||||
} dateKEY;
|
} dateKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** date ops
|
** date ops
|
||||||
@ -18,46 +18,51 @@ PG_FUNCTION_INFO_V1(gbt_date_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_date_penalty);
|
PG_FUNCTION_INFO_V1(gbt_date_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_date_same);
|
PG_FUNCTION_INFO_V1(gbt_date_same);
|
||||||
|
|
||||||
Datum gbt_date_compress(PG_FUNCTION_ARGS);
|
Datum gbt_date_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_date_union(PG_FUNCTION_ARGS);
|
Datum gbt_date_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_date_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_date_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_date_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_date_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_date_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_date_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_date_same(PG_FUNCTION_ARGS);
|
Datum gbt_date_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
static bool gbt_dategt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_dategt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(date_gt,DateADTGetDatum( *((DateADT*)a) ), DateADTGetDatum( *((DateADT*)b) ) )
|
DirectFunctionCall2(date_gt, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_datege (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_datege(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(date_ge,DateADTGetDatum( *((DateADT*)a) ), DateADTGetDatum( *((DateADT*)b) ) )
|
DirectFunctionCall2(date_ge, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_dateeq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_dateeq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(date_eq,DateADTGetDatum( *((DateADT*)a) ), DateADTGetDatum( *((DateADT*)b) ) )
|
DirectFunctionCall2(date_eq, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_datele (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_datele(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(date_le,DateADTGetDatum( *((DateADT*)a) ), DateADTGetDatum( *((DateADT*)b) ) )
|
DirectFunctionCall2(date_le, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_datelt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_datelt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(date_lt,DateADTGetDatum( *((DateADT*)a) ), DateADTGetDatum( *((DateADT*)b) ) )
|
DirectFunctionCall2(date_lt, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -65,26 +70,24 @@ static bool gbt_datelt (const void *a, const void *b)
|
|||||||
static int
|
static int
|
||||||
gbt_datekey_cmp(const void *a, const void *b)
|
gbt_datekey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
if ( gbt_dategt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
if (gbt_dategt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (gbt_datelt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
if ( gbt_datelt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_date,
|
gbt_t_date,
|
||||||
sizeof(DateADT),
|
sizeof(DateADT),
|
||||||
gbt_dategt,
|
gbt_dategt,
|
||||||
gbt_datege,
|
gbt_datege,
|
||||||
gbt_dateeq,
|
gbt_dateeq,
|
||||||
gbt_datele,
|
gbt_datele,
|
||||||
gbt_datelt,
|
gbt_datelt,
|
||||||
gbt_datekey_cmp
|
gbt_datekey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -97,9 +100,10 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_date_compress(PG_FUNCTION_ARGS)
|
gbt_date_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,86 +111,89 @@ gbt_date_compress(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_date_consistent(PG_FUNCTION_ARGS)
|
gbt_date_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
DateADT query = PG_GETARG_DATEADT( 1 );
|
DateADT query = PG_GETARG_DATEADT(1);
|
||||||
dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
|
dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_date_union(PG_FUNCTION_ARGS)
|
gbt_date_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(dateKEY));
|
void *out = palloc(sizeof(dateKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_date_penalty(PG_FUNCTION_ARGS)
|
gbt_date_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
int32 diff, res ;
|
int32 diff,
|
||||||
|
res;
|
||||||
|
|
||||||
diff = DatumGetInt32(DirectFunctionCall2(
|
diff = DatumGetInt32(DirectFunctionCall2(
|
||||||
date_mi,
|
date_mi,
|
||||||
DateADTGetDatum(newentry->upper),
|
DateADTGetDatum(newentry->upper),
|
||||||
DateADTGetDatum(origentry->upper)));
|
DateADTGetDatum(origentry->upper)));
|
||||||
|
|
||||||
res = Max(diff, 0);
|
res = Max(diff, 0);
|
||||||
|
|
||||||
diff = DatumGetInt32(DirectFunctionCall2(
|
diff = DatumGetInt32(DirectFunctionCall2(
|
||||||
date_mi,
|
date_mi,
|
||||||
DateADTGetDatum(origentry->lower),
|
DateADTGetDatum(origentry->lower),
|
||||||
DateADTGetDatum(newentry->lower)));
|
DateADTGetDatum(newentry->lower)));
|
||||||
|
|
||||||
res += Max(diff, 0);
|
res += Max(diff, 0);
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
diff = DatumGetInt32(DirectFunctionCall2(
|
{
|
||||||
date_mi,
|
diff = DatumGetInt32(DirectFunctionCall2(
|
||||||
DateADTGetDatum(origentry->upper),
|
date_mi,
|
||||||
DateADTGetDatum(origentry->lower)));
|
DateADTGetDatum(origentry->upper),
|
||||||
*result += FLT_MIN ;
|
DateADTGetDatum(origentry->lower)));
|
||||||
*result += (float) ( res / ( (double) ( res + diff ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + diff)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_date_picksplit(PG_FUNCTION_ARGS)
|
gbt_date_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_date_same(PG_FUNCTION_ARGS)
|
gbt_date_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
dateKEY *b1 = (dateKEY *) PG_GETARG_POINTER(0);
|
dateKEY *b1 = (dateKEY *) PG_GETARG_POINTER(0);
|
||||||
dateKEY *b2 = (dateKEY *) PG_GETARG_POINTER(1);
|
dateKEY *b2 = (dateKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct float4key
|
typedef struct float4key
|
||||||
{
|
{
|
||||||
float4 lower;
|
float4 lower;
|
||||||
float4 upper;
|
float4 upper;
|
||||||
} float4KEY;
|
} float4KEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** float4 ops
|
** float4 ops
|
||||||
@ -17,59 +17,62 @@ PG_FUNCTION_INFO_V1(gbt_float4_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_float4_penalty);
|
PG_FUNCTION_INFO_V1(gbt_float4_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_float4_same);
|
PG_FUNCTION_INFO_V1(gbt_float4_same);
|
||||||
|
|
||||||
Datum gbt_float4_compress(PG_FUNCTION_ARGS);
|
Datum gbt_float4_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float4_union(PG_FUNCTION_ARGS);
|
Datum gbt_float4_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float4_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_float4_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float4_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_float4_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float4_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_float4_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float4_same(PG_FUNCTION_ARGS);
|
Datum gbt_float4_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
static bool gbt_float4gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float4gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float4*)a) > *((float4*)b) );
|
return (*((float4 *) a) > *((float4 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float4ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float4ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float4*)a) >= *((float4*)b) );
|
return (*((float4 *) a) >= *((float4 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float4eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float4eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float4*)a) == *((float4*)b) );
|
return (*((float4 *) a) == *((float4 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float4le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float4le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float4*)a) <= *((float4*)b) );
|
return (*((float4 *) a) <= *((float4 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float4lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float4lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float4*)a) < *((float4*)b) );
|
return (*((float4 *) a) < *((float4 *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_float4key_cmp(const void *a, const void *b)
|
gbt_float4key_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(float4*)&(((Nsrt *) a)->t[0]) > *(float4*)&(((Nsrt *) b)->t[0]) ){
|
if (*(float4 *) &(((Nsrt *) a)->t[0]) > *(float4 *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(float4 *) &(((Nsrt *) a)->t[0]) < *(float4 *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(float4*)&(((Nsrt *) a)->t[0]) < *(float4*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_float4,
|
gbt_t_float4,
|
||||||
sizeof(float4),
|
sizeof(float4),
|
||||||
gbt_float4gt,
|
gbt_float4gt,
|
||||||
gbt_float4ge,
|
gbt_float4ge,
|
||||||
gbt_float4eq,
|
gbt_float4eq,
|
||||||
gbt_float4le,
|
gbt_float4le,
|
||||||
gbt_float4lt,
|
gbt_float4lt,
|
||||||
gbt_float4key_cmp
|
gbt_float4key_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -81,80 +84,83 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_float4_compress(PG_FUNCTION_ARGS)
|
gbt_float4_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float4_consistent(PG_FUNCTION_ARGS)
|
gbt_float4_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
float4 query = PG_GETARG_FLOAT4(1);
|
float4 query = PG_GETARG_FLOAT4(1);
|
||||||
float4KEY *kkk = (float4KEY *) DatumGetPointer(entry->key);
|
float4KEY *kkk = (float4KEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float4_union(PG_FUNCTION_ARGS)
|
gbt_float4_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(float4KEY));
|
void *out = palloc(sizeof(float4KEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float4_penalty(PG_FUNCTION_ARGS)
|
gbt_float4_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float4KEY *origentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
float4KEY *origentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
float4KEY *newentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
float4KEY *newentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
float4 res ;
|
float4 res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float4_picksplit(PG_FUNCTION_ARGS)
|
gbt_float4_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float4_same(PG_FUNCTION_ARGS)
|
gbt_float4_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float4KEY *b1 = (float4KEY *) PG_GETARG_POINTER(0);
|
float4KEY *b1 = (float4KEY *) PG_GETARG_POINTER(0);
|
||||||
float4KEY *b2 = (float4KEY *) PG_GETARG_POINTER(1);
|
float4KEY *b2 = (float4KEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct float8key
|
typedef struct float8key
|
||||||
{
|
{
|
||||||
float8 lower;
|
float8 lower;
|
||||||
float8 upper;
|
float8 upper;
|
||||||
} float8KEY;
|
} float8KEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** float8 ops
|
** float8 ops
|
||||||
@ -17,60 +17,63 @@ PG_FUNCTION_INFO_V1(gbt_float8_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_float8_penalty);
|
PG_FUNCTION_INFO_V1(gbt_float8_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_float8_same);
|
PG_FUNCTION_INFO_V1(gbt_float8_same);
|
||||||
|
|
||||||
Datum gbt_float8_compress(PG_FUNCTION_ARGS);
|
Datum gbt_float8_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float8_union(PG_FUNCTION_ARGS);
|
Datum gbt_float8_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float8_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_float8_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float8_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_float8_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float8_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_float8_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_float8_same(PG_FUNCTION_ARGS);
|
Datum gbt_float8_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_float8gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float8gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float8*)a) > *((float8*)b) );
|
return (*((float8 *) a) > *((float8 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float8ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float8ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float8*)a) >= *((float8*)b) );
|
return (*((float8 *) a) >= *((float8 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float8eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float8eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float8*)a) == *((float8*)b) );
|
return (*((float8 *) a) == *((float8 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float8le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float8le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float8*)a) <= *((float8*)b) );
|
return (*((float8 *) a) <= *((float8 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_float8lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_float8lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((float8*)a) < *((float8*)b) );
|
return (*((float8 *) a) < *((float8 *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_float8key_cmp(const void *a, const void *b)
|
gbt_float8key_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(float8*)&(((Nsrt *) a)->t[0]) > *(float8*)&(((Nsrt *) b)->t[0]) ){
|
if (*(float8 *) &(((Nsrt *) a)->t[0]) > *(float8 *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(float8 *) &(((Nsrt *) a)->t[0]) < *(float8 *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(float8*)&(((Nsrt *) a)->t[0]) < *(float8*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_float8,
|
gbt_t_float8,
|
||||||
sizeof(float8),
|
sizeof(float8),
|
||||||
gbt_float8gt,
|
gbt_float8gt,
|
||||||
gbt_float8ge,
|
gbt_float8ge,
|
||||||
gbt_float8eq,
|
gbt_float8eq,
|
||||||
gbt_float8le,
|
gbt_float8le,
|
||||||
gbt_float8lt,
|
gbt_float8lt,
|
||||||
gbt_float8key_cmp
|
gbt_float8key_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -82,9 +85,10 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_float8_compress(PG_FUNCTION_ARGS)
|
gbt_float8_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,70 +96,73 @@ Datum
|
|||||||
gbt_float8_consistent(PG_FUNCTION_ARGS)
|
gbt_float8_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
float8 query = PG_GETARG_FLOAT8(1);
|
float8 query = PG_GETARG_FLOAT8(1);
|
||||||
float8KEY *kkk = (float8KEY *) DatumGetPointer(entry->key);
|
float8KEY *kkk = (float8KEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float8_union(PG_FUNCTION_ARGS)
|
gbt_float8_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(float8KEY));
|
void *out = palloc(sizeof(float8KEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float8_penalty(PG_FUNCTION_ARGS)
|
gbt_float8_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float8KEY *origentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
float8KEY *origentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
float8KEY *newentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
float8KEY *newentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
float8 res ;
|
float8 res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float8_picksplit(PG_FUNCTION_ARGS)
|
gbt_float8_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_float8_same(PG_FUNCTION_ARGS)
|
gbt_float8_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float8KEY *b1 = (float8KEY *) PG_GETARG_POINTER(0);
|
float8KEY *b1 = (float8KEY *) PG_GETARG_POINTER(0);
|
||||||
float8KEY *b2 = (float8KEY *) PG_GETARG_POINTER(1);
|
float8KEY *b2 = (float8KEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ PG_FUNCTION_INFO_V1(gbt_decompress);
|
|||||||
PG_FUNCTION_INFO_V1(gbtreekey_in);
|
PG_FUNCTION_INFO_V1(gbtreekey_in);
|
||||||
PG_FUNCTION_INFO_V1(gbtreekey_out);
|
PG_FUNCTION_INFO_V1(gbtreekey_out);
|
||||||
|
|
||||||
Datum gbt_decompress(PG_FUNCTION_ARGS);
|
Datum gbt_decompress(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* In/Out for keys
|
* In/Out for keys
|
||||||
@ -14,11 +14,11 @@ Datum gbt_decompress(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
gbtreekey_in(PG_FUNCTION_ARGS)
|
gbtreekey_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("<datatype>key_in() not implemented")));
|
errmsg("<datatype>key_in() not implemented")));
|
||||||
|
|
||||||
PG_RETURN_POINTER(NULL);
|
PG_RETURN_POINTER(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "btree_utils_var.h"
|
#include "btree_utils_var.h"
|
||||||
@ -26,10 +26,10 @@ gbtreekey_in(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbtreekey_out(PG_FUNCTION_ARGS)
|
gbtreekey_out(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("<datatype>key_out() not implemented")));
|
errmsg("<datatype>key_out() not implemented")));
|
||||||
PG_RETURN_POINTER(NULL);
|
PG_RETURN_POINTER(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +40,5 @@ gbtreekey_out(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_decompress(PG_FUNCTION_ARGS)
|
gbt_decompress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(PG_GETARG_POINTER(0));
|
PG_RETURN_POINTER(PG_GETARG_POINTER(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,25 +7,25 @@
|
|||||||
|
|
||||||
enum gbtree_type
|
enum gbtree_type
|
||||||
{
|
{
|
||||||
gbt_t_var ,
|
gbt_t_var,
|
||||||
gbt_t_int2 ,
|
gbt_t_int2,
|
||||||
gbt_t_int4 ,
|
gbt_t_int4,
|
||||||
gbt_t_int8 ,
|
gbt_t_int8,
|
||||||
gbt_t_float4 ,
|
gbt_t_float4,
|
||||||
gbt_t_float8 ,
|
gbt_t_float8,
|
||||||
gbt_t_numeric,
|
gbt_t_numeric,
|
||||||
gbt_t_ts,
|
gbt_t_ts,
|
||||||
gbt_t_cash,
|
gbt_t_cash,
|
||||||
gbt_t_oid,
|
gbt_t_oid,
|
||||||
gbt_t_time,
|
gbt_t_time,
|
||||||
gbt_t_date,
|
gbt_t_date,
|
||||||
gbt_t_intv,
|
gbt_t_intv,
|
||||||
gbt_t_macad,
|
gbt_t_macad,
|
||||||
gbt_t_text,
|
gbt_t_text,
|
||||||
gbt_t_bpchar,
|
gbt_t_bpchar,
|
||||||
gbt_t_bytea,
|
gbt_t_bytea,
|
||||||
gbt_t_bit,
|
gbt_t_bit,
|
||||||
gbt_t_inet
|
gbt_t_inet
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -34,6 +34,6 @@ enum gbtree_type
|
|||||||
* Generic btree functions
|
* Generic btree functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Datum gbtreekey_in (PG_FUNCTION_ARGS);
|
Datum gbtreekey_in(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
Datum gbtreekey_out(PG_FUNCTION_ARGS);
|
Datum gbtreekey_out(PG_FUNCTION_ARGS);
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
typedef struct inetkey
|
typedef struct inetkey
|
||||||
{
|
{
|
||||||
double lower;
|
double lower;
|
||||||
double upper;
|
double upper;
|
||||||
} inetKEY;
|
} inetKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** inet ops
|
** inet ops
|
||||||
@ -22,62 +22,65 @@ PG_FUNCTION_INFO_V1(gbt_cidr_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_inet_penalty);
|
PG_FUNCTION_INFO_V1(gbt_inet_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_inet_same);
|
PG_FUNCTION_INFO_V1(gbt_inet_same);
|
||||||
|
|
||||||
Datum gbt_inet_compress(PG_FUNCTION_ARGS);
|
Datum gbt_inet_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cidr_compress(PG_FUNCTION_ARGS);
|
Datum gbt_cidr_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_inet_union(PG_FUNCTION_ARGS);
|
Datum gbt_inet_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_inet_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_inet_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_inet_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_inet_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_cidr_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_cidr_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_inet_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_inet_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_inet_same(PG_FUNCTION_ARGS);
|
Datum gbt_inet_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_inetgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_inetgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((double*)a) > *((double*)b) );
|
return (*((double *) a) > *((double *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_inetge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_inetge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((double*)a) >= *((double*)b) );
|
return (*((double *) a) >= *((double *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_ineteq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_ineteq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((double*)a) == *((double*)b) );
|
return (*((double *) a) == *((double *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_inetle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_inetle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((double*)a) <= *((double*)b) );
|
return (*((double *) a) <= *((double *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_inetlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_inetlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((double*)a) < *((double*)b) );
|
return (*((double *) a) < *((double *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_inetkey_cmp(const void *a, const void *b)
|
gbt_inetkey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(double*)(&((Nsrt *) a)->t[0]) > *(double*)(&((Nsrt *) b)->t[0]) ){
|
if (*(double *) (&((Nsrt *) a)->t[0]) > *(double *) (&((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(double *) (&((Nsrt *) a)->t[0]) < *(double *) (&((Nsrt *) b)->t[0]))
|
||||||
if ( *(double*)(&((Nsrt *) a)->t[0]) < *(double*)(&((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_inet,
|
gbt_t_inet,
|
||||||
sizeof(double),
|
sizeof(double),
|
||||||
gbt_inetgt,
|
gbt_inetgt,
|
||||||
gbt_inetge,
|
gbt_inetge,
|
||||||
gbt_ineteq,
|
gbt_ineteq,
|
||||||
gbt_inetle,
|
gbt_inetle,
|
||||||
gbt_inetlt,
|
gbt_inetlt,
|
||||||
gbt_inetkey_cmp
|
gbt_inetkey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -87,24 +90,25 @@ static const gbtree_ninfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static GISTENTRY *
|
static GISTENTRY *
|
||||||
gbt_inet_compress_inetrnal(GISTENTRY *retval , GISTENTRY *entry , Oid typid)
|
gbt_inet_compress_inetrnal(GISTENTRY *retval, GISTENTRY *entry, Oid typid)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{
|
{
|
||||||
inetKEY *r = (inetKEY *) palloc(sizeof(inetKEY));
|
inetKEY *r = (inetKEY *) palloc(sizeof(inetKEY));
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
|
||||||
r->lower = convert_network_to_scalar(entry->key, typid );
|
|
||||||
r->upper = r->lower ;
|
|
||||||
gistentryinit(*retval, PointerGetDatum(r),
|
|
||||||
entry->rel, entry->page,
|
|
||||||
entry->offset, sizeof(inetKEY), FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
retval = entry;
|
|
||||||
|
|
||||||
return ( retval );
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
|
r->lower = convert_network_to_scalar(entry->key, typid);
|
||||||
|
r->upper = r->lower;
|
||||||
|
gistentryinit(*retval, PointerGetDatum(r),
|
||||||
|
entry->rel, entry->page,
|
||||||
|
entry->offset, sizeof(inetKEY), FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retval = entry;
|
||||||
|
|
||||||
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,113 +116,118 @@ gbt_inet_compress_inetrnal(GISTENTRY *retval , GISTENTRY *entry , Oid typid)
|
|||||||
Datum
|
Datum
|
||||||
gbt_inet_compress(PG_FUNCTION_ARGS)
|
gbt_inet_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_inet_compress_inetrnal(retval ,entry ,INETOID ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_inet_compress_inetrnal(retval, entry, INETOID));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cidr_compress(PG_FUNCTION_ARGS)
|
gbt_cidr_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_inet_compress_inetrnal(retval ,entry ,CIDROID ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_inet_compress_inetrnal(retval, entry, CIDROID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
gbt_inet_consistent_internal (
|
gbt_inet_consistent_internal(
|
||||||
const GISTENTRY * entry,
|
const GISTENTRY *entry,
|
||||||
const double * query,
|
const double *query,
|
||||||
const StrategyNumber * strategy
|
const StrategyNumber *strategy
|
||||||
){
|
)
|
||||||
inetKEY *kkk = (inetKEY *) DatumGetPointer(entry->key);
|
{
|
||||||
GBT_NUMKEY_R key ;
|
inetKEY *kkk = (inetKEY *) DatumGetPointer(entry->key);
|
||||||
|
GBT_NUMKEY_R key;
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
gbt_num_consistent( &key, (void*)query,strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) query, strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_inet_consistent(PG_FUNCTION_ARGS)
|
gbt_inet_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
double query = convert_network_to_scalar( PG_GETARG_DATUM(1) ,INETOID );
|
double query = convert_network_to_scalar(PG_GETARG_DATUM(1), INETOID);
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_inet_consistent_internal ( entry, &query, &strategy )
|
gbt_inet_consistent_internal(entry, &query, &strategy)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_cidr_consistent(PG_FUNCTION_ARGS)
|
gbt_cidr_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
double query = convert_network_to_scalar( PG_GETARG_DATUM(1) ,CIDROID );
|
double query = convert_network_to_scalar(PG_GETARG_DATUM(1), CIDROID);
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_inet_consistent_internal ( entry, &query, &strategy )
|
gbt_inet_consistent_internal(entry, &query, &strategy)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_inet_union(PG_FUNCTION_ARGS)
|
gbt_inet_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(inetKEY));
|
void *out = palloc(sizeof(inetKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_inet_penalty(PG_FUNCTION_ARGS)
|
gbt_inet_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
inetKEY *origentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
inetKEY *origentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
inetKEY *newentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
inetKEY *newentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
double res ;
|
double res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_inet_picksplit(PG_FUNCTION_ARGS)
|
gbt_inet_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_inet_same(PG_FUNCTION_ARGS)
|
gbt_inet_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
inetKEY *b1 = (inetKEY *) PG_GETARG_POINTER(0);
|
inetKEY *b1 = (inetKEY *) PG_GETARG_POINTER(0);
|
||||||
inetKEY *b2 = (inetKEY *) PG_GETARG_POINTER(1);
|
inetKEY *b2 = (inetKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct int16key
|
typedef struct int16key
|
||||||
{
|
{
|
||||||
int16 lower;
|
int16 lower;
|
||||||
int16 upper;
|
int16 upper;
|
||||||
} int16KEY;
|
} int16KEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** int16 ops
|
** int16 ops
|
||||||
@ -17,59 +17,62 @@ PG_FUNCTION_INFO_V1(gbt_int2_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_int2_penalty);
|
PG_FUNCTION_INFO_V1(gbt_int2_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_int2_same);
|
PG_FUNCTION_INFO_V1(gbt_int2_same);
|
||||||
|
|
||||||
Datum gbt_int2_compress(PG_FUNCTION_ARGS);
|
Datum gbt_int2_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int2_union(PG_FUNCTION_ARGS);
|
Datum gbt_int2_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int2_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_int2_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int2_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_int2_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int2_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_int2_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int2_same(PG_FUNCTION_ARGS);
|
Datum gbt_int2_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
static bool gbt_int2gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int2gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int16*)a) > *((int16*)b) );
|
return (*((int16 *) a) > *((int16 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int2ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int2ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int16*)a) >= *((int16*)b) );
|
return (*((int16 *) a) >= *((int16 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int2eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int2eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int16*)a) == *((int16*)b) );
|
return (*((int16 *) a) == *((int16 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int2le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int2le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int16*)a) <= *((int16*)b) );
|
return (*((int16 *) a) <= *((int16 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int2lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int2lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int16*)a) < *((int16*)b) );
|
return (*((int16 *) a) < *((int16 *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_int2key_cmp(const void *a, const void *b)
|
gbt_int2key_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(int16*)(&((Nsrt *) a)->t[0]) > *(int16*)&(((Nsrt *) b)->t[0]) ){
|
if (*(int16 *) (&((Nsrt *) a)->t[0]) > *(int16 *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(int16 *) &(((Nsrt *) a)->t[0]) < *(int16 *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(int16*)&(((Nsrt *) a)->t[0]) < *(int16*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_int2,
|
gbt_t_int2,
|
||||||
sizeof(int16),
|
sizeof(int16),
|
||||||
gbt_int2gt,
|
gbt_int2gt,
|
||||||
gbt_int2ge,
|
gbt_int2ge,
|
||||||
gbt_int2eq,
|
gbt_int2eq,
|
||||||
gbt_int2le,
|
gbt_int2le,
|
||||||
gbt_int2lt,
|
gbt_int2lt,
|
||||||
gbt_int2key_cmp
|
gbt_int2key_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -85,77 +88,81 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_int2_compress(PG_FUNCTION_ARGS)
|
gbt_int2_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int2_consistent(PG_FUNCTION_ARGS)
|
gbt_int2_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
int16 query = PG_GETARG_INT16(1);
|
int16 query = PG_GETARG_INT16(1);
|
||||||
int16KEY *kkk = (int16KEY *) DatumGetPointer(entry->key);
|
int16KEY *kkk = (int16KEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int2_union(PG_FUNCTION_ARGS)
|
gbt_int2_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(int16KEY));
|
void *out = palloc(sizeof(int16KEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int2_penalty(PG_FUNCTION_ARGS)
|
gbt_int2_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int16KEY *origentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
int16KEY *origentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
int16KEY *newentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
int16KEY *newentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
int2 res ;
|
int2 res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int2_picksplit(PG_FUNCTION_ARGS)
|
gbt_int2_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int2_same(PG_FUNCTION_ARGS)
|
gbt_int2_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int16KEY *b1 = (int16KEY *) PG_GETARG_POINTER(0);
|
int16KEY *b1 = (int16KEY *) PG_GETARG_POINTER(0);
|
||||||
int16KEY *b2 = (int16KEY *) PG_GETARG_POINTER(1);
|
int16KEY *b2 = (int16KEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct int32key
|
typedef struct int32key
|
||||||
{
|
{
|
||||||
int32 lower;
|
int32 lower;
|
||||||
int32 upper;
|
int32 upper;
|
||||||
} int32KEY;
|
} int32KEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** int32 ops
|
** int32 ops
|
||||||
@ -17,60 +17,63 @@ PG_FUNCTION_INFO_V1(gbt_int4_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_int4_penalty);
|
PG_FUNCTION_INFO_V1(gbt_int4_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_int4_same);
|
PG_FUNCTION_INFO_V1(gbt_int4_same);
|
||||||
|
|
||||||
Datum gbt_int4_compress(PG_FUNCTION_ARGS);
|
Datum gbt_int4_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int4_union(PG_FUNCTION_ARGS);
|
Datum gbt_int4_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int4_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_int4_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int4_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_int4_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int4_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_int4_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int4_same(PG_FUNCTION_ARGS);
|
Datum gbt_int4_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_int4gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int4gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int32*)a) > *((int32*)b) );
|
return (*((int32 *) a) > *((int32 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int4ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int4ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int32*)a) >= *((int32*)b) );
|
return (*((int32 *) a) >= *((int32 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int4eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int4eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int32*)a) == *((int32*)b) );
|
return (*((int32 *) a) == *((int32 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int4le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int4le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int32*)a) <= *((int32*)b) );
|
return (*((int32 *) a) <= *((int32 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int4lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int4lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int32*)a) < *((int32*)b) );
|
return (*((int32 *) a) < *((int32 *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_int4key_cmp(const void *a, const void *b)
|
gbt_int4key_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(int32*)&(((Nsrt *) a)->t[0]) > *(int32*)&(((Nsrt *) b)->t[0]) ){
|
if (*(int32 *) &(((Nsrt *) a)->t[0]) > *(int32 *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(int32 *) &(((Nsrt *) a)->t[0]) < *(int32 *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(int32*)&(((Nsrt *) a)->t[0]) < *(int32*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_int4,
|
gbt_t_int4,
|
||||||
sizeof(int32),
|
sizeof(int32),
|
||||||
gbt_int4gt,
|
gbt_int4gt,
|
||||||
gbt_int4ge,
|
gbt_int4ge,
|
||||||
gbt_int4eq,
|
gbt_int4eq,
|
||||||
gbt_int4le,
|
gbt_int4le,
|
||||||
gbt_int4lt,
|
gbt_int4lt,
|
||||||
gbt_int4key_cmp
|
gbt_int4key_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -82,9 +85,10 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_int4_compress(PG_FUNCTION_ARGS)
|
gbt_int4_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,68 +96,71 @@ Datum
|
|||||||
gbt_int4_consistent(PG_FUNCTION_ARGS)
|
gbt_int4_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
int32 query = PG_GETARG_INT32(1);
|
int32 query = PG_GETARG_INT32(1);
|
||||||
int32KEY *kkk = (int32KEY *) DatumGetPointer(entry->key);
|
int32KEY *kkk = (int32KEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int4_union(PG_FUNCTION_ARGS)
|
gbt_int4_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc( sizeof(int32KEY) );
|
void *out = palloc(sizeof(int32KEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int4_penalty(PG_FUNCTION_ARGS)
|
gbt_int4_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int32KEY *origentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
int32KEY *origentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
int32KEY *newentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
int32KEY *newentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
int4 res ;
|
int4 res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int4_picksplit(PG_FUNCTION_ARGS)
|
gbt_int4_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int4_same(PG_FUNCTION_ARGS)
|
gbt_int4_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int32KEY *b1 = (int32KEY *) PG_GETARG_POINTER(0);
|
int32KEY *b1 = (int32KEY *) PG_GETARG_POINTER(0);
|
||||||
int32KEY *b2 = (int32KEY *) PG_GETARG_POINTER(1);
|
int32KEY *b2 = (int32KEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct int64key
|
typedef struct int64key
|
||||||
{
|
{
|
||||||
int64 lower;
|
int64 lower;
|
||||||
int64 upper;
|
int64 upper;
|
||||||
} int64KEY;
|
} int64KEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** int64 ops
|
** int64 ops
|
||||||
@ -17,60 +17,63 @@ PG_FUNCTION_INFO_V1(gbt_int8_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_int8_penalty);
|
PG_FUNCTION_INFO_V1(gbt_int8_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_int8_same);
|
PG_FUNCTION_INFO_V1(gbt_int8_same);
|
||||||
|
|
||||||
Datum gbt_int8_compress(PG_FUNCTION_ARGS);
|
Datum gbt_int8_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int8_union(PG_FUNCTION_ARGS);
|
Datum gbt_int8_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int8_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_int8_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int8_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_int8_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int8_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_int8_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_int8_same(PG_FUNCTION_ARGS);
|
Datum gbt_int8_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_int8gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int8gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int64*)a) > *((int64*)b) );
|
return (*((int64 *) a) > *((int64 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int8ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int8ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int64*)a) >= *((int64*)b) );
|
return (*((int64 *) a) >= *((int64 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int8eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int8eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int64*)a) == *((int64*)b) );
|
return (*((int64 *) a) == *((int64 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int8le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int8le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int64*)a) <= *((int64*)b) );
|
return (*((int64 *) a) <= *((int64 *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_int8lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_int8lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((int64*)a) < *((int64*)b) );
|
return (*((int64 *) a) < *((int64 *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_int8key_cmp(const void *a, const void *b)
|
gbt_int8key_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(int64*)&(((Nsrt *) a)->t[0]) > *(int64*)&(((Nsrt *) b)->t[0]) ){
|
if (*(int64 *) &(((Nsrt *) a)->t[0]) > *(int64 *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(int64 *) &(((Nsrt *) a)->t[0]) < *(int64 *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(int64*)&(((Nsrt *) a)->t[0]) < *(int64*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_int8,
|
gbt_t_int8,
|
||||||
sizeof(int64),
|
sizeof(int64),
|
||||||
gbt_int8gt,
|
gbt_int8gt,
|
||||||
gbt_int8ge,
|
gbt_int8ge,
|
||||||
gbt_int8eq,
|
gbt_int8eq,
|
||||||
gbt_int8le,
|
gbt_int8le,
|
||||||
gbt_int8lt,
|
gbt_int8lt,
|
||||||
gbt_int8key_cmp
|
gbt_int8key_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -82,79 +85,82 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_int8_compress(PG_FUNCTION_ARGS)
|
gbt_int8_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int8_consistent(PG_FUNCTION_ARGS)
|
gbt_int8_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
int64 query = PG_GETARG_INT64(1);
|
int64 query = PG_GETARG_INT64(1);
|
||||||
int64KEY *kkk = (int64KEY *) DatumGetPointer(entry->key);
|
int64KEY *kkk = (int64KEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int8_union(PG_FUNCTION_ARGS)
|
gbt_int8_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(int64KEY));
|
void *out = palloc(sizeof(int64KEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int8_penalty(PG_FUNCTION_ARGS)
|
gbt_int8_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int64KEY *origentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
int64KEY *origentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
int64KEY *newentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
int64KEY *newentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
int64 res ;
|
int64 res;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower, newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int8_picksplit(PG_FUNCTION_ARGS)
|
gbt_int8_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_int8_same(PG_FUNCTION_ARGS)
|
gbt_int8_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int64KEY *b1 = (int64KEY *) PG_GETARG_POINTER(0);
|
int64KEY *b1 = (int64KEY *) PG_GETARG_POINTER(0);
|
||||||
int64KEY *b2 = (int64KEY *) PG_GETARG_POINTER(1);
|
int64KEY *b2 = (int64KEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Interval lower, upper;
|
Interval lower,
|
||||||
} intvKEY;
|
upper;
|
||||||
|
} intvKEY;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -18,81 +19,88 @@ PG_FUNCTION_INFO_V1(gbt_intv_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
|
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_intv_same);
|
PG_FUNCTION_INFO_V1(gbt_intv_same);
|
||||||
|
|
||||||
Datum gbt_intv_compress(PG_FUNCTION_ARGS);
|
Datum gbt_intv_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_decompress(PG_FUNCTION_ARGS);
|
Datum gbt_intv_decompress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_union(PG_FUNCTION_ARGS);
|
Datum gbt_intv_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_intv_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_intv_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_intv_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_intv_same(PG_FUNCTION_ARGS);
|
Datum gbt_intv_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_intvgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_intvgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2 ( interval_gt , IntervalPGetDatum ( a ) , IntervalPGetDatum ( b ) ));
|
return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_intvge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_intvge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2 ( interval_ge , IntervalPGetDatum ( a ) , IntervalPGetDatum ( b ) ));
|
return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_intveq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_intveq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2 ( interval_eq , IntervalPGetDatum ( a ) , IntervalPGetDatum ( b ) ));
|
return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_intvle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_intvle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2 ( interval_le , IntervalPGetDatum ( a ) , IntervalPGetDatum ( b ) ));
|
return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_intvlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_intvlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2 ( interval_lt , IntervalPGetDatum ( a ) , IntervalPGetDatum ( b ) ));
|
return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_intvkey_cmp(const void *a, const void *b)
|
gbt_intvkey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetInt32 (
|
return DatumGetInt32(
|
||||||
DirectFunctionCall2 ( interval_cmp ,
|
DirectFunctionCall2(interval_cmp,
|
||||||
IntervalPGetDatum(((Nsrt *) a)->t) ,
|
IntervalPGetDatum(((Nsrt *) a)->t),
|
||||||
IntervalPGetDatum(((Nsrt *) b)->t)
|
IntervalPGetDatum(((Nsrt *) b)->t)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static double intr2num ( const Interval * i )
|
static double
|
||||||
|
intr2num(const Interval *i)
|
||||||
{
|
{
|
||||||
double ret = 0.0;
|
double ret = 0.0;
|
||||||
struct pg_tm tm;
|
struct pg_tm tm;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
interval2tm( *i, &tm, &fsec);
|
|
||||||
ret += ( tm.tm_year * 360.0 * 86400.0 ) ;
|
|
||||||
ret += ( tm.tm_mon * 12.0 * 86400.0 ) ;
|
|
||||||
ret += ( tm.tm_mday * 86400.0 ) ;
|
|
||||||
ret += ( tm.tm_hour * 3600.0 ) ;
|
|
||||||
ret += ( tm.tm_min * 60.0 ) ;
|
|
||||||
ret += ( tm.tm_sec ) ;
|
|
||||||
ret += ( fsec / 1000000.0 );
|
|
||||||
|
|
||||||
return ( ret );
|
interval2tm(*i, &tm, &fsec);
|
||||||
|
ret += (tm.tm_year * 360.0 * 86400.0);
|
||||||
|
ret += (tm.tm_mon * 12.0 * 86400.0);
|
||||||
|
ret += (tm.tm_mday * 86400.0);
|
||||||
|
ret += (tm.tm_hour * 3600.0);
|
||||||
|
ret += (tm.tm_min * 60.0);
|
||||||
|
ret += (tm.tm_sec);
|
||||||
|
ret += (fsec / 1000000.0);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INTERVALSIZE 12
|
#define INTERVALSIZE 12
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_intv,
|
gbt_t_intv,
|
||||||
sizeof(Interval),
|
sizeof(Interval),
|
||||||
gbt_intvgt,
|
gbt_intvgt,
|
||||||
gbt_intvge,
|
gbt_intvge,
|
||||||
gbt_intveq,
|
gbt_intveq,
|
||||||
gbt_intvle,
|
gbt_intvle,
|
||||||
gbt_intvlt,
|
gbt_intvlt,
|
||||||
gbt_intvkey_cmp
|
gbt_intvkey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -104,126 +112,137 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_intv_compress(PG_FUNCTION_ARGS)
|
gbt_intv_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = entry;
|
GISTENTRY *retval = entry;
|
||||||
if ( entry->leafkey || INTERVALSIZE != sizeof(Interval) ) {
|
|
||||||
char *r = ( char * ) palloc(2 * INTERVALSIZE);
|
|
||||||
|
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
|
||||||
|
{
|
||||||
|
char *r = (char *) palloc(2 * INTERVALSIZE);
|
||||||
|
|
||||||
if ( entry->leafkey ) {
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
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, 2 * INTERVALSIZE, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(retval);
|
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, 2 * INTERVALSIZE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(retval);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_decompress(PG_FUNCTION_ARGS)
|
gbt_intv_decompress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = entry;
|
GISTENTRY *retval = entry;
|
||||||
|
|
||||||
if ( INTERVALSIZE != sizeof(Interval) ) {
|
if (INTERVALSIZE != sizeof(Interval))
|
||||||
intvKEY *r = palloc(sizeof(intvKEY));
|
{
|
||||||
char *key = DatumGetPointer(entry->key);
|
intvKEY *r = palloc(sizeof(intvKEY));
|
||||||
|
char *key = DatumGetPointer(entry->key);
|
||||||
|
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
memcpy( &r->lower, key, INTERVALSIZE);
|
memcpy(&r->lower, key, INTERVALSIZE);
|
||||||
memcpy( &r->upper, key+ INTERVALSIZE, INTERVALSIZE);
|
memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
|
||||||
|
|
||||||
gistentryinit(*retval, PointerGetDatum(r),
|
gistentryinit(*retval, PointerGetDatum(r),
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, sizeof(intvKEY), FALSE);
|
entry->offset, sizeof(intvKEY), FALSE);
|
||||||
}
|
}
|
||||||
PG_RETURN_POINTER(retval);
|
PG_RETURN_POINTER(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_consistent(PG_FUNCTION_ARGS)
|
gbt_intv_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
Interval *query = PG_GETARG_INTERVAL_P(1);
|
Interval *query = PG_GETARG_INTERVAL_P(1);
|
||||||
intvKEY *kkk = (intvKEY *) DatumGetPointer(entry->key);
|
intvKEY *kkk = (intvKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)query ,&strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_union(PG_FUNCTION_ARGS)
|
gbt_intv_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(intvKEY));
|
void *out = palloc(sizeof(intvKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_penalty(PG_FUNCTION_ARGS)
|
gbt_intv_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
intvKEY *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
intvKEY *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
intvKEY *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
intvKEY *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
double iorg[2], inew[2], res;
|
double iorg[2],
|
||||||
|
inew[2],
|
||||||
|
res;
|
||||||
|
|
||||||
iorg[0] = intr2num ( &origentry->lower );
|
iorg[0] = intr2num(&origentry->lower);
|
||||||
iorg[1] = intr2num ( &origentry->upper );
|
iorg[1] = intr2num(&origentry->upper);
|
||||||
inew[0] = intr2num ( &newentry->lower );
|
inew[0] = intr2num(&newentry->lower);
|
||||||
inew[1] = intr2num ( &newentry->upper );
|
inew[1] = intr2num(&newentry->upper);
|
||||||
|
|
||||||
penalty_range_enlarge ( iorg[0], iorg[1], inew[0], inew[1] );
|
penalty_range_enlarge(iorg[0], iorg[1], inew[0], inew[1]);
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( res + iorg[1] - iorg[0] ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / (res + iorg[1] - iorg[0]));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_picksplit(PG_FUNCTION_ARGS)
|
gbt_intv_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_intv_same(PG_FUNCTION_ARGS)
|
gbt_intv_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
intvKEY *b1 = (intvKEY *) PG_GETARG_POINTER(0);
|
intvKEY *b1 = (intvKEY *) PG_GETARG_POINTER(0);
|
||||||
intvKEY *b2 = (intvKEY *) PG_GETARG_POINTER(1);
|
intvKEY *b2 = (intvKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
macaddr lower;
|
macaddr lower;
|
||||||
macaddr upper;
|
macaddr upper;
|
||||||
} macKEY;
|
} macKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** OID ops
|
** OID ops
|
||||||
@ -19,62 +19,67 @@ PG_FUNCTION_INFO_V1(gbt_macad_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_macad_penalty);
|
PG_FUNCTION_INFO_V1(gbt_macad_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_macad_same);
|
PG_FUNCTION_INFO_V1(gbt_macad_same);
|
||||||
|
|
||||||
Datum gbt_macad_compress(PG_FUNCTION_ARGS);
|
Datum gbt_macad_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_macad_union(PG_FUNCTION_ARGS);
|
Datum gbt_macad_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_macad_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_macad_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_macad_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_macad_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_macad_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_macad_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_macad_same(PG_FUNCTION_ARGS);
|
Datum gbt_macad_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_macadgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_macadgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2(macaddr_gt,PointerGetDatum(a),PointerGetDatum(b)));
|
return DatumGetBool(DirectFunctionCall2(macaddr_gt, PointerGetDatum(a), PointerGetDatum(b)));
|
||||||
}
|
}
|
||||||
static bool gbt_macadge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_macadge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2(macaddr_ge,PointerGetDatum(a),PointerGetDatum(b)));
|
return DatumGetBool(DirectFunctionCall2(macaddr_ge, PointerGetDatum(a), PointerGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_macadeq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_macadeq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2(macaddr_eq,PointerGetDatum(a),PointerGetDatum(b)));
|
return DatumGetBool(DirectFunctionCall2(macaddr_eq, PointerGetDatum(a), PointerGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_macadle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_macadle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2(macaddr_le,PointerGetDatum(a),PointerGetDatum(b)));
|
return DatumGetBool(DirectFunctionCall2(macaddr_le, PointerGetDatum(a), PointerGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_macadlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_macadlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(DirectFunctionCall2(macaddr_lt,PointerGetDatum(a),PointerGetDatum(b)));
|
return DatumGetBool(DirectFunctionCall2(macaddr_lt, PointerGetDatum(a), PointerGetDatum(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_macadkey_cmp(const void *a, const void *b)
|
gbt_macadkey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetInt32(
|
return DatumGetInt32(
|
||||||
DirectFunctionCall2(
|
DirectFunctionCall2(
|
||||||
macaddr_cmp ,
|
macaddr_cmp,
|
||||||
PointerGetDatum (&((Nsrt *) a)->t[0]),
|
PointerGetDatum(&((Nsrt *) a)->t[0]),
|
||||||
PointerGetDatum (&((Nsrt *) b)->t[0])
|
PointerGetDatum(&((Nsrt *) b)->t[0])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_macad,
|
gbt_t_macad,
|
||||||
sizeof(macaddr),
|
sizeof(macaddr),
|
||||||
gbt_macadgt,
|
gbt_macadgt,
|
||||||
gbt_macadge,
|
gbt_macadge,
|
||||||
gbt_macadeq,
|
gbt_macadeq,
|
||||||
gbt_macadle,
|
gbt_macadle,
|
||||||
gbt_macadlt,
|
gbt_macadlt,
|
||||||
gbt_macadkey_cmp
|
gbt_macadkey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -84,14 +89,16 @@ static const gbtree_ninfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static uint64 mac_2_uint64 ( macaddr * m ){
|
static uint64
|
||||||
unsigned char * mi = ( unsigned char * ) m;
|
mac_2_uint64(macaddr *m)
|
||||||
uint64 res = 0;
|
{
|
||||||
int i;
|
unsigned char *mi = (unsigned char *) m;
|
||||||
for (i=0; i<6; i++ ){
|
uint64 res = 0;
|
||||||
res += ( ( (uint64) mi[i] ) << ( (uint64) ( (5-i)*8 ) ) );
|
int i;
|
||||||
}
|
|
||||||
return res;
|
for (i = 0; i < 6; i++)
|
||||||
|
res += (((uint64) mi[i]) << ((uint64) ((5 - i) * 8)));
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,9 +106,10 @@ static uint64 mac_2_uint64 ( macaddr * m ){
|
|||||||
Datum
|
Datum
|
||||||
gbt_macad_compress(PG_FUNCTION_ARGS)
|
gbt_macad_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,76 +117,79 @@ Datum
|
|||||||
gbt_macad_consistent(PG_FUNCTION_ARGS)
|
gbt_macad_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
macaddr *query = (macaddr *) PG_GETARG_POINTER(1);
|
macaddr *query = (macaddr *) PG_GETARG_POINTER(1);
|
||||||
macKEY *kkk = (macKEY *) DatumGetPointer(entry->key);
|
macKEY *kkk = (macKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_macad_union(PG_FUNCTION_ARGS)
|
gbt_macad_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(macKEY));
|
void *out = palloc(sizeof(macKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_macad_penalty(PG_FUNCTION_ARGS)
|
gbt_macad_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
macKEY *origentry = (macKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
macKEY *origentry = (macKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
macKEY *newentry = (macKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
macKEY *newentry = (macKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
uint64 iorg[2], inew[2];
|
uint64 iorg[2],
|
||||||
uint64 res;
|
inew[2];
|
||||||
|
uint64 res;
|
||||||
|
|
||||||
iorg[0] = mac_2_uint64 ( &origentry->lower );
|
iorg[0] = mac_2_uint64(&origentry->lower);
|
||||||
iorg[1] = mac_2_uint64 ( &origentry->upper );
|
iorg[1] = mac_2_uint64(&origentry->upper);
|
||||||
inew[0] = mac_2_uint64 ( &newentry->lower );
|
inew[0] = mac_2_uint64(&newentry->lower);
|
||||||
inew[1] = mac_2_uint64 ( &newentry->upper );
|
inew[1] = mac_2_uint64(&newentry->upper);
|
||||||
|
|
||||||
penalty_range_enlarge ( iorg[0], iorg[1], inew[0], inew[1] );
|
penalty_range_enlarge(iorg[0], iorg[1], inew[0], inew[1]);
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( ( (double)res ) / ( (double)res + (double)iorg[1] - (double)iorg[0] ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (((double) res) / ((double) res + (double) iorg[1] - (double) iorg[0]));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_macad_picksplit(PG_FUNCTION_ARGS)
|
gbt_macad_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_macad_same(PG_FUNCTION_ARGS)
|
gbt_macad_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
macKEY *b1 = (macKEY *) PG_GETARG_POINTER(0);
|
macKEY *b1 = (macKEY *) PG_GETARG_POINTER(0);
|
||||||
macKEY *b2 = (macKEY *) PG_GETARG_POINTER(1);
|
macKEY *b2 = (macKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,61 +13,67 @@ PG_FUNCTION_INFO_V1(gbt_numeric_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
|
PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_numeric_same);
|
PG_FUNCTION_INFO_V1(gbt_numeric_same);
|
||||||
|
|
||||||
Datum gbt_numeric_compress(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_numeric_union(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_numeric_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_numeric_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_numeric_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_numeric_same(PG_FUNCTION_ARGS);
|
Datum gbt_numeric_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
/* define for comparison */
|
/* define for comparison */
|
||||||
|
|
||||||
static bool gbt_numeric_gt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_numeric_gt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( numeric_gt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(numeric_gt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_numeric_ge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_numeric_ge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( numeric_ge ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(numeric_ge, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_numeric_eq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_numeric_eq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( numeric_eq ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(numeric_eq, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_numeric_le (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_numeric_le(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( numeric_le ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(numeric_le, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_numeric_lt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_numeric_lt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( numeric_lt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(numeric_lt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32 gbt_numeric_cmp ( const bytea * a , const bytea * b )
|
static int32
|
||||||
|
gbt_numeric_cmp(const bytea *a, const bytea *b)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
( DatumGetInt32(DirectFunctionCall2(numeric_cmp,PointerGetDatum(a),PointerGetDatum(b) ) ) );
|
(DatumGetInt32(DirectFunctionCall2(numeric_cmp, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_vinfo tinfo =
|
static const gbtree_vinfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_numeric,
|
gbt_t_numeric,
|
||||||
FALSE,
|
FALSE,
|
||||||
FALSE,
|
FALSE,
|
||||||
gbt_numeric_gt,
|
gbt_numeric_gt,
|
||||||
gbt_numeric_ge,
|
gbt_numeric_ge,
|
||||||
gbt_numeric_eq,
|
gbt_numeric_eq,
|
||||||
gbt_numeric_le,
|
gbt_numeric_le,
|
||||||
gbt_numeric_lt,
|
gbt_numeric_lt,
|
||||||
gbt_numeric_cmp,
|
gbt_numeric_cmp,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -77,10 +83,11 @@ static const gbtree_vinfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_numeric_compress (PG_FUNCTION_ARGS)
|
gbt_numeric_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
PG_RETURN_POINTER ( gbt_var_compress( entry, &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,24 +96,22 @@ Datum
|
|||||||
gbt_numeric_consistent(PG_FUNCTION_ARGS)
|
gbt_numeric_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer ( entry->key ) ;
|
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer ( PG_DETOAST_DATUM( entry->key ) );
|
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
void *qtst = ( void * ) DatumGetPointer ( PG_GETARG_DATUM(1) );
|
void *qtst = (void *) DatumGetPointer(PG_GETARG_DATUM(1));
|
||||||
void *query = ( void * ) DatumGetNumeric ( PG_GETARG_DATUM(1) );
|
void *query = (void *) DatumGetNumeric(PG_GETARG_DATUM(1));
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( key );
|
GBT_VARKEY_R r = gbt_var_key_readable(key);
|
||||||
|
|
||||||
retval = gbt_var_consistent( &r, query, &strategy, GIST_LEAF(entry), &tinfo );
|
retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo);
|
||||||
|
|
||||||
if ( ktst != key ){
|
if (ktst != key)
|
||||||
pfree ( key );
|
pfree(key);
|
||||||
}
|
if (qtst != query)
|
||||||
if ( qtst != query ){
|
pfree(query);
|
||||||
pfree ( query );
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
|
||||||
PG_RETURN_BOOL(retval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -114,104 +119,110 @@ gbt_numeric_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_numeric_union(PG_FUNCTION_ARGS)
|
gbt_numeric_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int32 * size = (int *) PG_GETARG_POINTER(1);
|
int32 *size = (int *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_union ( entryvec , size , &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_numeric_same(PG_FUNCTION_ARGS)
|
gbt_numeric_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum d1 = PG_GETARG_DATUM(0);
|
Datum d1 = PG_GETARG_DATUM(0);
|
||||||
Datum d2 = PG_GETARG_DATUM(1);
|
Datum d2 = PG_GETARG_DATUM(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
PG_RETURN_POINTER( gbt_var_same ( result, d1 , d2 , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_numeric_penalty (PG_FUNCTION_ARGS)
|
gbt_numeric_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY * o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY * n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
Numeric us, os, ds ;
|
Numeric us,
|
||||||
|
os,
|
||||||
|
ds;
|
||||||
|
|
||||||
GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
|
GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
|
||||||
GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
|
GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
|
||||||
Datum uni ;
|
Datum uni;
|
||||||
GBT_VARKEY_R rk , ok, uk ;
|
GBT_VARKEY_R rk,
|
||||||
|
ok,
|
||||||
|
uk;
|
||||||
|
|
||||||
rk = gbt_var_key_readable ( org );
|
rk = gbt_var_key_readable(org);
|
||||||
uni = PointerGetDatum( gbt_var_key_copy( &rk, TRUE ) );
|
uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE));
|
||||||
gbt_var_bin_union ( &uni , newe, &tinfo );
|
gbt_var_bin_union(&uni, newe, &tinfo);
|
||||||
ok = gbt_var_key_readable ( org );
|
ok = gbt_var_key_readable(org);
|
||||||
uk = gbt_var_key_readable ( (GBT_VARKEY *) DatumGetPointer(uni) );
|
uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
|
||||||
|
|
||||||
us = DatumGetNumeric(DirectFunctionCall2(
|
us = DatumGetNumeric(DirectFunctionCall2(
|
||||||
numeric_sub,
|
numeric_sub,
|
||||||
PointerGetDatum(uk.upper),
|
PointerGetDatum(uk.upper),
|
||||||
PointerGetDatum(uk.lower)
|
PointerGetDatum(uk.lower)
|
||||||
));
|
));
|
||||||
|
|
||||||
pfree ( DatumGetPointer(uni) );
|
pfree(DatumGetPointer(uni));
|
||||||
|
|
||||||
os = DatumGetNumeric(DirectFunctionCall2(
|
os = DatumGetNumeric(DirectFunctionCall2(
|
||||||
numeric_sub,
|
numeric_sub,
|
||||||
PointerGetDatum(ok.upper),
|
PointerGetDatum(ok.upper),
|
||||||
PointerGetDatum(ok.lower)
|
PointerGetDatum(ok.lower)
|
||||||
));
|
));
|
||||||
|
|
||||||
ds = DatumGetNumeric(DirectFunctionCall2(
|
ds = DatumGetNumeric(DirectFunctionCall2(
|
||||||
numeric_sub,
|
numeric_sub,
|
||||||
NumericGetDatum(us),
|
NumericGetDatum(us),
|
||||||
NumericGetDatum(os)
|
NumericGetDatum(os)
|
||||||
));
|
));
|
||||||
|
|
||||||
pfree ( os );
|
pfree(os);
|
||||||
|
|
||||||
if ( NUMERIC_IS_NAN( us ) )
|
if (NUMERIC_IS_NAN(us))
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( NUMERIC_IS_NAN( os ) )
|
if (NUMERIC_IS_NAN(os))
|
||||||
{
|
*result = 0.0;
|
||||||
*result = 0.0;
|
else
|
||||||
} else {
|
*result = 1.0;
|
||||||
*result = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
Numeric nul = DatumGetNumeric(DirectFunctionCall1( int4_numeric , Int32GetDatum (0) ) );
|
Numeric nul = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0)));
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( DirectFunctionCall2( numeric_gt , NumericGetDatum(ds), NumericGetDatum(nul) ) )
|
if (DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul)))
|
||||||
{
|
{
|
||||||
|
|
||||||
*result += FLT_MIN ;
|
*result += FLT_MIN;
|
||||||
os = DatumGetNumeric(DirectFunctionCall2(
|
os = DatumGetNumeric(DirectFunctionCall2(
|
||||||
numeric_div,
|
numeric_div,
|
||||||
NumericGetDatum(ds),
|
NumericGetDatum(ds),
|
||||||
NumericGetDatum(us)
|
NumericGetDatum(us)
|
||||||
));
|
));
|
||||||
*result += ( float4 ) DatumGetFloat8( DirectFunctionCall1( numeric_float8_no_overflow , NumericGetDatum(os) ) );
|
*result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
|
||||||
pfree ( os );
|
pfree(os);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree ( nul );
|
pfree(nul);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( *result > 0 )
|
if (*result > 0)
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
|
||||||
pfree ( us );
|
pfree(us);
|
||||||
pfree ( ds );
|
pfree(ds);
|
||||||
|
|
||||||
PG_RETURN_POINTER( result );
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,9 +230,9 @@ gbt_numeric_penalty (PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_numeric_picksplit(PG_FUNCTION_ARGS)
|
gbt_numeric_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
gbt_var_picksplit ( entryvec, v, &tinfo );
|
|
||||||
PG_RETURN_POINTER(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
gbt_var_picksplit(entryvec, v, &tinfo);
|
||||||
|
PG_RETURN_POINTER(v);
|
||||||
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Oid lower;
|
Oid lower;
|
||||||
Oid upper;
|
Oid upper;
|
||||||
} oidKEY;
|
} oidKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** OID ops
|
** OID ops
|
||||||
@ -17,60 +17,63 @@ PG_FUNCTION_INFO_V1(gbt_oid_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_oid_penalty);
|
PG_FUNCTION_INFO_V1(gbt_oid_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_oid_same);
|
PG_FUNCTION_INFO_V1(gbt_oid_same);
|
||||||
|
|
||||||
Datum gbt_oid_compress(PG_FUNCTION_ARGS);
|
Datum gbt_oid_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_oid_union(PG_FUNCTION_ARGS);
|
Datum gbt_oid_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_oid_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_oid_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_oid_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_oid_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_oid_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_oid_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_oid_same(PG_FUNCTION_ARGS);
|
Datum gbt_oid_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_oidgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_oidgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Oid*)a) > *((Oid*)b) );
|
return (*((Oid *) a) > *((Oid *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_oidge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_oidge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Oid*)a) >= *((Oid*)b) );
|
return (*((Oid *) a) >= *((Oid *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_oideq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_oideq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Oid*)a) == *((Oid*)b) );
|
return (*((Oid *) a) == *((Oid *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_oidle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_oidle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Oid*)a) <= *((Oid*)b) );
|
return (*((Oid *) a) <= *((Oid *) b));
|
||||||
}
|
}
|
||||||
static bool gbt_oidlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_oidlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( *((Oid*)a) < *((Oid*)b) );
|
return (*((Oid *) a) < *((Oid *) b));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_oidkey_cmp(const void *a, const void *b)
|
gbt_oidkey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( *(Oid*)&(((Nsrt *) a)->t[0]) > *(Oid*)&(((Nsrt *) b)->t[0]) ){
|
if (*(Oid *) &(((Nsrt *) a)->t[0]) > *(Oid *) &(((Nsrt *) b)->t[0]))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (*(Oid *) &(((Nsrt *) a)->t[0]) < *(Oid *) &(((Nsrt *) b)->t[0]))
|
||||||
if ( *(Oid*)&(((Nsrt *) a)->t[0]) < *(Oid*)&(((Nsrt *) b)->t[0]) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_oid,
|
gbt_t_oid,
|
||||||
sizeof(Oid),
|
sizeof(Oid),
|
||||||
gbt_oidgt,
|
gbt_oidgt,
|
||||||
gbt_oidge,
|
gbt_oidge,
|
||||||
gbt_oideq,
|
gbt_oideq,
|
||||||
gbt_oidle,
|
gbt_oidle,
|
||||||
gbt_oidlt,
|
gbt_oidlt,
|
||||||
gbt_oidkey_cmp
|
gbt_oidkey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -82,9 +85,10 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_oid_compress(PG_FUNCTION_ARGS)
|
gbt_oid_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,69 +96,72 @@ Datum
|
|||||||
gbt_oid_consistent(PG_FUNCTION_ARGS)
|
gbt_oid_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
Oid query = PG_GETARG_OID(1);
|
Oid query = PG_GETARG_OID(1);
|
||||||
oidKEY *kkk = (oidKEY *) DatumGetPointer(entry->key);
|
oidKEY *kkk = (oidKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
);
|
|
||||||
|
PG_RETURN_BOOL(
|
||||||
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_oid_union(PG_FUNCTION_ARGS)
|
gbt_oid_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(oidKEY));
|
void *out = palloc(sizeof(oidKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_oid_penalty(PG_FUNCTION_ARGS)
|
gbt_oid_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
oidKEY *origentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
oidKEY *origentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
oidKEY *newentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
oidKEY *newentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
Oid res = 0 ;
|
Oid res = 0;
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
penalty_range_enlarge ( origentry->lower, origentry->upper, newentry->lower , newentry->upper );
|
penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper);
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
*result += FLT_MIN ;
|
{
|
||||||
*result += (float) ( res / ( (double) ( res + origentry->upper - origentry->lower ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + origentry->upper - origentry->lower)));
|
||||||
}
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_oid_picksplit(PG_FUNCTION_ARGS)
|
gbt_oid_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_oid_same(PG_FUNCTION_ARGS)
|
gbt_oid_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
oidKEY *b1 = (oidKEY *) PG_GETARG_POINTER(0);
|
oidKEY *b1 = (oidKEY *) PG_GETARG_POINTER(0);
|
||||||
oidKEY *b2 = (oidKEY *) PG_GETARG_POINTER(1);
|
oidKEY *b2 = (oidKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -14,46 +14,52 @@ PG_FUNCTION_INFO_V1(gbt_bpchar_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_text_penalty);
|
PG_FUNCTION_INFO_V1(gbt_text_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_text_same);
|
PG_FUNCTION_INFO_V1(gbt_text_same);
|
||||||
|
|
||||||
Datum gbt_text_compress(PG_FUNCTION_ARGS);
|
Datum gbt_text_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bpchar_compress(PG_FUNCTION_ARGS);
|
Datum gbt_bpchar_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_text_union(PG_FUNCTION_ARGS);
|
Datum gbt_text_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_text_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_text_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_text_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_text_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_bpchar_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_bpchar_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_text_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_text_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_text_same(PG_FUNCTION_ARGS);
|
Datum gbt_text_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
/* define for comparison */
|
/* define for comparison */
|
||||||
|
|
||||||
static bool gbt_textgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_textgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( text_gt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(text_gt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_textge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_textge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( text_ge ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(text_ge, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_texteq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_texteq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( texteq ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(texteq, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_textle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_textle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( text_le ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(text_le, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_textlt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_textlt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ( DatumGetBool(DirectFunctionCall2( text_lt ,PointerGetDatum( a ),PointerGetDatum( b ) ) ) );
|
return (DatumGetBool(DirectFunctionCall2(text_lt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 gbt_textcmp ( const bytea * a , const bytea * b )
|
static int32
|
||||||
|
gbt_textcmp(const bytea *a, const bytea *b)
|
||||||
{
|
{
|
||||||
return strcmp( VARDATA(a), VARDATA(b) );
|
return strcmp(VARDATA(a), VARDATA(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -62,47 +68,48 @@ static int32 gbt_textcmp ( const bytea * a , const bytea * b )
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static bytea *
|
static bytea *
|
||||||
gbt_text_xfrm ( bytea * leaf )
|
gbt_text_xfrm(bytea *leaf)
|
||||||
{
|
{
|
||||||
bytea * out = leaf;
|
bytea *out = leaf;
|
||||||
int32 ilen = VARSIZE (leaf) - VARHDRSZ;
|
int32 ilen = VARSIZE(leaf) - VARHDRSZ;
|
||||||
int32 olen ;
|
int32 olen;
|
||||||
char * sin;
|
char *sin;
|
||||||
char * sou;
|
char *sou;
|
||||||
|
|
||||||
sin = palloc(ilen + 1);
|
sin = palloc(ilen + 1);
|
||||||
memcpy (sin, (void*) VARDATA(leaf) ,ilen );
|
memcpy(sin, (void *) VARDATA(leaf), ilen);
|
||||||
sin[ilen] = '\0';
|
sin[ilen] = '\0';
|
||||||
|
|
||||||
olen = strxfrm ( NULL, &sin[0], 0 ) + 1;
|
olen = strxfrm(NULL, &sin[0], 0) + 1;
|
||||||
sou = palloc ( olen );
|
sou = palloc(olen);
|
||||||
olen = strxfrm ( sou , &sin[0] , olen );
|
olen = strxfrm(sou, &sin[0], olen);
|
||||||
olen += VARHDRSZ;
|
olen += VARHDRSZ;
|
||||||
out = palloc ( olen + 1 );
|
out = palloc(olen + 1);
|
||||||
out->vl_len = olen+1;
|
out->vl_len = olen + 1;
|
||||||
memcpy( (void*) VARDATA(out), sou, olen-VARHDRSZ );
|
memcpy((void *) VARDATA(out), sou, olen - VARHDRSZ);
|
||||||
((char*)out)[olen] = '\0';
|
((char *) out)[olen] = '\0';
|
||||||
|
|
||||||
pfree(sou);
|
pfree(sou);
|
||||||
pfree(sin);
|
pfree(sin);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GBT_VARKEY * gbt_text_l2n ( GBT_VARKEY * leaf )
|
static GBT_VARKEY *
|
||||||
|
gbt_text_l2n(GBT_VARKEY * leaf)
|
||||||
{
|
{
|
||||||
|
|
||||||
GBT_VARKEY *out = leaf ;
|
GBT_VARKEY *out = leaf;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( leaf );
|
GBT_VARKEY_R r = gbt_var_key_readable(leaf);
|
||||||
bytea * o ;
|
bytea *o;
|
||||||
|
|
||||||
o = gbt_text_xfrm ( r.lower );
|
o = gbt_text_xfrm(r.lower);
|
||||||
r.lower = r.upper = o;
|
r.lower = r.upper = o;
|
||||||
out = gbt_var_key_copy ( &r , TRUE );
|
out = gbt_var_key_copy(&r, TRUE);
|
||||||
pfree(o);
|
pfree(o);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,16 +119,16 @@ static GBT_VARKEY * gbt_text_l2n ( GBT_VARKEY * leaf )
|
|||||||
|
|
||||||
static const gbtree_vinfo tinfo =
|
static const gbtree_vinfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_text,
|
gbt_t_text,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
gbt_textgt,
|
gbt_textgt,
|
||||||
gbt_textge,
|
gbt_textge,
|
||||||
gbt_texteq,
|
gbt_texteq,
|
||||||
gbt_textle,
|
gbt_textle,
|
||||||
gbt_textlt,
|
gbt_textlt,
|
||||||
gbt_textcmp,
|
gbt_textcmp,
|
||||||
gbt_text_l2n
|
gbt_text_l2n
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -132,36 +139,38 @@ static const gbtree_vinfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_text_compress (PG_FUNCTION_ARGS)
|
gbt_text_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
PG_RETURN_POINTER ( gbt_var_compress( entry, &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bpchar_compress (PG_FUNCTION_ARGS)
|
gbt_bpchar_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY * retval ;
|
GISTENTRY *retval;
|
||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{
|
{
|
||||||
|
|
||||||
Datum d = DirectFunctionCall1 ( rtrim1, entry->key );
|
Datum d = DirectFunctionCall1(rtrim1, entry->key);
|
||||||
GISTENTRY * trim = palloc(sizeof(GISTENTRY));
|
GISTENTRY *trim = palloc(sizeof(GISTENTRY));
|
||||||
|
|
||||||
gistentryinit(*trim, d ,
|
gistentryinit(*trim, d,
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, VARSIZE(DatumGetPointer(d)), TRUE);
|
entry->offset, VARSIZE(DatumGetPointer(d)), TRUE);
|
||||||
retval = gbt_var_compress( trim , &tinfo ) ;
|
retval = gbt_var_compress(trim, &tinfo);
|
||||||
|
|
||||||
pfree ( trim );
|
pfree(trim);
|
||||||
pfree ( DatumGetPointer(d) );
|
pfree(DatumGetPointer(d));
|
||||||
} else
|
}
|
||||||
retval = entry;
|
else
|
||||||
|
retval = entry;
|
||||||
|
|
||||||
PG_RETURN_POINTER ( retval );
|
PG_RETURN_POINTER(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,68 +178,66 @@ gbt_bpchar_compress (PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_text_consistent(PG_FUNCTION_ARGS)
|
gbt_text_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer ( entry->key ) ;
|
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer ( PG_DETOAST_DATUM( entry->key ) );
|
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
void *qtst = ( void * ) DatumGetPointer( PG_GETARG_DATUM(1) );
|
void *qtst = (void *) DatumGetPointer(PG_GETARG_DATUM(1));
|
||||||
void *query = ( void * ) DatumGetTextP ( PG_GETARG_DATUM(1) );
|
void *query = (void *) DatumGetTextP(PG_GETARG_DATUM(1));
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( key );
|
GBT_VARKEY_R r = gbt_var_key_readable(key);
|
||||||
|
|
||||||
if ( GIST_LEAF(entry) )
|
if (GIST_LEAF(entry))
|
||||||
{
|
retval = gbt_var_consistent(&r, query, &strategy, TRUE, &tinfo);
|
||||||
retval = gbt_var_consistent( &r, query, &strategy, TRUE, &tinfo );
|
else
|
||||||
} else {
|
{
|
||||||
bytea * q = gbt_text_xfrm ( ( bytea * ) query );
|
bytea *q = gbt_text_xfrm((bytea *) query);
|
||||||
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo );
|
|
||||||
if ( q != query )
|
|
||||||
pfree(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ktst != key ){
|
retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
|
||||||
pfree ( key );
|
if (q != query)
|
||||||
}
|
pfree(q);
|
||||||
if ( qtst != query ){
|
}
|
||||||
pfree ( query );
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(retval);
|
if (ktst != key)
|
||||||
|
pfree(key);
|
||||||
|
if (qtst != query)
|
||||||
|
pfree(query);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_bpchar_consistent(PG_FUNCTION_ARGS)
|
gbt_bpchar_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer ( entry->key ) ;
|
GBT_VARKEY *ktst = (GBT_VARKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer ( PG_DETOAST_DATUM( entry->key ) );
|
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
void *qtst = ( void * ) DatumGetPointer ( PG_GETARG_DATUM(1) );
|
void *qtst = (void *) DatumGetPointer(PG_GETARG_DATUM(1));
|
||||||
void *query = ( void * ) DatumGetPointer (PG_DETOAST_DATUM( PG_GETARG_DATUM(1) ) );
|
void *query = (void *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
|
||||||
void *trim = ( void * ) DatumGetPointer ( DirectFunctionCall1 ( rtrim1, PointerGetDatum ( query ) ) ) ;
|
void *trim = (void *) DatumGetPointer(DirectFunctionCall1(rtrim1, PointerGetDatum(query)));
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
GBT_VARKEY_R r = gbt_var_key_readable ( key );
|
GBT_VARKEY_R r = gbt_var_key_readable(key);
|
||||||
|
|
||||||
if ( GIST_LEAF(entry) )
|
if (GIST_LEAF(entry))
|
||||||
{
|
retval = gbt_var_consistent(&r, trim, &strategy, TRUE, &tinfo);
|
||||||
retval = gbt_var_consistent( &r, trim , &strategy, TRUE, &tinfo );
|
else
|
||||||
} else {
|
{
|
||||||
bytea * q = gbt_text_xfrm ( ( bytea * ) trim );
|
bytea *q = gbt_text_xfrm((bytea *) trim);
|
||||||
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo );
|
|
||||||
if ( q != trim )
|
|
||||||
pfree(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
pfree(trim);
|
retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
|
||||||
|
if (q != trim)
|
||||||
|
pfree(q);
|
||||||
|
}
|
||||||
|
|
||||||
if ( ktst != key ){
|
pfree(trim);
|
||||||
pfree ( key );
|
|
||||||
}
|
if (ktst != key)
|
||||||
if ( qtst != query ){
|
pfree(key);
|
||||||
pfree ( query );
|
if (qtst != query)
|
||||||
}
|
pfree(query);
|
||||||
PG_RETURN_BOOL(retval);
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,37 +246,40 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_text_union(PG_FUNCTION_ARGS)
|
gbt_text_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int32 *size = (int *) PG_GETARG_POINTER(1);
|
int32 *size = (int *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_union ( entryvec , size , &tinfo ) );
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_text_picksplit(PG_FUNCTION_ARGS)
|
gbt_text_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
gbt_var_picksplit ( entryvec, v, &tinfo );
|
|
||||||
PG_RETURN_POINTER(v);
|
gbt_var_picksplit(entryvec, v, &tinfo);
|
||||||
|
PG_RETURN_POINTER(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_text_same(PG_FUNCTION_ARGS)
|
gbt_text_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum d1 = PG_GETARG_DATUM(0);
|
Datum d1 = PG_GETARG_DATUM(0);
|
||||||
Datum d2 = PG_GETARG_DATUM(1);
|
Datum d2 = PG_GETARG_DATUM(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
PG_RETURN_POINTER( gbt_var_same ( result, d1 , d2 , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_text_penalty(PG_FUNCTION_ARGS)
|
gbt_text_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
GISTENTRY * o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY * n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
PG_RETURN_POINTER( gbt_var_penalty ( result ,o , n, &tinfo ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
|
||||||
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
TimeADT lower;
|
TimeADT lower;
|
||||||
TimeADT upper;
|
TimeADT upper;
|
||||||
} timeKEY;
|
} timeKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** time ops
|
** time ops
|
||||||
@ -20,49 +20,54 @@ PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_time_penalty);
|
PG_FUNCTION_INFO_V1(gbt_time_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_time_same);
|
PG_FUNCTION_INFO_V1(gbt_time_same);
|
||||||
|
|
||||||
Datum gbt_time_compress(PG_FUNCTION_ARGS);
|
Datum gbt_time_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_timetz_compress(PG_FUNCTION_ARGS);
|
Datum gbt_timetz_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_time_union(PG_FUNCTION_ARGS);
|
Datum gbt_time_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_time_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_time_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_time_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_time_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_time_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_time_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_time_same(PG_FUNCTION_ARGS);
|
Datum gbt_time_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_timegt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_timegt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(time_gt,TimeADTGetDatum( *((TimeADT*)a) ), TimeADTGetDatum( *((TimeADT*)b) ) )
|
DirectFunctionCall2(time_gt, TimeADTGetDatum(*((TimeADT *) a)), TimeADTGetDatum(*((TimeADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_timege (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_timege(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(time_ge,TimeADTGetDatum( *((TimeADT*)a) ), TimeADTGetDatum( *((TimeADT*)b) ) )
|
DirectFunctionCall2(time_ge, TimeADTGetDatum(*((TimeADT *) a)), TimeADTGetDatum(*((TimeADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_timeeq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_timeeq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(time_eq,TimeADTGetDatum( *((TimeADT*)a) ), TimeADTGetDatum( *((TimeADT*)b) ) )
|
DirectFunctionCall2(time_eq, TimeADTGetDatum(*((TimeADT *) a)), TimeADTGetDatum(*((TimeADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_timele (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_timele(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(time_le,TimeADTGetDatum( *((TimeADT*)a) ), TimeADTGetDatum( *((TimeADT*)b) ) )
|
DirectFunctionCall2(time_le, TimeADTGetDatum(*((TimeADT *) a)), TimeADTGetDatum(*((TimeADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_timelt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_timelt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(time_lt,TimeADTGetDatum( *((TimeADT*)a) ), TimeADTGetDatum( *((TimeADT*)b) ) )
|
DirectFunctionCall2(time_lt, TimeADTGetDatum(*((TimeADT *) a)), TimeADTGetDatum(*((TimeADT *) b)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,26 +75,24 @@ static bool gbt_timelt (const void *a, const void *b)
|
|||||||
static int
|
static int
|
||||||
gbt_timekey_cmp(const void *a, const void *b)
|
gbt_timekey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
if ( gbt_timegt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
if (gbt_timegt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (gbt_timelt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
if ( gbt_timelt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_time,
|
gbt_t_time,
|
||||||
sizeof(TimeADT),
|
sizeof(TimeADT),
|
||||||
gbt_timegt,
|
gbt_timegt,
|
||||||
gbt_timege,
|
gbt_timege,
|
||||||
gbt_timeeq,
|
gbt_timeeq,
|
||||||
gbt_timele,
|
gbt_timele,
|
||||||
gbt_timelt,
|
gbt_timelt,
|
||||||
gbt_timekey_cmp
|
gbt_timekey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -102,150 +105,154 @@ static const gbtree_ninfo tinfo =
|
|||||||
Datum
|
Datum
|
||||||
gbt_time_compress(PG_FUNCTION_ARGS)
|
gbt_time_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_timetz_compress(PG_FUNCTION_ARGS)
|
gbt_timetz_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval;
|
GISTENTRY *retval;
|
||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{
|
{
|
||||||
timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY));
|
timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY));
|
||||||
TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
|
TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
|
||||||
|
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
|
|
||||||
/* We are using the time + zone only to compress */
|
/* We are using the time + zone only to compress */
|
||||||
r->lower = r->upper = ( tz->time + tz->zone ) ;
|
r->lower = r->upper = (tz->time + tz->zone);
|
||||||
gistentryinit(*retval, PointerGetDatum(r),
|
gistentryinit(*retval, PointerGetDatum(r),
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, sizeof(timeKEY), FALSE);
|
entry->offset, sizeof(timeKEY), FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
retval = entry;
|
retval = entry;
|
||||||
PG_RETURN_POINTER(retval);
|
PG_RETURN_POINTER(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_time_consistent(PG_FUNCTION_ARGS)
|
gbt_time_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
TimeADT query = PG_GETARG_TIMEADT( 1 );
|
TimeADT query = PG_GETARG_TIMEADT(1);
|
||||||
timeKEY *kkk = (timeKEY*) DatumGetPointer(entry->key);
|
timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)&query,&strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_timetz_consistent(PG_FUNCTION_ARGS)
|
gbt_timetz_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
TimeTzADT *query = PG_GETARG_TIMETZADT_P( 1 );
|
TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
|
||||||
TimeADT qqq = query->time + query->zone ;
|
TimeADT qqq = query->time + query->zone;
|
||||||
timeKEY *kkk = (timeKEY*) DatumGetPointer(entry->key);
|
timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)&qqq, &strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_time_union(PG_FUNCTION_ARGS)
|
gbt_time_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(timeKEY));
|
void *out = palloc(sizeof(timeKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_time_penalty(PG_FUNCTION_ARGS)
|
gbt_time_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
Interval *intr;
|
Interval *intr;
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
int64 res;
|
int64 res;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
double res;
|
double res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
time_mi_time,
|
time_mi_time,
|
||||||
TimeADTGetDatum(newentry->upper),
|
TimeADTGetDatum(newentry->upper),
|
||||||
TimeADTGetDatum(origentry->upper)));
|
TimeADTGetDatum(origentry->upper)));
|
||||||
|
|
||||||
/* see interval_larger */
|
/* see interval_larger */
|
||||||
res = Max(intr->time + intr->month * (30 * 86400), 0);
|
res = Max(intr->time + intr->month * (30 * 86400), 0);
|
||||||
pfree(intr);
|
pfree(intr);
|
||||||
|
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
time_mi_time,
|
time_mi_time,
|
||||||
TimeADTGetDatum(origentry->lower),
|
TimeADTGetDatum(origentry->lower),
|
||||||
TimeADTGetDatum(newentry->lower)));
|
TimeADTGetDatum(newentry->lower)));
|
||||||
|
|
||||||
/* see interval_larger */
|
/* see interval_larger */
|
||||||
res += Max(intr->time + intr->month * (30 * 86400), 0);
|
res += Max(intr->time + intr->month * (30 * 86400), 0);
|
||||||
pfree(intr);
|
pfree(intr);
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
{
|
||||||
time_mi_time,
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
TimeADTGetDatum(origentry->upper),
|
time_mi_time,
|
||||||
TimeADTGetDatum(origentry->lower)));
|
TimeADTGetDatum(origentry->upper),
|
||||||
*result += FLT_MIN ;
|
TimeADTGetDatum(origentry->lower)));
|
||||||
*result += (float) ( res / ( (double) ( res + intr->time + intr->month * (30 * 86400) ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + intr->time + intr->month * (30 * 86400))));
|
||||||
pfree ( intr );
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
}
|
pfree(intr);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_time_picksplit(PG_FUNCTION_ARGS)
|
gbt_time_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_time_same(PG_FUNCTION_ARGS)
|
gbt_time_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
|
timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
|
||||||
timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
|
timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Timestamp lower;
|
Timestamp lower;
|
||||||
Timestamp upper;
|
Timestamp upper;
|
||||||
} tsKEY;
|
} tsKEY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** timestamp ops
|
** timestamp ops
|
||||||
@ -19,75 +19,78 @@ PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
|
|||||||
PG_FUNCTION_INFO_V1(gbt_ts_penalty);
|
PG_FUNCTION_INFO_V1(gbt_ts_penalty);
|
||||||
PG_FUNCTION_INFO_V1(gbt_ts_same);
|
PG_FUNCTION_INFO_V1(gbt_ts_same);
|
||||||
|
|
||||||
Datum gbt_ts_compress(PG_FUNCTION_ARGS);
|
Datum gbt_ts_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_tstz_compress(PG_FUNCTION_ARGS);
|
Datum gbt_tstz_compress(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_ts_union(PG_FUNCTION_ARGS);
|
Datum gbt_ts_union(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_ts_picksplit(PG_FUNCTION_ARGS);
|
Datum gbt_ts_picksplit(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_ts_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_ts_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_tstz_consistent(PG_FUNCTION_ARGS);
|
Datum gbt_tstz_consistent(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_ts_penalty(PG_FUNCTION_ARGS);
|
Datum gbt_ts_penalty(PG_FUNCTION_ARGS);
|
||||||
Datum gbt_ts_same(PG_FUNCTION_ARGS);
|
Datum gbt_ts_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
static bool gbt_tsgt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_tsgt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(timestamp_gt,PointerGetDatum( a ), PointerGetDatum( b ) )
|
DirectFunctionCall2(timestamp_gt, PointerGetDatum(a), PointerGetDatum(b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_tsge (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_tsge(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(timestamp_ge,PointerGetDatum( a ), PointerGetDatum( b ) )
|
DirectFunctionCall2(timestamp_ge, PointerGetDatum(a), PointerGetDatum(b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_tseq (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_tseq(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(timestamp_eq,PointerGetDatum( a ), PointerGetDatum( b ) )
|
DirectFunctionCall2(timestamp_eq, PointerGetDatum(a), PointerGetDatum(b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_tsle (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_tsle(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(timestamp_le,PointerGetDatum( a ), PointerGetDatum( b ) )
|
DirectFunctionCall2(timestamp_le, PointerGetDatum(a), PointerGetDatum(b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gbt_tslt (const void *a, const void *b)
|
static bool
|
||||||
|
gbt_tslt(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return DatumGetBool(
|
return DatumGetBool(
|
||||||
DirectFunctionCall2(timestamp_lt,PointerGetDatum( a ), PointerGetDatum( b ) )
|
DirectFunctionCall2(timestamp_lt, PointerGetDatum(a), PointerGetDatum(b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gbt_tskey_cmp(const void *a, const void *b)
|
gbt_tskey_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
if ( gbt_tsgt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
if (gbt_tsgt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
else if (gbt_tslt((void *) &(((Nsrt *) a)->t[0]), (void *) &(((Nsrt *) b)->t[0])))
|
||||||
if ( gbt_tslt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){
|
return -1;
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const gbtree_ninfo tinfo =
|
static const gbtree_ninfo tinfo =
|
||||||
{
|
{
|
||||||
gbt_t_ts,
|
gbt_t_ts,
|
||||||
sizeof(Timestamp),
|
sizeof(Timestamp),
|
||||||
gbt_tsgt,
|
gbt_tsgt,
|
||||||
gbt_tsge,
|
gbt_tsge,
|
||||||
gbt_tseq,
|
gbt_tseq,
|
||||||
gbt_tsle,
|
gbt_tsle,
|
||||||
gbt_tslt,
|
gbt_tslt,
|
||||||
gbt_tskey_cmp
|
gbt_tskey_cmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -97,26 +100,28 @@ static const gbtree_ninfo tinfo =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Timestamp * tstz_to_ts_gmt ( Timestamp * gmt, TimestampTz * ts )
|
static Timestamp *
|
||||||
|
tstz_to_ts_gmt(Timestamp *gmt, TimestampTz *ts)
|
||||||
{
|
{
|
||||||
int val, tz ;
|
int val,
|
||||||
|
tz;
|
||||||
|
|
||||||
*gmt = *ts;
|
*gmt = *ts;
|
||||||
DecodeSpecial(0, "gmt", &val);
|
DecodeSpecial(0, "gmt", &val);
|
||||||
|
|
||||||
if ( ! TIMESTAMP_NOT_FINITE(*ts))
|
if (!TIMESTAMP_NOT_FINITE(*ts))
|
||||||
{
|
{
|
||||||
tz = val * 60;
|
tz = val * 60;
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
*gmt -= (tz * INT64CONST(1000000));
|
*gmt -= (tz * INT64CONST(1000000));
|
||||||
#else
|
#else
|
||||||
*gmt -= tz;
|
*gmt -= tz;
|
||||||
*gmt = JROUND(*gmt);
|
*gmt = JROUND(*gmt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
return gmt;
|
return gmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,84 +130,86 @@ static Timestamp * tstz_to_ts_gmt ( Timestamp * gmt, TimestampTz * ts )
|
|||||||
Datum
|
Datum
|
||||||
gbt_ts_compress(PG_FUNCTION_ARGS)
|
gbt_ts_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval = NULL;
|
GISTENTRY *retval = NULL;
|
||||||
PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo ));
|
|
||||||
|
PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_tstz_compress(PG_FUNCTION_ARGS)
|
gbt_tstz_compress(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
GISTENTRY *retval ;
|
GISTENTRY *retval;
|
||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{
|
{
|
||||||
tsKEY *r = (tsKEY *) palloc(sizeof(tsKEY));
|
tsKEY *r = (tsKEY *) palloc(sizeof(tsKEY));
|
||||||
|
|
||||||
TimestampTz ts = *(TimestampTz *) DatumGetPointer(entry->key);
|
TimestampTz ts = *(TimestampTz *) DatumGetPointer(entry->key);
|
||||||
Timestamp gmt ;
|
Timestamp gmt;
|
||||||
|
|
||||||
tstz_to_ts_gmt ( &gmt, &ts );
|
tstz_to_ts_gmt(&gmt, &ts);
|
||||||
|
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
r->lower = r->upper = gmt ;
|
r->lower = r->upper = gmt;
|
||||||
gistentryinit(*retval, PointerGetDatum(r),
|
gistentryinit(*retval, PointerGetDatum(r),
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, sizeof(tsKEY), FALSE);
|
entry->offset, sizeof(tsKEY), FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
retval = entry;
|
retval = entry;
|
||||||
|
|
||||||
PG_RETURN_POINTER( retval );
|
PG_RETURN_POINTER(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_ts_consistent(PG_FUNCTION_ARGS)
|
gbt_ts_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1);
|
Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1);
|
||||||
tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
|
tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk->lower ;
|
key.lower = (GBT_NUMKEY *) & kkk->lower;
|
||||||
key.upper = (GBT_NUMKEY*) &kkk->upper ;
|
key.upper = (GBT_NUMKEY *) & kkk->upper;
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)query,&strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_tstz_consistent(PG_FUNCTION_ARGS)
|
gbt_tstz_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
TimestampTz *query = (Timestamp *) PG_GETARG_POINTER(1);
|
TimestampTz *query = (Timestamp *) PG_GETARG_POINTER(1);
|
||||||
char *kkk = (char *) DatumGetPointer(entry->key);
|
char *kkk = (char *) DatumGetPointer(entry->key);
|
||||||
GBT_NUMKEY_R key ;
|
GBT_NUMKEY_R key;
|
||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
Timestamp qqq ;
|
Timestamp qqq;
|
||||||
|
|
||||||
key.lower = (GBT_NUMKEY*) &kkk[0];
|
key.lower = (GBT_NUMKEY *) & kkk[0];
|
||||||
key.upper = (GBT_NUMKEY*) &kkk[MAXALIGN(tinfo.size)];
|
key.upper = (GBT_NUMKEY *) & kkk[MAXALIGN(tinfo.size)];
|
||||||
tstz_to_ts_gmt ( &qqq, query );
|
tstz_to_ts_gmt(&qqq, query);
|
||||||
|
|
||||||
PG_RETURN_BOOL(
|
PG_RETURN_BOOL(
|
||||||
gbt_num_consistent( &key, (void*)&qqq,&strategy,GIST_LEAF(entry),&tinfo)
|
gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_ts_union(PG_FUNCTION_ARGS)
|
gbt_ts_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
void *out = palloc(sizeof(tsKEY));
|
void *out = palloc(sizeof(tsKEY));
|
||||||
*(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
|
|
||||||
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) );
|
*(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
|
||||||
|
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -210,52 +217,55 @@ Datum
|
|||||||
gbt_ts_penalty(PG_FUNCTION_ARGS)
|
gbt_ts_penalty(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *result = (float *) PG_GETARG_POINTER(2);
|
float *result = (float *) PG_GETARG_POINTER(2);
|
||||||
Interval *intr;
|
Interval *intr;
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
int64 res;
|
int64 res;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
double res;
|
double res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
timestamp_mi,
|
timestamp_mi,
|
||||||
TimestampGetDatum(newentry->upper),
|
TimestampGetDatum(newentry->upper),
|
||||||
TimestampGetDatum(origentry->upper)
|
TimestampGetDatum(origentry->upper)
|
||||||
));
|
));
|
||||||
|
|
||||||
/* see interval_larger */
|
/* see interval_larger */
|
||||||
|
|
||||||
res = Max(intr->time + intr->month * (30 * 86400), 0);
|
res = Max(intr->time + intr->month * (30 * 86400), 0);
|
||||||
pfree(intr);
|
pfree(intr);
|
||||||
|
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
timestamp_mi,
|
timestamp_mi,
|
||||||
TimestampGetDatum(origentry->lower),
|
TimestampGetDatum(origentry->lower),
|
||||||
TimestampGetDatum(newentry->lower)
|
TimestampGetDatum(newentry->lower)
|
||||||
));
|
));
|
||||||
|
|
||||||
/* see interval_larger */
|
/* see interval_larger */
|
||||||
res += Max(intr->time + intr->month * (30 * 86400), 0);
|
res += Max(intr->time + intr->month * (30 * 86400), 0);
|
||||||
pfree(intr);
|
pfree(intr);
|
||||||
|
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
|
|
||||||
if ( res > 0 ){
|
if (res > 0)
|
||||||
intr = DatumGetIntervalP(DirectFunctionCall2(
|
{
|
||||||
timestamp_mi,
|
intr = DatumGetIntervalP(DirectFunctionCall2(
|
||||||
TimestampGetDatum(origentry->upper),
|
timestamp_mi,
|
||||||
TimestampGetDatum(origentry->lower)
|
TimestampGetDatum(origentry->upper),
|
||||||
));
|
TimestampGetDatum(origentry->lower)
|
||||||
*result += FLT_MIN ;
|
));
|
||||||
*result += (float) ( res / ( (double) ( res + intr->time + intr->month * (30 * 86400) ) ) );
|
*result += FLT_MIN;
|
||||||
*result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) );
|
*result += (float) (res / ((double) (res + intr->time + intr->month * (30 * 86400))));
|
||||||
pfree(intr);
|
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
|
||||||
}
|
pfree(intr);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,21 +273,20 @@ gbt_ts_penalty(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbt_ts_picksplit(PG_FUNCTION_ARGS)
|
gbt_ts_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PG_RETURN_POINTER(gbt_num_picksplit(
|
PG_RETURN_POINTER(gbt_num_picksplit(
|
||||||
(GistEntryVector *) PG_GETARG_POINTER(0),
|
(GistEntryVector *) PG_GETARG_POINTER(0),
|
||||||
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
|
||||||
&tinfo
|
&tinfo
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gbt_ts_same(PG_FUNCTION_ARGS)
|
gbt_ts_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0);
|
tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0);
|
||||||
tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1);
|
tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo );
|
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,58 +3,60 @@
|
|||||||
#include "utils/date.h"
|
#include "utils/date.h"
|
||||||
|
|
||||||
extern GISTENTRY *
|
extern GISTENTRY *
|
||||||
gbt_num_compress( GISTENTRY *retval , GISTENTRY *entry , const gbtree_ninfo * tinfo )
|
gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo * tinfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{
|
{
|
||||||
|
|
||||||
union {
|
union
|
||||||
int16 i2;
|
{
|
||||||
int32 i4;
|
int16 i2;
|
||||||
TimeADT ts;
|
int32 i4;
|
||||||
DateADT dt;
|
TimeADT ts;
|
||||||
} v ;
|
DateADT dt;
|
||||||
|
} v;
|
||||||
|
|
||||||
GBT_NUMKEY *r = ( GBT_NUMKEY * ) palloc(2 * tinfo->size );
|
GBT_NUMKEY *r = (GBT_NUMKEY *) palloc(2 * tinfo->size);
|
||||||
void *leaf = NULL;
|
void *leaf = NULL;
|
||||||
|
|
||||||
switch ( tinfo->t )
|
switch (tinfo->t)
|
||||||
{
|
{
|
||||||
case gbt_t_int2 :
|
case gbt_t_int2:
|
||||||
v.i2 = DatumGetInt16(entry->key);
|
v.i2 = DatumGetInt16(entry->key);
|
||||||
leaf = &v.i2;
|
leaf = &v.i2;
|
||||||
break;
|
break;
|
||||||
case gbt_t_int4 :
|
case gbt_t_int4:
|
||||||
v.i4 = DatumGetInt32(entry->key);
|
v.i4 = DatumGetInt32(entry->key);
|
||||||
leaf = &v.i4;
|
leaf = &v.i4;
|
||||||
break;
|
break;
|
||||||
case gbt_t_oid :
|
case gbt_t_oid:
|
||||||
v.i4 = DatumGetObjectId(entry->key);
|
v.i4 = DatumGetObjectId(entry->key);
|
||||||
leaf = &v.i4;
|
leaf = &v.i4;
|
||||||
break;
|
break;
|
||||||
case gbt_t_time :
|
case gbt_t_time:
|
||||||
v.ts = DatumGetTimeADT(entry->key);
|
v.ts = DatumGetTimeADT(entry->key);
|
||||||
leaf = &v.ts;
|
leaf = &v.ts;
|
||||||
break;
|
break;
|
||||||
case gbt_t_date :
|
case gbt_t_date:
|
||||||
v.dt = DatumGetDateADT(entry->key);
|
v.dt = DatumGetDateADT(entry->key);
|
||||||
leaf = &v.dt;
|
leaf = &v.dt;
|
||||||
break;
|
break;
|
||||||
default :
|
default:
|
||||||
leaf = DatumGetPointer(entry->key);
|
leaf = DatumGetPointer(entry->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset ( (void*) &r[0] , 0 , 2*tinfo->size );
|
memset((void *) &r[0], 0, 2 * tinfo->size);
|
||||||
memcpy ( (void*) &r[0] , leaf, tinfo->size );
|
memcpy((void *) &r[0], leaf, tinfo->size);
|
||||||
memcpy ( (void*) &r[tinfo->size] , leaf, tinfo->size );
|
memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
|
||||||
retval = palloc(sizeof(GISTENTRY));
|
retval = palloc(sizeof(GISTENTRY));
|
||||||
gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
|
gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
|
||||||
entry->offset,( 2 * tinfo->size ), FALSE);
|
entry->offset, (2 * tinfo->size), FALSE);
|
||||||
} else
|
}
|
||||||
retval = entry;
|
else
|
||||||
|
retval = entry;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -65,34 +67,35 @@ gbt_num_compress( GISTENTRY *retval , GISTENTRY *entry , const gbtree_ninfo *
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern void *
|
extern void *
|
||||||
gbt_num_union( GBT_NUMKEY * out, const GistEntryVector * entryvec, const gbtree_ninfo * tinfo )
|
gbt_num_union(GBT_NUMKEY * out, const GistEntryVector *entryvec, const gbtree_ninfo * tinfo)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
numranges;
|
numranges;
|
||||||
GBT_NUMKEY * cur ;
|
GBT_NUMKEY *cur;
|
||||||
GBT_NUMKEY_R o, c;
|
GBT_NUMKEY_R o,
|
||||||
|
c;
|
||||||
|
|
||||||
numranges = entryvec->n;
|
numranges = entryvec->n;
|
||||||
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
|
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
|
||||||
|
|
||||||
|
|
||||||
o.lower = &((GBT_NUMKEY *)out)[0];
|
o.lower = &((GBT_NUMKEY *) out)[0];
|
||||||
o.upper = &((GBT_NUMKEY *)out)[tinfo->size];
|
o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
|
||||||
|
|
||||||
memcpy( (void*)out, (void*) cur, 2*tinfo->size );
|
memcpy((void *) out, (void *) cur, 2 * tinfo->size);
|
||||||
|
|
||||||
for (i = 1; i < numranges; i++)
|
for (i = 1; i < numranges; i++)
|
||||||
{
|
{
|
||||||
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
||||||
c.lower = &cur[0];
|
c.lower = &cur[0];
|
||||||
c.upper = &cur[tinfo->size];
|
c.upper = &cur[tinfo->size];
|
||||||
if ( (*tinfo->f_gt)(o.lower, c.lower) ) /* out->lower > cur->lower */
|
if ((*tinfo->f_gt) (o.lower, c.lower)) /* out->lower > cur->lower */
|
||||||
memcpy( (void* ) o.lower, (void*) c.lower, tinfo->size );
|
memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
|
||||||
if ( (*tinfo->f_lt)(o.upper, c.upper) ) /* out->upper < cur->upper */
|
if ((*tinfo->f_lt) (o.upper, c.upper)) /* out->upper < cur->upper */
|
||||||
memcpy( (void*) o.upper, (void*) c.upper, tinfo->size );
|
memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -101,51 +104,54 @@ gbt_num_union( GBT_NUMKEY * out, const GistEntryVector * entryvec, const gbtree_
|
|||||||
** The GiST same method for numerical values
|
** The GiST same method for numerical values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern bool gbt_num_same ( const GBT_NUMKEY * a, const GBT_NUMKEY * b, const gbtree_ninfo * tinfo )
|
extern bool
|
||||||
|
gbt_num_same(const GBT_NUMKEY * a, const GBT_NUMKEY * b, const gbtree_ninfo * tinfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
GBT_NUMKEY_R b1, b2 ;
|
GBT_NUMKEY_R b1,
|
||||||
|
b2;
|
||||||
|
|
||||||
b1.lower = &(((GBT_NUMKEY *)a)[0]);
|
b1.lower = &(((GBT_NUMKEY *) a)[0]);
|
||||||
b1.upper = &(((GBT_NUMKEY *)a)[tinfo->size]);
|
b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
|
||||||
b2.lower = &(((GBT_NUMKEY *)b)[0]);
|
b2.lower = &(((GBT_NUMKEY *) b)[0]);
|
||||||
b2.upper = &(((GBT_NUMKEY *)b)[tinfo->size]);
|
b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(*tinfo->f_eq)( b1.lower, b2.lower) &&
|
(*tinfo->f_eq) (b1.lower, b2.lower) &&
|
||||||
(*tinfo->f_eq)( b1.upper, b2.upper)
|
(*tinfo->f_eq) (b1.upper, b2.upper)
|
||||||
)
|
)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
gbt_num_bin_union(Datum * u , GBT_NUMKEY * e , const gbtree_ninfo * tinfo )
|
gbt_num_bin_union(Datum *u, GBT_NUMKEY * e, const gbtree_ninfo * tinfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
GBT_NUMKEY_R rd;
|
GBT_NUMKEY_R rd;
|
||||||
|
|
||||||
rd.lower = &e[0];
|
rd.lower = &e[0];
|
||||||
rd.upper = &e[tinfo->size];
|
rd.upper = &e[tinfo->size];
|
||||||
|
|
||||||
if (!DatumGetPointer(*u))
|
if (!DatumGetPointer(*u))
|
||||||
{
|
{
|
||||||
*u = PointerGetDatum(palloc(2 * tinfo->size));
|
*u = PointerGetDatum(palloc(2 * tinfo->size));
|
||||||
memcpy( (void* ) &( ( (GBT_NUMKEY *) DatumGetPointer(*u) )[0] ) , (void*)rd.lower , tinfo->size );
|
memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
|
||||||
memcpy( (void* ) &( ( (GBT_NUMKEY *) DatumGetPointer(*u) )[tinfo->size]) , (void*)rd.upper , tinfo->size );
|
memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GBT_NUMKEY_R ur ;
|
GBT_NUMKEY_R ur;
|
||||||
ur.lower = &( ( (GBT_NUMKEY *) DatumGetPointer(*u) )[0] ) ;
|
|
||||||
ur.upper = &( ( (GBT_NUMKEY *) DatumGetPointer(*u) )[tinfo->size]) ;
|
ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
|
||||||
if ( (*tinfo->f_gt)((void*)ur.lower, (void*)rd.lower) )
|
ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
|
||||||
memcpy( (void*) ur.lower, (void*) rd.lower, tinfo->size );
|
if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower))
|
||||||
if ( (*tinfo->f_lt)((void*)ur.upper, (void*)rd.upper) )
|
memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
|
||||||
memcpy( (void*) ur.upper, (void*) rd.upper, tinfo->size );
|
if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper))
|
||||||
}
|
memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -156,96 +162,96 @@ gbt_num_bin_union(Datum * u , GBT_NUMKEY * e , const gbtree_ninfo * tinfo )
|
|||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
gbt_num_consistent(
|
gbt_num_consistent(
|
||||||
const GBT_NUMKEY_R * key,
|
const GBT_NUMKEY_R * key,
|
||||||
const void * query,
|
const void *query,
|
||||||
const StrategyNumber * strategy,
|
const StrategyNumber *strategy,
|
||||||
bool is_leaf,
|
bool is_leaf,
|
||||||
const gbtree_ninfo * tinfo
|
const gbtree_ninfo * tinfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool retval = FALSE;
|
bool retval = FALSE;
|
||||||
|
|
||||||
switch (*strategy)
|
switch (*strategy)
|
||||||
{
|
{
|
||||||
case BTLessEqualStrategyNumber:
|
case BTLessEqualStrategyNumber:
|
||||||
retval = (*tinfo->f_ge)(query, key->lower);
|
retval = (*tinfo->f_ge) (query, key->lower);
|
||||||
break;
|
break;
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
if ( is_leaf )
|
if (is_leaf)
|
||||||
retval = (*tinfo->f_gt)(query, key->lower);
|
retval = (*tinfo->f_gt) (query, key->lower);
|
||||||
else
|
else
|
||||||
retval = (*tinfo->f_ge)(query, key->lower);
|
retval = (*tinfo->f_ge) (query, key->lower);
|
||||||
break;
|
break;
|
||||||
case BTEqualStrategyNumber:
|
case BTEqualStrategyNumber:
|
||||||
if ( is_leaf )
|
if (is_leaf)
|
||||||
retval = (*tinfo->f_eq)(query, key->lower);
|
retval = (*tinfo->f_eq) (query, key->lower);
|
||||||
else
|
else
|
||||||
retval = (*tinfo->f_le)(key->lower, query) && (*tinfo->f_le)(query, key->upper );
|
retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
|
||||||
break;
|
break;
|
||||||
case BTGreaterStrategyNumber:
|
case BTGreaterStrategyNumber:
|
||||||
if ( is_leaf )
|
if (is_leaf)
|
||||||
retval = (*tinfo->f_lt)(query, key->upper);
|
retval = (*tinfo->f_lt) (query, key->upper);
|
||||||
else
|
else
|
||||||
retval = (*tinfo->f_le)(query, key->upper);
|
retval = (*tinfo->f_le) (query, key->upper);
|
||||||
break;
|
break;
|
||||||
case BTGreaterEqualStrategyNumber:
|
case BTGreaterEqualStrategyNumber:
|
||||||
retval = (*tinfo->f_le)(query, key->upper);
|
retval = (*tinfo->f_le) (query, key->upper);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
retval = FALSE;
|
retval = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GIST_SPLITVEC *
|
GIST_SPLITVEC *
|
||||||
gbt_num_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
||||||
const gbtree_ninfo * tinfo )
|
const gbtree_ninfo * tinfo)
|
||||||
{
|
{
|
||||||
OffsetNumber i,
|
OffsetNumber i,
|
||||||
maxoff = entryvec->n - 1;
|
maxoff = entryvec->n - 1;
|
||||||
Nsrt *arr;
|
Nsrt *arr;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
arr = (Nsrt *) palloc((maxoff+1) * sizeof(Nsrt));
|
arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
|
||||||
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
|
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
|
||||||
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
||||||
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
||||||
v->spl_ldatum = PointerGetDatum(0);
|
v->spl_ldatum = PointerGetDatum(0);
|
||||||
v->spl_rdatum = PointerGetDatum(0);
|
v->spl_rdatum = PointerGetDatum(0);
|
||||||
v->spl_nleft = 0;
|
v->spl_nleft = 0;
|
||||||
v->spl_nright = 0;
|
v->spl_nright = 0;
|
||||||
|
|
||||||
/* Sort entries */
|
/* Sort entries */
|
||||||
|
|
||||||
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
||||||
{
|
{
|
||||||
arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
||||||
arr[i].i = i;
|
arr[i].i = i;
|
||||||
}
|
}
|
||||||
qsort ( (void*) &arr[FirstOffsetNumber], maxoff-FirstOffsetNumber+1,sizeof(Nsrt), tinfo->f_cmp );
|
qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), tinfo->f_cmp);
|
||||||
|
|
||||||
/* We do simply create two parts */
|
/* We do simply create two parts */
|
||||||
|
|
||||||
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
||||||
{
|
{
|
||||||
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
|
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
|
||||||
{
|
{
|
||||||
gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
|
gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
|
||||||
v->spl_left[v->spl_nleft] = arr[i].i;
|
v->spl_left[v->spl_nleft] = arr[i].i;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
|
gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
|
||||||
v->spl_right[v->spl_nright] = arr[i].i;
|
v->spl_right[v->spl_nright] = arr[i].i;
|
||||||
v->spl_nright++;
|
v->spl_nright++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(arr);
|
pfree(arr);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,17 @@ typedef char GBT_NUMKEY;
|
|||||||
/* Better readable key */
|
/* Better readable key */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const GBT_NUMKEY * lower, * upper;
|
const GBT_NUMKEY *lower,
|
||||||
} GBT_NUMKEY_R;
|
*upper;
|
||||||
|
} GBT_NUMKEY_R;
|
||||||
|
|
||||||
|
|
||||||
/* for sorting */
|
/* for sorting */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GBT_NUMKEY * t;
|
GBT_NUMKEY *t;
|
||||||
} Nsrt;
|
} Nsrt;
|
||||||
|
|
||||||
|
|
||||||
/* type description */
|
/* type description */
|
||||||
@ -21,53 +22,53 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Attribs */
|
/* Attribs */
|
||||||
|
|
||||||
enum gbtree_type t ; /* data type */
|
enum gbtree_type t; /* data type */
|
||||||
int32 size ; /* size of type , 0 means variable */
|
int32 size; /* size of type , 0 means variable */
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
bool (*f_gt) ( const void * , const void * ); /* greater then */
|
bool (*f_gt) (const void *, const void *); /* greater then */
|
||||||
bool (*f_ge) ( const void * , const void * ); /* greater equal */
|
bool (*f_ge) (const void *, const void *); /* greater equal */
|
||||||
bool (*f_eq) ( const void * , const void * ); /* equal */
|
bool (*f_eq) (const void *, const void *); /* equal */
|
||||||
bool (*f_le) ( const void * , const void * ); /* less equal */
|
bool (*f_le) (const void *, const void *); /* less equal */
|
||||||
bool (*f_lt) ( const void * , const void * ); /* less then */
|
bool (*f_lt) (const void *, const void *); /* less then */
|
||||||
int (*f_cmp) ( const void * , const void * ); /* key compare function */
|
int (*f_cmp) (const void *, const void *); /* key compare function */
|
||||||
} gbtree_ninfo;
|
} gbtree_ninfo;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Numeric btree functions
|
* Numeric btree functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define penalty_range_enlarge(olower,oupper,nlower,nupper) do { \
|
#define penalty_range_enlarge(olower,oupper,nlower,nupper) do { \
|
||||||
res = 0; \
|
res = 0; \
|
||||||
if ( (nupper) > (oupper) ) \
|
if ( (nupper) > (oupper) ) \
|
||||||
res += ( (nupper) - (oupper) ); \
|
res += ( (nupper) - (oupper) ); \
|
||||||
if ( (olower) > (nlower) ) \
|
if ( (olower) > (nlower) ) \
|
||||||
res += ( (olower) - (nlower) ); \
|
res += ( (olower) - (nlower) ); \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern bool gbt_num_consistent( const GBT_NUMKEY_R * key , const void * query,
|
extern bool gbt_num_consistent(const GBT_NUMKEY_R * key, const void *query,
|
||||||
const StrategyNumber * strategy , bool is_leaf,
|
const StrategyNumber *strategy, bool is_leaf,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
|
||||||
extern GIST_SPLITVEC *gbt_num_picksplit ( const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
|
||||||
extern GISTENTRY *gbt_num_compress( GISTENTRY *retval , GISTENTRY *entry ,
|
extern GISTENTRY *gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
|
||||||
|
|
||||||
extern void *gbt_num_union ( GBT_NUMKEY * out, const GistEntryVector * entryvec,
|
extern void *gbt_num_union(GBT_NUMKEY * out, const GistEntryVector *entryvec,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
|
||||||
extern bool gbt_num_same ( const GBT_NUMKEY * a, const GBT_NUMKEY * b,
|
extern bool gbt_num_same(const GBT_NUMKEY * a, const GBT_NUMKEY * b,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
|
||||||
extern void gbt_num_bin_union(Datum * u , GBT_NUMKEY * e ,
|
extern void gbt_num_bin_union(Datum *u, GBT_NUMKEY * e,
|
||||||
const gbtree_ninfo * tinfo );
|
const gbtree_ninfo * tinfo);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,15 +5,16 @@ typedef bytea GBT_VARKEY;
|
|||||||
/* Better readable key */
|
/* Better readable key */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bytea * lower, * upper;
|
bytea *lower,
|
||||||
} GBT_VARKEY_R;
|
*upper;
|
||||||
|
} GBT_VARKEY_R;
|
||||||
|
|
||||||
/* used for key sorting */
|
/* used for key sorting */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int i ;
|
int i;
|
||||||
GBT_VARKEY * t ;
|
GBT_VARKEY *t;
|
||||||
} Vsrt ;
|
} Vsrt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
type description
|
type description
|
||||||
@ -23,45 +24,45 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Attribs */
|
/* Attribs */
|
||||||
|
|
||||||
enum gbtree_type t ; /* data type */
|
enum gbtree_type t; /* data type */
|
||||||
bool str ; /* true, if string ( else binary ) */
|
bool str; /* true, if string ( else binary ) */
|
||||||
bool trnc ; /* truncate (=compress) key */
|
bool trnc; /* truncate (=compress) key */
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
bool (*f_gt) ( const void * , const void * ); /* greater then */
|
bool (*f_gt) (const void *, const void *); /* greater then */
|
||||||
bool (*f_ge) ( const void * , const void * ); /* greater equal */
|
bool (*f_ge) (const void *, const void *); /* greater equal */
|
||||||
bool (*f_eq) ( const void * , const void * ); /* equal */
|
bool (*f_eq) (const void *, const void *); /* equal */
|
||||||
bool (*f_le) ( const void * , const void * ); /* less equal */
|
bool (*f_le) (const void *, const void *); /* less equal */
|
||||||
bool (*f_lt) ( const void * , const void * ); /* less then */
|
bool (*f_lt) (const void *, const void *); /* less then */
|
||||||
int32 (*f_cmp) ( const bytea * , const bytea * ); /* node compare */
|
int32 (*f_cmp) (const bytea *, const bytea *); /* node compare */
|
||||||
GBT_VARKEY* (*f_l2n) ( GBT_VARKEY * ); /* convert leaf to node */
|
GBT_VARKEY *(*f_l2n) (GBT_VARKEY *); /* convert leaf to node */
|
||||||
} gbtree_vinfo;
|
} gbtree_vinfo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern GBT_VARKEY_R gbt_var_key_readable ( const GBT_VARKEY * k );
|
extern GBT_VARKEY_R gbt_var_key_readable(const GBT_VARKEY * k);
|
||||||
|
|
||||||
extern GBT_VARKEY *gbt_var_key_copy ( const GBT_VARKEY_R * u, bool force_node );
|
extern GBT_VARKEY *gbt_var_key_copy(const GBT_VARKEY_R * u, bool force_node);
|
||||||
|
|
||||||
extern GISTENTRY *gbt_var_compress ( GISTENTRY *entry , const gbtree_vinfo * tinfo );
|
extern GISTENTRY *gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo * tinfo);
|
||||||
|
|
||||||
extern GBT_VARKEY *gbt_var_union ( const GistEntryVector * entryvec , int32 * size ,
|
extern GBT_VARKEY *gbt_var_union(const GistEntryVector *entryvec, int32 *size,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
|
|
||||||
extern bool gbt_var_same ( bool * result, const Datum d1 , const Datum d2 ,
|
extern bool gbt_var_same(bool *result, const Datum d1, const Datum d2,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
|
|
||||||
extern float *gbt_var_penalty ( float * res , const GISTENTRY * o , const GISTENTRY * n,
|
extern float *gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
|
|
||||||
extern bool gbt_var_consistent( GBT_VARKEY_R * key , const void * query,
|
extern bool gbt_var_consistent(GBT_VARKEY_R * key, const void *query,
|
||||||
const StrategyNumber * strategy , bool is_leaf,
|
const StrategyNumber *strategy, bool is_leaf,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
|
|
||||||
extern GIST_SPLITVEC *gbt_var_picksplit ( const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
extern GIST_SPLITVEC *gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
extern void gbt_var_bin_union ( Datum * u , GBT_VARKEY * e ,
|
extern void gbt_var_bin_union(Datum *u, GBT_VARKEY * e,
|
||||||
const gbtree_vinfo * tinfo );
|
const gbtree_vinfo * tinfo);
|
||||||
|
@ -230,7 +230,7 @@ g_cube_union(GistEntryVector *entryvec, int *sizep)
|
|||||||
for (i = 1; i < entryvec->n; i++)
|
for (i = 1; i < entryvec->n; i++)
|
||||||
{
|
{
|
||||||
out = g_cube_binary_union(tmp, (NDBOX *)
|
out = g_cube_binary_union(tmp, (NDBOX *)
|
||||||
DatumGetPointer(entryvec->vector[i].key),
|
DatumGetPointer(entryvec->vector[i].key),
|
||||||
sizep);
|
sizep);
|
||||||
if (i > 1)
|
if (i > 1)
|
||||||
pfree(tmp);
|
pfree(tmp);
|
||||||
|
@ -700,7 +700,7 @@ main(int argc, char **argv)
|
|||||||
if (verbose > 1)
|
if (verbose > 1)
|
||||||
printf("Opening dbf-file\n");
|
printf("Opening dbf-file\n");
|
||||||
|
|
||||||
setlocale(LC_ALL, ""); /* fix for isprint() */
|
setlocale(LC_ALL, ""); /* fix for isprint() */
|
||||||
|
|
||||||
if ((dbh = dbf_open(argv[0], O_RDONLY)) == (dbhead *) - 1)
|
if ((dbh = dbf_open(argv[0], O_RDONLY)) == (dbhead *) - 1)
|
||||||
{
|
{
|
||||||
|
@ -571,8 +571,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
|||||||
rsinfo->expectedDesc == NULL)
|
rsinfo->expectedDesc == NULL)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("function returning record called in context "
|
errmsg("function returning record called in context "
|
||||||
"that cannot accept type record")));
|
"that cannot accept type record")));
|
||||||
|
|
||||||
/* get the requested return tuple description */
|
/* get the requested return tuple description */
|
||||||
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
|
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
|
||||||
@ -777,8 +777,8 @@ dblink_record(PG_FUNCTION_ARGS)
|
|||||||
rsinfo->expectedDesc == NULL)
|
rsinfo->expectedDesc == NULL)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("function returning record called in context "
|
errmsg("function returning record called in context "
|
||||||
"that cannot accept type record")));
|
"that cannot accept type record")));
|
||||||
|
|
||||||
/* get the requested return tuple description */
|
/* get the requested return tuple description */
|
||||||
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
|
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* pending.c
|
* pending.c
|
||||||
* $Id: pending.c,v 1.18 2004/05/26 00:08:26 wieck Exp $
|
* $Id: pending.c,v 1.19 2004/08/29 05:06:35 momjian Exp $
|
||||||
* $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.18 2004/05/26 00:08:26 wieck Exp $
|
* $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.19 2004/08/29 05:06:35 momjian Exp $
|
||||||
*
|
*
|
||||||
* This file contains a trigger for Postgresql-7.x to record changes to tables
|
* This file contains a trigger for Postgresql-7.x to record changes to tables
|
||||||
* to a pending table for mirroring.
|
* to a pending table for mirroring.
|
||||||
@ -43,17 +43,17 @@ enum FieldUsage
|
|||||||
};
|
};
|
||||||
|
|
||||||
int storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
int storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
||||||
HeapTuple tAfterTuple,
|
HeapTuple tAfterTuple,
|
||||||
TupleDesc tTupdesc,
|
TupleDesc tTupdesc,
|
||||||
Oid tableOid,
|
Oid tableOid,
|
||||||
char cOp);
|
char cOp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int storeKeyInfo(char *cpTableName, HeapTuple tTupleData, TupleDesc tTuplDesc,
|
int storeKeyInfo(char *cpTableName, HeapTuple tTupleData, TupleDesc tTuplDesc,
|
||||||
Oid tableOid);
|
Oid tableOid);
|
||||||
int storeData(char *cpTableName, HeapTuple tTupleData,
|
int storeData(char *cpTableName, HeapTuple tTupleData,
|
||||||
TupleDesc tTupleDesc,Oid tableOid,int iIncludeKeyData);
|
TupleDesc tTupleDesc, Oid tableOid, int iIncludeKeyData);
|
||||||
|
|
||||||
int2vector *getPrimaryKey(Oid tblOid);
|
int2vector *getPrimaryKey(Oid tblOid);
|
||||||
|
|
||||||
@ -77,7 +77,6 @@ PG_FUNCTION_INFO_V1(recordchange);
|
|||||||
#define debug_msg2(x,y)
|
#define debug_msg2(x,y)
|
||||||
#define debug_msg(x)
|
#define debug_msg(x)
|
||||||
#define debug_msg3(x,y,z)
|
#define debug_msg3(x,y,z)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -85,8 +84,8 @@ PG_FUNCTION_INFO_V1(recordchange);
|
|||||||
extern Datum nextval(PG_FUNCTION_ARGS);
|
extern Datum nextval(PG_FUNCTION_ARGS);
|
||||||
extern Datum setval(PG_FUNCTION_ARGS);
|
extern Datum setval(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
int saveSequenceUpdate(const text * sequenceName,
|
int saveSequenceUpdate(const text *sequenceName,
|
||||||
int nextSequenceValue);
|
int nextSequenceValue);
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -107,15 +106,15 @@ recordchange(PG_FUNCTION_ARGS)
|
|||||||
char op = 0;
|
char op = 0;
|
||||||
char *schemaname;
|
char *schemaname;
|
||||||
char *fullyqualtblname;
|
char *fullyqualtblname;
|
||||||
char *pkxpress=NULL;
|
char *pkxpress = NULL;
|
||||||
|
|
||||||
if (fcinfo->context != NULL)
|
if (fcinfo->context != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (SPI_connect() < 0)
|
if (SPI_connect() < 0)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_CONNECTION_FAILURE),
|
ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE),
|
||||||
errmsg("dbmirror:recordchange could not connect to SPI")));
|
errmsg("dbmirror:recordchange could not connect to SPI")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
trigdata = (TriggerData *) fcinfo->context;
|
trigdata = (TriggerData *) fcinfo->context;
|
||||||
@ -154,13 +153,13 @@ recordchange(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
|
||||||
errmsg("dbmirror:recordchange Unknown operation")));
|
errmsg("dbmirror:recordchange Unknown operation")));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storePending(fullyqualtblname, beforeTuple, afterTuple,
|
if (storePending(fullyqualtblname, beforeTuple, afterTuple,
|
||||||
tupdesc, retTuple->t_tableOid, op))
|
tupdesc, retTuple->t_tableOid, op))
|
||||||
{
|
{
|
||||||
/* An error occoured. Skip the operation. */
|
/* An error occoured. Skip the operation. */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -173,8 +172,8 @@ recordchange(PG_FUNCTION_ARGS)
|
|||||||
debug_msg("dbmirror:recordchange returning on success");
|
debug_msg("dbmirror:recordchange returning on success");
|
||||||
|
|
||||||
SPI_pfree(fullyqualtblname);
|
SPI_pfree(fullyqualtblname);
|
||||||
if(pkxpress != NULL)
|
if (pkxpress != NULL)
|
||||||
SPI_pfree(pkxpress);
|
SPI_pfree(pkxpress);
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
return PointerGetDatum(retTuple);
|
return PointerGetDatum(retTuple);
|
||||||
}
|
}
|
||||||
@ -196,20 +195,20 @@ int
|
|||||||
storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
||||||
HeapTuple tAfterTuple,
|
HeapTuple tAfterTuple,
|
||||||
TupleDesc tTupDesc,
|
TupleDesc tTupDesc,
|
||||||
Oid tableOid,
|
Oid tableOid,
|
||||||
char cOp)
|
char cOp)
|
||||||
{
|
{
|
||||||
char *cpQueryBase = "INSERT INTO dbmirror_pending (TableName,Op,XID) VALUES ($1,$2,$3)";
|
char *cpQueryBase = "INSERT INTO dbmirror_pending (TableName,Op,XID) VALUES ($1,$2,$3)";
|
||||||
|
|
||||||
int iResult = 0;
|
int iResult = 0;
|
||||||
HeapTuple tCurTuple;
|
HeapTuple tCurTuple;
|
||||||
char nulls[3]=" ";
|
char nulls[3] = " ";
|
||||||
|
|
||||||
/* Points the current tuple(before or after) */
|
/* Points the current tuple(before or after) */
|
||||||
Datum saPlanData[3];
|
Datum saPlanData[3];
|
||||||
Oid taPlanArgTypes[4] = {NAMEOID,
|
Oid taPlanArgTypes[4] = {NAMEOID,
|
||||||
CHAROID,
|
CHAROID,
|
||||||
INT4OID};
|
INT4OID};
|
||||||
void *vpPlan;
|
void *vpPlan;
|
||||||
|
|
||||||
tCurTuple = tBeforeTuple ? tBeforeTuple : tAfterTuple;
|
tCurTuple = tBeforeTuple ? tBeforeTuple : tAfterTuple;
|
||||||
@ -218,8 +217,8 @@ storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
|||||||
|
|
||||||
vpPlan = SPI_prepare(cpQueryBase, 3, taPlanArgTypes);
|
vpPlan = SPI_prepare(cpQueryBase, 3, taPlanArgTypes);
|
||||||
if (vpPlan == NULL)
|
if (vpPlan == NULL)
|
||||||
ereport(ERROR,(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
|
||||||
errmsg("dbmirror:storePending error creating plan")));
|
errmsg("dbmirror:storePending error creating plan")));
|
||||||
|
|
||||||
|
|
||||||
saPlanData[0] = PointerGetDatum(cpTableName);
|
saPlanData[0] = PointerGetDatum(cpTableName);
|
||||||
@ -229,7 +228,7 @@ storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
|||||||
iResult = SPI_execp(vpPlan, saPlanData, nulls, 1);
|
iResult = SPI_execp(vpPlan, saPlanData, nulls, 1);
|
||||||
if (iResult < 0)
|
if (iResult < 0)
|
||||||
elog(NOTICE, "storedPending fired (%s) returned %d",
|
elog(NOTICE, "storedPending fired (%s) returned %d",
|
||||||
cpQueryBase, iResult);
|
cpQueryBase, iResult);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -243,7 +242,7 @@ storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
|||||||
* Just store the key data.
|
* Just store the key data.
|
||||||
*/
|
*/
|
||||||
iResult = storeKeyInfo(cpTableName,
|
iResult = storeKeyInfo(cpTableName,
|
||||||
tBeforeTuple, tTupDesc, tableOid);
|
tBeforeTuple, tTupDesc, tableOid);
|
||||||
}
|
}
|
||||||
else if (cOp == 'i')
|
else if (cOp == 'i')
|
||||||
{
|
{
|
||||||
@ -252,17 +251,17 @@ storePending(char *cpTableName, HeapTuple tBeforeTuple,
|
|||||||
* Store all data
|
* Store all data
|
||||||
*/
|
*/
|
||||||
iResult = storeData(cpTableName, tAfterTuple,
|
iResult = storeData(cpTableName, tAfterTuple,
|
||||||
tTupDesc, tableOid,TRUE);
|
tTupDesc, tableOid, TRUE);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* op must be an update. */
|
/* op must be an update. */
|
||||||
iResult = storeKeyInfo(cpTableName, tBeforeTuple,
|
iResult = storeKeyInfo(cpTableName, tBeforeTuple,
|
||||||
tTupDesc, tableOid);
|
tTupDesc, tableOid);
|
||||||
iResult = iResult ? iResult :
|
iResult = iResult ? iResult :
|
||||||
storeData(cpTableName, tAfterTuple, tTupDesc,
|
storeData(cpTableName, tAfterTuple, tTupDesc,
|
||||||
tableOid,TRUE);
|
tableOid, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -292,7 +291,7 @@ storeKeyInfo(char *cpTableName, HeapTuple tTupleData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pplan = SPI_saveplan(pplan); */
|
/* pplan = SPI_saveplan(pplan); */
|
||||||
cpKeyData = packageData(tTupleData, tTupleDesc,tableOid, PRIMARY);
|
cpKeyData = packageData(tTupleData, tTupleDesc, tableOid, PRIMARY);
|
||||||
if (cpKeyData == NULL)
|
if (cpKeyData == NULL)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
@ -312,8 +311,8 @@ storeKeyInfo(char *cpTableName, HeapTuple tTupleData,
|
|||||||
|
|
||||||
if (iRetCode != SPI_OK_INSERT)
|
if (iRetCode != SPI_OK_INSERT)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION)
|
ereport(ERROR, (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION)
|
||||||
,errmsg("error inserting row in pendingDelete")));
|
,errmsg("error inserting row in pendingDelete")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,7 +360,7 @@ getPrimaryKey(Oid tblOid)
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int
|
int
|
||||||
storeData(char *cpTableName, HeapTuple tTupleData,
|
storeData(char *cpTableName, HeapTuple tTupleData,
|
||||||
TupleDesc tTupleDesc,Oid tableOid, int iIncludeKeyData)
|
TupleDesc tTupleDesc, Oid tableOid, int iIncludeKeyData)
|
||||||
{
|
{
|
||||||
|
|
||||||
Oid planArgTypes[1] = {NAMEOID};
|
Oid planArgTypes[1] = {NAMEOID};
|
||||||
@ -381,9 +380,9 @@ storeData(char *cpTableName, HeapTuple tTupleData,
|
|||||||
/* pplan = SPI_saveplan(pplan); */
|
/* pplan = SPI_saveplan(pplan); */
|
||||||
if (iIncludeKeyData == 0)
|
if (iIncludeKeyData == 0)
|
||||||
cpKeyData = packageData(tTupleData, tTupleDesc,
|
cpKeyData = packageData(tTupleData, tTupleDesc,
|
||||||
tableOid, NONPRIMARY);
|
tableOid, NONPRIMARY);
|
||||||
else
|
else
|
||||||
cpKeyData = packageData(tTupleData, tTupleDesc,tableOid, ALL);
|
cpKeyData = packageData(tTupleData, tTupleDesc, tableOid, ALL);
|
||||||
|
|
||||||
planData[0] = PointerGetDatum(cpKeyData);
|
planData[0] = PointerGetDatum(cpKeyData);
|
||||||
iRetValue = SPI_execp(pplan, planData, NULL, 1);
|
iRetValue = SPI_execp(pplan, planData, NULL, 1);
|
||||||
@ -439,10 +438,10 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tpPKeys != NULL)
|
if (tpPKeys != NULL)
|
||||||
{
|
{
|
||||||
debug_msg("dbmirror:packageData have primary keys");
|
debug_msg("dbmirror:packageData have primary keys");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpDataBlock = SPI_palloc(BUFFER_SIZE);
|
cpDataBlock = SPI_palloc(BUFFER_SIZE);
|
||||||
iDataBlockSize = BUFFER_SIZE;
|
iDataBlockSize = BUFFER_SIZE;
|
||||||
@ -463,18 +462,18 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
/* Determine if this is a primary key or not. */
|
/* Determine if this is a primary key or not. */
|
||||||
iIsPrimaryKey = 0;
|
iIsPrimaryKey = 0;
|
||||||
for (iPrimaryKeyIndex = 0;
|
for (iPrimaryKeyIndex = 0;
|
||||||
(*tpPKeys)[iPrimaryKeyIndex] != 0;
|
(*tpPKeys)[iPrimaryKeyIndex] != 0;
|
||||||
iPrimaryKeyIndex++)
|
iPrimaryKeyIndex++)
|
||||||
{
|
{
|
||||||
if ((*tpPKeys)[iPrimaryKeyIndex]
|
if ((*tpPKeys)[iPrimaryKeyIndex]
|
||||||
== iColumnCounter)
|
== iColumnCounter)
|
||||||
{
|
{
|
||||||
iIsPrimaryKey = 1;
|
iIsPrimaryKey = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (iIsPrimaryKey ? (eKeyUsage != PRIMARY) :
|
if (iIsPrimaryKey ? (eKeyUsage != PRIMARY) :
|
||||||
(eKeyUsage != NONPRIMARY))
|
(eKeyUsage != NONPRIMARY))
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Don't use.
|
* Don't use.
|
||||||
@ -486,34 +485,34 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
}
|
}
|
||||||
} /* KeyUsage!=ALL */
|
} /* KeyUsage!=ALL */
|
||||||
|
|
||||||
if(tTupleDesc->attrs[iColumnCounter-1]->attisdropped)
|
if (tTupleDesc->attrs[iColumnCounter - 1]->attisdropped)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This column has been dropped.
|
* This column has been dropped.
|
||||||
* Do not mirror it.
|
* Do not mirror it.
|
||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpFieldName = DatumGetPointer(NameGetDatum
|
cpFieldName = DatumGetPointer(NameGetDatum
|
||||||
|
|
||||||
(&tTupleDesc->attrs
|
(&tTupleDesc->attrs
|
||||||
[iColumnCounter - 1]->attname));
|
[iColumnCounter - 1]->attname));
|
||||||
|
|
||||||
debug_msg2("dbmirror:packageData field name: %s", cpFieldName);
|
debug_msg2("dbmirror:packageData field name: %s", cpFieldName);
|
||||||
|
|
||||||
while (iDataBlockSize - iUsedDataBlock <
|
while (iDataBlockSize - iUsedDataBlock <
|
||||||
strlen(cpFieldName) + 6)
|
strlen(cpFieldName) + 6)
|
||||||
{
|
{
|
||||||
cpDataBlock = SPI_repalloc(cpDataBlock,
|
cpDataBlock = SPI_repalloc(cpDataBlock,
|
||||||
iDataBlockSize +
|
iDataBlockSize +
|
||||||
BUFFER_SIZE);
|
BUFFER_SIZE);
|
||||||
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
sprintf(cpDataBlock + iUsedDataBlock, "\"%s\"=", cpFieldName);
|
sprintf(cpDataBlock + iUsedDataBlock, "\"%s\"=", cpFieldName);
|
||||||
iUsedDataBlock = iUsedDataBlock + strlen(cpFieldName) + 3;
|
iUsedDataBlock = iUsedDataBlock + strlen(cpFieldName) + 3;
|
||||||
cpFieldData = SPI_getvalue(tTupleData, tTupleDesc,
|
cpFieldData = SPI_getvalue(tTupleData, tTupleDesc,
|
||||||
iColumnCounter);
|
iColumnCounter);
|
||||||
|
|
||||||
cpUnFormatedPtr = cpFieldData;
|
cpUnFormatedPtr = cpFieldData;
|
||||||
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
||||||
@ -532,7 +531,7 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
|
|
||||||
}
|
}
|
||||||
debug_msg2("dbmirror:packageData field data: \"%s\"",
|
debug_msg2("dbmirror:packageData field data: \"%s\"",
|
||||||
cpFieldData);
|
cpFieldData);
|
||||||
debug_msg("dbmirror:packageData starting format loop");
|
debug_msg("dbmirror:packageData starting format loop");
|
||||||
|
|
||||||
while (*cpUnFormatedPtr != 0)
|
while (*cpUnFormatedPtr != 0)
|
||||||
@ -540,8 +539,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
while (iDataBlockSize - iUsedDataBlock < 2)
|
while (iDataBlockSize - iUsedDataBlock < 2)
|
||||||
{
|
{
|
||||||
cpDataBlock = SPI_repalloc(cpDataBlock,
|
cpDataBlock = SPI_repalloc(cpDataBlock,
|
||||||
iDataBlockSize
|
iDataBlockSize
|
||||||
+ BUFFER_SIZE);
|
+ BUFFER_SIZE);
|
||||||
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
||||||
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
||||||
}
|
}
|
||||||
@ -562,8 +561,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
while (iDataBlockSize - iUsedDataBlock < 3)
|
while (iDataBlockSize - iUsedDataBlock < 3)
|
||||||
{
|
{
|
||||||
cpDataBlock = SPI_repalloc(cpDataBlock,
|
cpDataBlock = SPI_repalloc(cpDataBlock,
|
||||||
iDataBlockSize +
|
iDataBlockSize +
|
||||||
BUFFER_SIZE);
|
BUFFER_SIZE);
|
||||||
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
iDataBlockSize = iDataBlockSize + BUFFER_SIZE;
|
||||||
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
cpFormatedPtr = cpDataBlock + iUsedDataBlock;
|
||||||
}
|
}
|
||||||
@ -571,15 +570,15 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
iUsedDataBlock = iUsedDataBlock + 2;
|
iUsedDataBlock = iUsedDataBlock + 2;
|
||||||
|
|
||||||
debug_msg2("dbmirror:packageData data block: \"%s\"",
|
debug_msg2("dbmirror:packageData data block: \"%s\"",
|
||||||
cpDataBlock);
|
cpDataBlock);
|
||||||
|
|
||||||
} /* for iColumnCounter */
|
} /* for iColumnCounter */
|
||||||
if (tpPKeys != NULL)
|
if (tpPKeys != NULL)
|
||||||
SPI_pfree(tpPKeys);
|
SPI_pfree(tpPKeys);
|
||||||
|
|
||||||
debug_msg3("dbmirror:packageData returning DataBlockSize:%d iUsedDataBlock:%d",
|
debug_msg3("dbmirror:packageData returning DataBlockSize:%d iUsedDataBlock:%d",
|
||||||
iDataBlockSize,
|
iDataBlockSize,
|
||||||
iUsedDataBlock);
|
iUsedDataBlock);
|
||||||
|
|
||||||
memset(cpDataBlock + iUsedDataBlock, 0, iDataBlockSize - iUsedDataBlock);
|
memset(cpDataBlock + iUsedDataBlock, 0, iDataBlockSize - iUsedDataBlock);
|
||||||
|
|
||||||
@ -590,54 +589,55 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
|
|||||||
|
|
||||||
PG_FUNCTION_INFO_V1(setval);
|
PG_FUNCTION_INFO_V1(setval);
|
||||||
|
|
||||||
Datum setval(PG_FUNCTION_ARGS)
|
Datum
|
||||||
|
setval(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
text * sequenceName;
|
text *sequenceName;
|
||||||
|
|
||||||
Oid setvalArgTypes[2] = {TEXTOID,INT4OID};
|
Oid setvalArgTypes[2] = {TEXTOID, INT4OID};
|
||||||
int nextValue;
|
int nextValue;
|
||||||
void * setvalPlan=NULL;
|
void *setvalPlan = NULL;
|
||||||
Datum setvalData[2];
|
Datum setvalData[2];
|
||||||
const char * setvalQuery = "SELECT setval_pg($1,$2)";
|
const char *setvalQuery = "SELECT setval_pg($1,$2)";
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sequenceName = PG_GETARG_TEXT_P(0);
|
sequenceName = PG_GETARG_TEXT_P(0);
|
||||||
nextValue = PG_GETARG_INT32(1);
|
nextValue = PG_GETARG_INT32(1);
|
||||||
|
|
||||||
setvalData[0] = PointerGetDatum(sequenceName);
|
setvalData[0] = PointerGetDatum(sequenceName);
|
||||||
setvalData[1] = Int32GetDatum(nextValue);
|
setvalData[1] = Int32GetDatum(nextValue);
|
||||||
|
|
||||||
if (SPI_connect() < 0)
|
if (SPI_connect() < 0)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
||||||
errmsg("dbmirror:setval could not connect to SPI")));
|
errmsg("dbmirror:setval could not connect to SPI")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
setvalPlan = SPI_prepare(setvalQuery,2,setvalArgTypes);
|
setvalPlan = SPI_prepare(setvalQuery, 2, setvalArgTypes);
|
||||||
if(setvalPlan == NULL)
|
if (setvalPlan == NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
||||||
errmsg("dbmirror:setval could not prepare plan")));
|
errmsg("dbmirror:setval could not prepare plan")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = SPI_execp(setvalPlan,setvalData,NULL,1);
|
ret = SPI_execp(setvalPlan, setvalData, NULL, 1);
|
||||||
|
|
||||||
if(ret != SPI_OK_SELECT || SPI_processed != 1)
|
if (ret != SPI_OK_SELECT || SPI_processed != 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
debug_msg2("dbmirror:setval: setval_pg returned ok:%d",nextValue);
|
debug_msg2("dbmirror:setval: setval_pg returned ok:%d", nextValue);
|
||||||
|
|
||||||
ret = saveSequenceUpdate(sequenceName,nextValue);
|
ret = saveSequenceUpdate(sequenceName, nextValue);
|
||||||
|
|
||||||
SPI_pfree(setvalPlan);
|
SPI_pfree(setvalPlan);
|
||||||
|
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
debug_msg("dbmirror:setval about to return");
|
debug_msg("dbmirror:setval about to return");
|
||||||
return Int64GetDatum(nextValue);
|
return Int64GetDatum(nextValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,131 +648,128 @@ PG_FUNCTION_INFO_V1(nextval);
|
|||||||
Datum
|
Datum
|
||||||
nextval(PG_FUNCTION_ARGS)
|
nextval(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text * sequenceName;
|
text *sequenceName;
|
||||||
|
|
||||||
const char * nextvalQuery = "SELECT nextval_pg($1)";
|
const char *nextvalQuery = "SELECT nextval_pg($1)";
|
||||||
Oid nextvalArgTypes[1] = {TEXTOID};
|
Oid nextvalArgTypes[1] = {TEXTOID};
|
||||||
void * nextvalPlan=NULL;
|
void *nextvalPlan = NULL;
|
||||||
Datum nextvalData[1];
|
Datum nextvalData[1];
|
||||||
|
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
HeapTuple resTuple;
|
HeapTuple resTuple;
|
||||||
char isNull;
|
char isNull;
|
||||||
int nextSequenceValue;
|
int nextSequenceValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
debug_msg("dbmirror:nextval Starting pending.so:nextval");
|
debug_msg("dbmirror:nextval Starting pending.so:nextval");
|
||||||
|
|
||||||
|
|
||||||
sequenceName = PG_GETARG_TEXT_P(0);
|
sequenceName = PG_GETARG_TEXT_P(0);
|
||||||
|
|
||||||
if (SPI_connect() < 0)
|
if (SPI_connect() < 0)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
||||||
errmsg("dbmirror:nextval could not connect to SPI")));
|
errmsg("dbmirror:nextval could not connect to SPI")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextvalPlan = SPI_prepare(nextvalQuery,1,nextvalArgTypes);
|
nextvalPlan = SPI_prepare(nextvalQuery, 1, nextvalArgTypes);
|
||||||
|
|
||||||
|
|
||||||
debug_msg("prepared plan to call nextval_pg");
|
debug_msg("prepared plan to call nextval_pg");
|
||||||
|
|
||||||
|
|
||||||
if(nextvalPlan==NULL)
|
if (nextvalPlan == NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
|
||||||
errmsg("dbmirror:nextval error creating plan")));
|
errmsg("dbmirror:nextval error creating plan")));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nextvalData[0] = PointerGetDatum(sequenceName);
|
nextvalData[0] = PointerGetDatum(sequenceName);
|
||||||
|
|
||||||
ret = SPI_execp(nextvalPlan,nextvalData,NULL,1);
|
ret = SPI_execp(nextvalPlan, nextvalData, NULL, 1);
|
||||||
|
|
||||||
debug_msg("dbmirror:Executed call to nextval_pg");
|
debug_msg("dbmirror:Executed call to nextval_pg");
|
||||||
|
|
||||||
|
|
||||||
if(ret != SPI_OK_SELECT || SPI_processed != 1)
|
if (ret != SPI_OK_SELECT || SPI_processed != 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
resTuple = SPI_tuptable->vals[0];
|
resTuple = SPI_tuptable->vals[0];
|
||||||
|
|
||||||
debug_msg("dbmirror:nextval Set resTuple");
|
debug_msg("dbmirror:nextval Set resTuple");
|
||||||
|
|
||||||
nextSequenceValue =* (unsigned int *)(DatumGetPointer(SPI_getbinval(resTuple,
|
nextSequenceValue = *(unsigned int *) (DatumGetPointer(SPI_getbinval(resTuple,
|
||||||
SPI_tuptable->tupdesc,
|
SPI_tuptable->tupdesc,
|
||||||
1,&isNull)));
|
1, &isNull)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
debug_msg2("dbmirror:nextval Set SPI_getbinval:%d",nextSequenceValue);
|
debug_msg2("dbmirror:nextval Set SPI_getbinval:%d", nextSequenceValue);
|
||||||
|
|
||||||
|
|
||||||
saveSequenceUpdate(sequenceName,nextSequenceValue);
|
saveSequenceUpdate(sequenceName, nextSequenceValue);
|
||||||
SPI_pfree(resTuple);
|
SPI_pfree(resTuple);
|
||||||
SPI_pfree(nextvalPlan);
|
SPI_pfree(nextvalPlan);
|
||||||
|
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
|
|
||||||
return Int64GetDatum(nextSequenceValue);
|
return Int64GetDatum(nextSequenceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
saveSequenceUpdate(const text * sequenceName,
|
saveSequenceUpdate(const text *sequenceName,
|
||||||
int nextSequenceVal)
|
int nextSequenceVal)
|
||||||
{
|
{
|
||||||
|
|
||||||
Oid insertArgTypes[2] = {TEXTOID,INT4OID};
|
Oid insertArgTypes[2] = {TEXTOID, INT4OID};
|
||||||
Oid insertDataArgTypes[1] = {NAMEOID};
|
Oid insertDataArgTypes[1] = {NAMEOID};
|
||||||
void * insertPlan=NULL;
|
void *insertPlan = NULL;
|
||||||
void * insertDataPlan=NULL;
|
void *insertDataPlan = NULL;
|
||||||
Datum insertDatum[2];
|
Datum insertDatum[2];
|
||||||
Datum insertDataDatum[1];
|
Datum insertDataDatum[1];
|
||||||
char nextSequenceText[32];
|
char nextSequenceText[32];
|
||||||
|
|
||||||
const char * insertQuery =
|
const char *insertQuery =
|
||||||
"INSERT INTO dbmirror_Pending (TableName,Op,XID) VALUES" \
|
"INSERT INTO dbmirror_Pending (TableName,Op,XID) VALUES" \
|
||||||
"($1,'s',$2)";
|
"($1,'s',$2)";
|
||||||
const char * insertDataQuery =
|
const char *insertDataQuery =
|
||||||
"INSERT INTO dbmirror_PendingData(SeqId,IsKey,Data) VALUES " \
|
"INSERT INTO dbmirror_PendingData(SeqId,IsKey,Data) VALUES " \
|
||||||
"(currval('dbmirror_pending_seqid_seq'),'t',$1)";
|
"(currval('dbmirror_pending_seqid_seq'),'t',$1)";
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
insertPlan = SPI_prepare(insertQuery,2,insertArgTypes);
|
insertPlan = SPI_prepare(insertQuery, 2, insertArgTypes);
|
||||||
insertDataPlan = SPI_prepare(insertDataQuery,1,insertDataArgTypes);
|
insertDataPlan = SPI_prepare(insertDataQuery, 1, insertDataArgTypes);
|
||||||
|
|
||||||
debug_msg("Prepared insert query");
|
debug_msg("Prepared insert query");
|
||||||
|
|
||||||
|
|
||||||
if(insertPlan == NULL || insertDataPlan == NULL)
|
if (insertPlan == NULL || insertDataPlan == NULL)
|
||||||
{
|
ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), errmsg("dbmirror:nextval error creating plan")));
|
||||||
ereport(ERROR,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),errmsg("dbmirror:nextval error creating plan")));
|
|
||||||
}
|
|
||||||
|
|
||||||
insertDatum[1] = Int32GetDatum(GetCurrentTransactionId());
|
insertDatum[1] = Int32GetDatum(GetCurrentTransactionId());
|
||||||
insertDatum[0] = PointerGetDatum(sequenceName);
|
insertDatum[0] = PointerGetDatum(sequenceName);
|
||||||
|
|
||||||
sprintf(nextSequenceText,"%d",nextSequenceVal);
|
sprintf(nextSequenceText, "%d", nextSequenceVal);
|
||||||
insertDataDatum[0] = PointerGetDatum(nextSequenceText);
|
insertDataDatum[0] = PointerGetDatum(nextSequenceText);
|
||||||
debug_msg2("dbmirror:savesequenceupdate: Setting value %s",
|
debug_msg2("dbmirror:savesequenceupdate: Setting value %s",
|
||||||
nextSequenceText);
|
nextSequenceText);
|
||||||
|
|
||||||
debug_msg("dbmirror:About to execute insert query");
|
debug_msg("dbmirror:About to execute insert query");
|
||||||
|
|
||||||
ret = SPI_execp(insertPlan,insertDatum,NULL,1);
|
ret = SPI_execp(insertPlan, insertDatum, NULL, 1);
|
||||||
|
|
||||||
ret = SPI_execp(insertDataPlan,insertDataDatum,NULL,1);
|
ret = SPI_execp(insertDataPlan, insertDataDatum, NULL, 1);
|
||||||
|
|
||||||
debug_msg("dbmirror:Insert query finished");
|
debug_msg("dbmirror:Insert query finished");
|
||||||
SPI_pfree(insertPlan);
|
SPI_pfree(insertPlan);
|
||||||
SPI_pfree(insertDataPlan);
|
SPI_pfree(insertDataPlan);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static int64
|
static int64
|
||||||
get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK);
|
get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK);
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
psnprintf(size_t len, const char *fmt,...)
|
psnprintf(size_t len, const char *fmt,...)
|
||||||
@ -50,10 +50,11 @@ database_size(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
Oid dbid;
|
Oid dbid;
|
||||||
int64 totalsize;
|
int64 totalsize;
|
||||||
|
|
||||||
#ifdef SYMLINK
|
#ifdef SYMLINK
|
||||||
Relation dbrel;
|
Relation dbrel;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dbid = get_database_oid(NameStr(*dbname));
|
dbid = get_database_oid(NameStr(*dbname));
|
||||||
@ -69,10 +70,11 @@ database_size(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
totalsize = 0;
|
totalsize = 0;
|
||||||
|
|
||||||
while((tuple = heap_getnext(scan, ForwardScanDirection)))
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)))
|
||||||
{
|
{
|
||||||
Oid spcid = HeapTupleGetOid(tuple);
|
Oid spcid = HeapTupleGetOid(tuple);
|
||||||
if(spcid != GLOBALTABLESPACE_OID)
|
|
||||||
|
if (spcid != GLOBALTABLESPACE_OID)
|
||||||
totalsize += get_tablespace_size(dbid, spcid, true);
|
totalsize += get_tablespace_size(dbid, spcid, true);
|
||||||
}
|
}
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
@ -94,8 +96,8 @@ database_size(PG_FUNCTION_ARGS)
|
|||||||
static int64
|
static int64
|
||||||
get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK)
|
get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK)
|
||||||
{
|
{
|
||||||
char *dbpath;
|
char *dbpath;
|
||||||
DIR *dirdesc;
|
DIR *dirdesc;
|
||||||
struct dirent *direntry;
|
struct dirent *direntry;
|
||||||
int64 totalsize;
|
int64 totalsize;
|
||||||
|
|
||||||
@ -104,11 +106,11 @@ get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK)
|
|||||||
dirdesc = AllocateDir(dbpath);
|
dirdesc = AllocateDir(dbpath);
|
||||||
if (!dirdesc)
|
if (!dirdesc)
|
||||||
{
|
{
|
||||||
if(baddirOK)
|
if (baddirOK)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not open directory \"%s\": %m", dbpath)));
|
errmsg("could not open directory \"%s\": %m", dbpath)));
|
||||||
}
|
}
|
||||||
totalsize = 0;
|
totalsize = 0;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
* especially they can be a bit different, depending on pronunciation.
|
* especially they can be a bit different, depending on pronunciation.
|
||||||
*
|
*
|
||||||
* Information on using Double Metaphone can be found at
|
* Information on using Double Metaphone can be found at
|
||||||
* http://www.codeproject.com/useritems/dmetaphone1.asp
|
* http://www.codeproject.com/useritems/dmetaphone1.asp
|
||||||
* and the original article describing it can be found at
|
* and the original article describing it can be found at
|
||||||
* http://www.cuj.com/documents/s=8038/cuj0006philips/
|
* http://www.cuj.com/documents/s=8038/cuj0006philips/
|
||||||
*
|
*
|
||||||
* For PostgrSQL we provide 2 functions - one for the primary and one for
|
* For PostgrSQL we provide 2 functions - one for the primary and one for
|
||||||
* the alternate. That way the functions are pure text->text mappings that
|
* the alternate. That way the functions are pure text->text mappings that
|
||||||
@ -19,12 +19,12 @@
|
|||||||
* functions looks like this:
|
* functions looks like this:
|
||||||
*
|
*
|
||||||
* CREATE FUNCTION dmetaphone (text) RETURNS text
|
* CREATE FUNCTION dmetaphone (text) RETURNS text
|
||||||
* LANGUAGE C IMMUTABLE STRICT
|
* LANGUAGE C IMMUTABLE STRICT
|
||||||
* AS '$libdir/dmetaphone', 'dmetaphone';
|
* AS '$libdir/dmetaphone', 'dmetaphone';
|
||||||
*
|
*
|
||||||
* CREATE FUNCTION dmetaphone_alt (text) RETURNS text
|
* CREATE FUNCTION dmetaphone_alt (text) RETURNS text
|
||||||
* LANGUAGE C IMMUTABLE STRICT
|
* LANGUAGE C IMMUTABLE STRICT
|
||||||
* AS '$libdir/dmetaphone', 'dmetaphone_alt';
|
* AS '$libdir/dmetaphone', 'dmetaphone_alt';
|
||||||
*
|
*
|
||||||
* Note that you have to declare the functions IMMUTABLE if you want to
|
* Note that you have to declare the functions IMMUTABLE if you want to
|
||||||
* use them in functional indexes, and you have to declare them as STRICT
|
* use them in functional indexes, and you have to declare them as STRICT
|
||||||
@ -48,8 +48,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Revision: 1.2 $
|
* $Revision: 1.3 $
|
||||||
* $Id: dmetaphone.c,v 1.2 2004/08/20 19:48:14 momjian Exp $
|
* $Id: dmetaphone.c,v 1.3 2004/08/29 05:06:35 momjian Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +109,6 @@ The remaining code is authored by Andrew Dunstan <amdunstan@ncshp.org> and
|
|||||||
|
|
||||||
/* turn off assertions for embedded function */
|
/* turn off assertions for embedded function */
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -124,7 +123,7 @@ extern Datum dmetaphone_alt(PG_FUNCTION_ARGS);
|
|||||||
|
|
||||||
/* prototype for the main function we got from the perl module */
|
/* prototype for the main function we got from the perl module */
|
||||||
static void
|
static void
|
||||||
DoubleMetaphone(char *, char **);
|
DoubleMetaphone(char *, char **);
|
||||||
|
|
||||||
#ifndef DMETAPHONE_MAIN
|
#ifndef DMETAPHONE_MAIN
|
||||||
|
|
||||||
@ -138,37 +137,41 @@ PG_FUNCTION_INFO_V1(dmetaphone);
|
|||||||
Datum
|
Datum
|
||||||
dmetaphone(PG_FUNCTION_ARGS)
|
dmetaphone(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text * arg, * result;
|
text *arg,
|
||||||
int alen, rsize;
|
*result;
|
||||||
char * aptr, *codes[2], * code, * rptr;
|
int alen,
|
||||||
|
rsize;
|
||||||
|
char *aptr,
|
||||||
|
*codes[2],
|
||||||
|
*code,
|
||||||
|
*rptr;
|
||||||
|
|
||||||
#ifdef DMETAPHONE_NOSTRICT
|
#ifdef DMETAPHONE_NOSTRICT
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
PG_RETURNNULL();
|
PG_RETURNNULL();
|
||||||
#endif
|
#endif
|
||||||
arg = PG_GETARG_TEXT_P(0);
|
arg = PG_GETARG_TEXT_P(0);
|
||||||
alen = VARSIZE(arg)-VARHDRSZ;
|
alen = VARSIZE(arg) - VARHDRSZ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Postgres' string values might not have trailing nuls.
|
* Postgres' string values might not have trailing nuls. The VARSIZE
|
||||||
* The VARSIZE will not include the nul in any case
|
* will not include the nul in any case so we copy things out and add
|
||||||
* so we copy things out and add a trailing nul.
|
* a trailing nul. When we copy back we ignore the nul (and we don't
|
||||||
* When we copy back we ignore the nul
|
* make space for it).
|
||||||
* (and we don't make space for it).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
aptr = palloc(alen+1);
|
aptr = palloc(alen + 1);
|
||||||
memcpy(aptr,VARDATA(arg),alen);
|
memcpy(aptr, VARDATA(arg), alen);
|
||||||
aptr[alen]=0;
|
aptr[alen] = 0;
|
||||||
DoubleMetaphone(aptr,codes);
|
DoubleMetaphone(aptr, codes);
|
||||||
code = codes[0];
|
code = codes[0];
|
||||||
if (!code)
|
if (!code)
|
||||||
code = "";
|
code = "";
|
||||||
rsize = VARHDRSZ + strlen(code) ;
|
rsize = VARHDRSZ + strlen(code);
|
||||||
result = (text *) palloc(rsize);
|
result = (text *) palloc(rsize);
|
||||||
memset(result,0,rsize);
|
memset(result, 0, rsize);
|
||||||
rptr = VARDATA(result);
|
rptr = VARDATA(result);
|
||||||
memcpy(rptr,code,strlen(code));
|
memcpy(rptr, code, strlen(code));
|
||||||
VARATT_SIZEP(result) = rsize;
|
VARATT_SIZEP(result) = rsize;
|
||||||
PG_RETURN_TEXT_P(result);
|
PG_RETURN_TEXT_P(result);
|
||||||
}
|
}
|
||||||
@ -183,28 +186,33 @@ PG_FUNCTION_INFO_V1(dmetaphone_alt);
|
|||||||
Datum
|
Datum
|
||||||
dmetaphone_alt(PG_FUNCTION_ARGS)
|
dmetaphone_alt(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text * arg, * result;
|
text *arg,
|
||||||
int alen, rsize;
|
*result;
|
||||||
char * aptr, * codes[2], * code, * rptr;
|
int alen,
|
||||||
|
rsize;
|
||||||
|
char *aptr,
|
||||||
|
*codes[2],
|
||||||
|
*code,
|
||||||
|
*rptr;
|
||||||
|
|
||||||
#ifdef DMETAPHONE_NOSTRICT
|
#ifdef DMETAPHONE_NOSTRICT
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
PG_RETURNNULL();
|
PG_RETURNNULL();
|
||||||
#endif
|
#endif
|
||||||
arg = PG_GETARG_TEXT_P(0);
|
arg = PG_GETARG_TEXT_P(0);
|
||||||
alen = VARSIZE(arg)-VARHDRSZ;
|
alen = VARSIZE(arg) - VARHDRSZ;
|
||||||
aptr = palloc(alen+1);
|
aptr = palloc(alen + 1);
|
||||||
memcpy(aptr,VARDATA(arg),alen);
|
memcpy(aptr, VARDATA(arg), alen);
|
||||||
aptr[alen]=0;
|
aptr[alen] = 0;
|
||||||
DoubleMetaphone(aptr,codes);
|
DoubleMetaphone(aptr, codes);
|
||||||
code = codes[1];
|
code = codes[1];
|
||||||
if (!code)
|
if (!code)
|
||||||
code = "";
|
code = "";
|
||||||
rsize = VARHDRSZ + strlen(code) ;
|
rsize = VARHDRSZ + strlen(code);
|
||||||
result = (text *) palloc(rsize);
|
result = (text *) palloc(rsize);
|
||||||
memset(result,0,rsize);
|
memset(result, 0, rsize);
|
||||||
rptr = VARDATA(result);
|
rptr = VARDATA(result);
|
||||||
memcpy(rptr,code,strlen(code));
|
memcpy(rptr, code, strlen(code));
|
||||||
VARATT_SIZEP(result) = rsize;
|
VARATT_SIZEP(result) = rsize;
|
||||||
PG_RETURN_TEXT_P(result);
|
PG_RETURN_TEXT_P(result);
|
||||||
}
|
}
|
||||||
@ -215,10 +223,10 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
|
|||||||
/* all memory handling is done with these macros */
|
/* all memory handling is done with these macros */
|
||||||
|
|
||||||
#define META_MALLOC(v,n,t) \
|
#define META_MALLOC(v,n,t) \
|
||||||
(v = (t*)palloc(((n)*sizeof(t))))
|
(v = (t*)palloc(((n)*sizeof(t))))
|
||||||
|
|
||||||
#define META_REALLOC(v,n,t) \
|
#define META_REALLOC(v,n,t) \
|
||||||
(v = (t*)repalloc((v),((n)*sizeof(t))))
|
(v = (t*)repalloc((v),((n)*sizeof(t))))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't do pfree - it seems to cause a segv sometimes - which might have just
|
* Don't do pfree - it seems to cause a segv sometimes - which might have just
|
||||||
@ -227,21 +235,20 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
|
|||||||
* in a case like this.
|
* in a case like this.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define META_FREE(x) /* pfree((x)) */
|
#define META_FREE(x) /* pfree((x)) */
|
||||||
|
|
||||||
#else /* not defined DMETAPHONE_MAIN */
|
#else /* not defined DMETAPHONE_MAIN */
|
||||||
|
|
||||||
/* use the standard malloc library when not running in PostgreSQL */
|
/* use the standard malloc library when not running in PostgreSQL */
|
||||||
|
|
||||||
#define META_MALLOC(v,n,t) \
|
#define META_MALLOC(v,n,t) \
|
||||||
(v = (t*)malloc(((n)*sizeof(t))))
|
(v = (t*)malloc(((n)*sizeof(t))))
|
||||||
|
|
||||||
#define META_REALLOC(v,n,t) \
|
#define META_REALLOC(v,n,t) \
|
||||||
(v = (t*)realloc((v),((n)*sizeof(t))))
|
(v = (t*)realloc((v),((n)*sizeof(t))))
|
||||||
|
|
||||||
#define META_FREE(x) free((x))
|
#define META_FREE(x) free((x))
|
||||||
|
#endif /* defined DMETAPHONE_MAIN */
|
||||||
#endif /* defined DMETAPHONE_MAIN */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -249,12 +256,13 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
int length;
|
int length;
|
||||||
int bufsize;
|
int bufsize;
|
||||||
int free_string_on_destroy;
|
int free_string_on_destroy;
|
||||||
}
|
}
|
||||||
metastring;
|
|
||||||
|
metastring;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* remaining perl module funcs unchanged except for declaring them static
|
* remaining perl module funcs unchanged except for declaring them static
|
||||||
@ -265,91 +273,89 @@ metastring;
|
|||||||
static metastring *
|
static metastring *
|
||||||
NewMetaString(char *init_str)
|
NewMetaString(char *init_str)
|
||||||
{
|
{
|
||||||
metastring *s;
|
metastring *s;
|
||||||
char empty_string[] = "";
|
char empty_string[] = "";
|
||||||
|
|
||||||
META_MALLOC(s, 1, metastring);
|
META_MALLOC(s, 1, metastring);
|
||||||
assert( s != NULL );
|
assert(s != NULL);
|
||||||
|
|
||||||
if (init_str == NULL)
|
if (init_str == NULL)
|
||||||
init_str = empty_string;
|
init_str = empty_string;
|
||||||
s->length = strlen(init_str);
|
s->length = strlen(init_str);
|
||||||
/* preallocate a bit more for potential growth */
|
/* preallocate a bit more for potential growth */
|
||||||
s->bufsize = s->length + 7;
|
s->bufsize = s->length + 7;
|
||||||
|
|
||||||
META_MALLOC(s->str, s->bufsize, char);
|
META_MALLOC(s->str, s->bufsize, char);
|
||||||
assert( s->str != NULL );
|
assert(s->str != NULL);
|
||||||
|
|
||||||
strncpy(s->str, init_str, s->length + 1);
|
strncpy(s->str, init_str, s->length + 1);
|
||||||
s->free_string_on_destroy = 1;
|
s->free_string_on_destroy = 1;
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DestroyMetaString(metastring * s)
|
DestroyMetaString(metastring * s)
|
||||||
{
|
{
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (s->free_string_on_destroy && (s->str != NULL))
|
if (s->free_string_on_destroy && (s->str != NULL))
|
||||||
META_FREE(s->str);
|
META_FREE(s->str);
|
||||||
|
|
||||||
META_FREE(s);
|
META_FREE(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
IncreaseBuffer(metastring * s, int chars_needed)
|
IncreaseBuffer(metastring * s, int chars_needed)
|
||||||
{
|
{
|
||||||
META_REALLOC(s->str, (s->bufsize + chars_needed + 10), char);
|
META_REALLOC(s->str, (s->bufsize + chars_needed + 10), char);
|
||||||
assert( s->str != NULL );
|
assert(s->str != NULL);
|
||||||
s->bufsize = s->bufsize + chars_needed + 10;
|
s->bufsize = s->bufsize + chars_needed + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
MakeUpper(metastring * s)
|
MakeUpper(metastring * s)
|
||||||
{
|
{
|
||||||
char *i;
|
char *i;
|
||||||
|
|
||||||
for (i = s->str; *i; i++)
|
for (i = s->str; *i; i++)
|
||||||
{
|
|
||||||
*i = toupper(*i);
|
*i = toupper(*i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
IsVowel(metastring * s, int pos)
|
IsVowel(metastring * s, int pos)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if ((pos < 0) || (pos >= s->length))
|
if ((pos < 0) || (pos >= s->length))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
c = *(s->str + pos);
|
c = *(s->str + pos);
|
||||||
if ((c == 'A') || (c == 'E') || (c == 'I') || (c =='O') ||
|
if ((c == 'A') || (c == 'E') || (c == 'I') || (c == 'O') ||
|
||||||
(c =='U') || (c == 'Y'))
|
(c == 'U') || (c == 'Y'))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SlavoGermanic(metastring * s)
|
SlavoGermanic(metastring * s)
|
||||||
{
|
{
|
||||||
if ((char *) strstr(s->str, "W"))
|
if ((char *) strstr(s->str, "W"))
|
||||||
return 1;
|
return 1;
|
||||||
else if ((char *) strstr(s->str, "K"))
|
else if ((char *) strstr(s->str, "K"))
|
||||||
return 1;
|
return 1;
|
||||||
else if ((char *) strstr(s->str, "CZ"))
|
else if ((char *) strstr(s->str, "CZ"))
|
||||||
return 1;
|
return 1;
|
||||||
else if ((char *) strstr(s->str, "WITZ"))
|
else if ((char *) strstr(s->str, "WITZ"))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,20 +363,20 @@ SlavoGermanic(metastring * s)
|
|||||||
static char
|
static char
|
||||||
GetAt(metastring * s, int pos)
|
GetAt(metastring * s, int pos)
|
||||||
{
|
{
|
||||||
if ((pos < 0) || (pos >= s->length))
|
if ((pos < 0) || (pos >= s->length))
|
||||||
return '\0';
|
return '\0';
|
||||||
|
|
||||||
return ((char) *(s->str + pos));
|
return ((char) *(s->str + pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SetAt(metastring * s, int pos, char c)
|
SetAt(metastring * s, int pos, char c)
|
||||||
{
|
{
|
||||||
if ((pos < 0) || (pos >= s->length))
|
if ((pos < 0) || (pos >= s->length))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
*(s->str + pos) = c;
|
*(s->str + pos) = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -378,96 +384,94 @@ SetAt(metastring * s, int pos, char c)
|
|||||||
Caveats: the START value is 0 based
|
Caveats: the START value is 0 based
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
StringAt(metastring * s, int start, int length, ...)
|
StringAt(metastring * s, int start, int length,...)
|
||||||
{
|
{
|
||||||
char *test;
|
char *test;
|
||||||
char *pos;
|
char *pos;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if ((start < 0) || (start >= s->length))
|
if ((start < 0) || (start >= s->length))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pos = (s->str + start);
|
pos = (s->str + start);
|
||||||
va_start(ap, length);
|
va_start(ap, length);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
test = va_arg(ap, char *);
|
test = va_arg(ap, char *);
|
||||||
if (*test && (strncmp(pos, test, length) == 0))
|
if (*test && (strncmp(pos, test, length) == 0))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
while (strcmp(test, ""));
|
while (strcmp(test, ""));
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
MetaphAdd(metastring * s, char *new_str)
|
MetaphAdd(metastring * s, char *new_str)
|
||||||
{
|
{
|
||||||
int add_length;
|
int add_length;
|
||||||
|
|
||||||
if (new_str == NULL)
|
if (new_str == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
add_length = strlen(new_str);
|
add_length = strlen(new_str);
|
||||||
if ((s->length + add_length) > (s->bufsize - 1))
|
if ((s->length + add_length) > (s->bufsize - 1))
|
||||||
{
|
|
||||||
IncreaseBuffer(s, add_length);
|
IncreaseBuffer(s, add_length);
|
||||||
}
|
|
||||||
|
|
||||||
strcat(s->str, new_str);
|
strcat(s->str, new_str);
|
||||||
s->length += add_length;
|
s->length += add_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DoubleMetaphone(char *str, char **codes)
|
DoubleMetaphone(char *str, char **codes)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
metastring *original;
|
metastring *original;
|
||||||
metastring *primary;
|
metastring *primary;
|
||||||
metastring *secondary;
|
metastring *secondary;
|
||||||
int current;
|
int current;
|
||||||
int last;
|
int last;
|
||||||
|
|
||||||
current = 0;
|
current = 0;
|
||||||
/* we need the real length and last prior to padding */
|
/* we need the real length and last prior to padding */
|
||||||
length = strlen(str);
|
length = strlen(str);
|
||||||
last = length - 1;
|
last = length - 1;
|
||||||
original = NewMetaString(str);
|
original = NewMetaString(str);
|
||||||
/* Pad original so we can index beyond end */
|
/* Pad original so we can index beyond end */
|
||||||
MetaphAdd(original, " ");
|
MetaphAdd(original, " ");
|
||||||
|
|
||||||
primary = NewMetaString("");
|
primary = NewMetaString("");
|
||||||
secondary = NewMetaString("");
|
secondary = NewMetaString("");
|
||||||
primary->free_string_on_destroy = 0;
|
primary->free_string_on_destroy = 0;
|
||||||
secondary->free_string_on_destroy = 0;
|
secondary->free_string_on_destroy = 0;
|
||||||
|
|
||||||
MakeUpper(original);
|
MakeUpper(original);
|
||||||
|
|
||||||
/* skip these when at start of word */
|
/* skip these when at start of word */
|
||||||
if (StringAt(original, 0, 2, "GN", "KN", "PN", "WR", "PS", ""))
|
if (StringAt(original, 0, 2, "GN", "KN", "PN", "WR", "PS", ""))
|
||||||
current += 1;
|
current += 1;
|
||||||
|
|
||||||
/* Initial 'X' is pronounced 'Z' e.g. 'Xavier' */
|
/* Initial 'X' is pronounced 'Z' e.g. 'Xavier' */
|
||||||
if (GetAt(original, 0) == 'X')
|
if (GetAt(original, 0) == 'X')
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "S"); /* 'Z' maps to 'S' */
|
MetaphAdd(primary, "S"); /* 'Z' maps to 'S' */
|
||||||
MetaphAdd(secondary, "S");
|
MetaphAdd(secondary, "S");
|
||||||
current += 1;
|
current += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* main loop */
|
/* main loop */
|
||||||
while ((primary->length < 4) || (secondary->length < 4))
|
while ((primary->length < 4) || (secondary->length < 4))
|
||||||
{
|
{
|
||||||
if (current >= length)
|
if (current >= length)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (GetAt(original, current))
|
switch (GetAt(original, current))
|
||||||
{
|
{
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'I':
|
case 'I':
|
||||||
@ -508,8 +512,8 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
&& StringAt(original, (current - 1), 3, "ACH", "")
|
&& StringAt(original, (current - 1), 3, "ACH", "")
|
||||||
&& ((GetAt(original, current + 2) != 'I')
|
&& ((GetAt(original, current + 2) != 'I')
|
||||||
&& ((GetAt(original, current + 2) != 'E')
|
&& ((GetAt(original, current + 2) != 'E')
|
||||||
|| StringAt(original, (current - 2), 6, "BACHER",
|
|| StringAt(original, (current - 2), 6, "BACHER",
|
||||||
"MACHER", ""))))
|
"MACHER", ""))))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "K");
|
MetaphAdd(primary, "K");
|
||||||
MetaphAdd(secondary, "K");
|
MetaphAdd(secondary, "K");
|
||||||
@ -566,7 +570,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
if (
|
if (
|
||||||
(StringAt(original, 0, 4, "VAN ", "VON ", "")
|
(StringAt(original, 0, 4, "VAN ", "VON ", "")
|
||||||
|| StringAt(original, 0, 3, "SCH", ""))
|
|| StringAt(original, 0, 3, "SCH", ""))
|
||||||
/* 'architect but not 'arch', 'orchestra', 'orchid' */
|
/* 'architect but not 'arch', 'orchestra', 'orchid' */
|
||||||
|| StringAt(original, (current - 2), 6, "ORCHES",
|
|| StringAt(original, (current - 2), 6, "ORCHES",
|
||||||
"ARCHIT", "ORCHID", "")
|
"ARCHIT", "ORCHID", "")
|
||||||
|| StringAt(original, (current + 2), 1, "T", "S",
|
|| StringAt(original, (current + 2), 1, "T", "S",
|
||||||
@ -574,11 +578,13 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
|| ((StringAt(original, (current - 1), 1,
|
|| ((StringAt(original, (current - 1), 1,
|
||||||
"A", "O", "U", "E", "")
|
"A", "O", "U", "E", "")
|
||||||
|| (current == 0))
|
|| (current == 0))
|
||||||
/* e.g., 'wachtler', 'wechsler',
|
|
||||||
but not 'tichner' */
|
/*
|
||||||
&& StringAt(original, (current + 2), 1, "L", "R",
|
* e.g., 'wachtler', 'wechsler', but not 'tichner'
|
||||||
"N", "M", "B", "H", "F", "V", "W",
|
*/
|
||||||
" ", "")))
|
&& StringAt(original, (current + 2), 1, "L", "R",
|
||||||
|
"N", "M", "B", "H", "F", "V", "W",
|
||||||
|
" ", "")))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "K");
|
MetaphAdd(primary, "K");
|
||||||
MetaphAdd(secondary, "K");
|
MetaphAdd(secondary, "K");
|
||||||
@ -633,14 +639,14 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
{
|
{
|
||||||
/* 'bellocchio' but not 'bacchus' */
|
/* 'bellocchio' but not 'bacchus' */
|
||||||
if (StringAt(original, (current + 2), 1, "I", "E", "H", "")
|
if (StringAt(original, (current + 2), 1, "I", "E", "H", "")
|
||||||
&& !StringAt(original, (current + 2), 2, "HU", ""))
|
&& !StringAt(original, (current + 2), 2, "HU", ""))
|
||||||
{
|
{
|
||||||
/* 'accident', 'accede' 'succeed' */
|
/* 'accident', 'accede' 'succeed' */
|
||||||
if (
|
if (
|
||||||
((current == 1)
|
((current == 1)
|
||||||
&& (GetAt(original, current - 1) == 'A'))
|
&& (GetAt(original, current - 1) == 'A'))
|
||||||
|| StringAt(original, (current - 1), 5, "UCCEE",
|
|| StringAt(original, (current - 1), 5, "UCCEE",
|
||||||
"UCCES", ""))
|
"UCCES", ""))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "KS");
|
MetaphAdd(primary, "KS");
|
||||||
MetaphAdd(secondary, "KS");
|
MetaphAdd(secondary, "KS");
|
||||||
@ -655,7 +661,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Pierce's rule */
|
{ /* Pierce's rule */
|
||||||
MetaphAdd(primary, "K");
|
MetaphAdd(primary, "K");
|
||||||
MetaphAdd(secondary, "K");
|
MetaphAdd(secondary, "K");
|
||||||
current += 2;
|
current += 2;
|
||||||
@ -696,13 +702,12 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
/* name sent in 'mac caffrey', 'mac gregor */
|
/* name sent in 'mac caffrey', 'mac gregor */
|
||||||
if (StringAt(original, (current + 1), 2, " C", " Q", " G", ""))
|
if (StringAt(original, (current + 1), 2, " C", " Q", " G", ""))
|
||||||
current += 3;
|
current += 3;
|
||||||
|
else if (StringAt(original, (current + 1), 1, "C", "K", "Q", "")
|
||||||
|
&& !StringAt(original, (current + 1), 2,
|
||||||
|
"CE", "CI", ""))
|
||||||
|
current += 2;
|
||||||
else
|
else
|
||||||
if (StringAt(original, (current + 1), 1, "C", "K", "Q", "")
|
current += 1;
|
||||||
&& !StringAt(original, (current + 1), 2,
|
|
||||||
"CE", "CI", ""))
|
|
||||||
current += 2;
|
|
||||||
else
|
|
||||||
current += 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
@ -780,17 +785,20 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Parker's rule (with some further refinements) -
|
|
||||||
e.g., 'hugh' */
|
/*
|
||||||
|
* Parker's rule (with some further refinements) -
|
||||||
|
* e.g., 'hugh'
|
||||||
|
*/
|
||||||
if (
|
if (
|
||||||
((current > 1)
|
((current > 1)
|
||||||
&& StringAt(original, (current - 2), 1,
|
&& StringAt(original, (current - 2), 1,
|
||||||
"B", "H", "D", ""))
|
"B", "H", "D", ""))
|
||||||
/* e.g., 'bough' */
|
/* e.g., 'bough' */
|
||||||
|| ((current > 2)
|
|| ((current > 2)
|
||||||
&& StringAt(original, (current - 3), 1,
|
&& StringAt(original, (current - 3), 1,
|
||||||
"B", "H", "D", ""))
|
"B", "H", "D", ""))
|
||||||
/* e.g., 'broughton' */
|
/* e.g., 'broughton' */
|
||||||
|| ((current > 3)
|
|| ((current > 3)
|
||||||
&& StringAt(original, (current - 4), 1,
|
&& StringAt(original, (current - 4), 1,
|
||||||
"B", "H", "")))
|
"B", "H", "")))
|
||||||
@ -800,8 +808,10 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* e.g., 'laugh', 'McLaughlin', 'cough',
|
/*
|
||||||
'gough', 'rough', 'tough' */
|
* e.g., 'laugh', 'McLaughlin', 'cough', 'gough',
|
||||||
|
* 'rough', 'tough'
|
||||||
|
*/
|
||||||
if ((current > 2)
|
if ((current > 2)
|
||||||
&& (GetAt(original, current - 1) == 'U')
|
&& (GetAt(original, current - 1) == 'U')
|
||||||
&& StringAt(original, (current - 3), 1, "C",
|
&& StringAt(original, (current - 3), 1, "C",
|
||||||
@ -837,15 +847,15 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
if (!StringAt(original, (current + 2), 2, "EY", "")
|
if (!StringAt(original, (current + 2), 2, "EY", "")
|
||||||
&& (GetAt(original, current + 1) != 'Y')
|
&& (GetAt(original, current + 1) != 'Y')
|
||||||
&& !SlavoGermanic(original))
|
&& !SlavoGermanic(original))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "N");
|
MetaphAdd(primary, "N");
|
||||||
MetaphAdd(secondary, "KN");
|
MetaphAdd(secondary, "KN");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "KN");
|
MetaphAdd(primary, "KN");
|
||||||
MetaphAdd(secondary, "KN");
|
MetaphAdd(secondary, "KN");
|
||||||
}
|
}
|
||||||
current += 2;
|
current += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -863,9 +873,9 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
/* -ges-,-gep-,-gel-, -gie- at beginning */
|
/* -ges-,-gep-,-gel-, -gie- at beginning */
|
||||||
if ((current == 0)
|
if ((current == 0)
|
||||||
&& ((GetAt(original, current + 1) == 'Y')
|
&& ((GetAt(original, current + 1) == 'Y')
|
||||||
|| StringAt(original, (current + 1), 2, "ES", "EP",
|
|| StringAt(original, (current + 1), 2, "ES", "EP",
|
||||||
"EB", "EL", "EY", "IB", "IL", "IN", "IE",
|
"EB", "EL", "EY", "IB", "IL", "IN", "IE",
|
||||||
"EI", "ER", "")))
|
"EI", "ER", "")))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "K");
|
MetaphAdd(primary, "K");
|
||||||
MetaphAdd(secondary, "J");
|
MetaphAdd(secondary, "J");
|
||||||
@ -873,7 +883,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -ger-, -gy- */
|
/* -ger-, -gy- */
|
||||||
if (
|
if (
|
||||||
(StringAt(original, (current + 1), 2, "ER", "")
|
(StringAt(original, (current + 1), 2, "ER", "")
|
||||||
|| (GetAt(original, current + 1) == 'Y'))
|
|| (GetAt(original, current + 1) == 'Y'))
|
||||||
@ -889,7 +899,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* italian e.g, 'biaggi' */
|
/* italian e.g, 'biaggi' */
|
||||||
if (StringAt(original, (current + 1), 1, "E", "I", "Y", "")
|
if (StringAt(original, (current + 1), 1, "E", "I", "Y", "")
|
||||||
|| StringAt(original, (current - 1), 4,
|
|| StringAt(original, (current - 1), 4,
|
||||||
"AGGI", "OGGI", ""))
|
"AGGI", "OGGI", ""))
|
||||||
@ -939,7 +949,8 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
MetaphAdd(secondary, "H");
|
MetaphAdd(secondary, "H");
|
||||||
current += 2;
|
current += 2;
|
||||||
}
|
}
|
||||||
else /* also takes care of 'HH' */
|
else
|
||||||
|
/* also takes care of 'HH' */
|
||||||
current += 1;
|
current += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -991,7 +1002,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!StringAt(original, (current + 1), 1, "L", "T",
|
if (!StringAt(original, (current + 1), 1, "L", "T",
|
||||||
"K", "S", "N", "M", "B", "Z", "")
|
"K", "S", "N", "M", "B", "Z", "")
|
||||||
&& !StringAt(original, (current - 1), 1,
|
&& !StringAt(original, (current - 1), 1,
|
||||||
"S", "K", "L", ""))
|
"S", "K", "L", ""))
|
||||||
{
|
{
|
||||||
@ -1002,7 +1013,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetAt(original, current + 1) == 'J') /* it could happen! */
|
if (GetAt(original, current + 1) == 'J') /* it could happen! */
|
||||||
current += 2;
|
current += 2;
|
||||||
else
|
else
|
||||||
current += 1;
|
current += 1;
|
||||||
@ -1024,10 +1035,10 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
if (((current == (length - 3))
|
if (((current == (length - 3))
|
||||||
&& StringAt(original, (current - 1), 4, "ILLO",
|
&& StringAt(original, (current - 1), 4, "ILLO",
|
||||||
"ILLA", "ALLE", ""))
|
"ILLA", "ALLE", ""))
|
||||||
|| ((StringAt(original, (last - 1), 2, "AS", "OS", "")
|
|| ((StringAt(original, (last - 1), 2, "AS", "OS", "")
|
||||||
|| StringAt(original, last, 1, "A", "O", ""))
|
|| StringAt(original, last, 1, "A", "O", ""))
|
||||||
&& StringAt(original, (current - 1), 4,
|
&& StringAt(original, (current - 1), 4,
|
||||||
"ALLE", "")))
|
"ALLE", "")))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "L");
|
MetaphAdd(primary, "L");
|
||||||
MetaphAdd(secondary, "");
|
MetaphAdd(secondary, "");
|
||||||
@ -1045,8 +1056,8 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
case 'M':
|
case 'M':
|
||||||
if ((StringAt(original, (current - 1), 3, "UMB", "")
|
if ((StringAt(original, (current - 1), 3, "UMB", "")
|
||||||
&& (((current + 1) == last)
|
&& (((current + 1) == last)
|
||||||
|| StringAt(original, (current + 2), 2, "ER", "")))
|
|| StringAt(original, (current + 2), 2, "ER", "")))
|
||||||
/* 'dumb','thumb' */
|
/* 'dumb','thumb' */
|
||||||
|| (GetAt(original, current + 1) == 'M'))
|
|| (GetAt(original, current + 1) == 'M'))
|
||||||
current += 2;
|
current += 2;
|
||||||
else
|
else
|
||||||
@ -1102,7 +1113,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
if ((current == last)
|
if ((current == last)
|
||||||
&& !SlavoGermanic(original)
|
&& !SlavoGermanic(original)
|
||||||
&& StringAt(original, (current - 2), 2, "IE", "")
|
&& StringAt(original, (current - 2), 2, "IE", "")
|
||||||
&& !StringAt(original, (current - 4), 2, "ME", "MA", ""))
|
&& !StringAt(original, (current - 4), 2, "ME", "MA", ""))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "");
|
MetaphAdd(primary, "");
|
||||||
MetaphAdd(secondary, "R");
|
MetaphAdd(secondary, "R");
|
||||||
@ -1141,8 +1152,8 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
{
|
{
|
||||||
/* germanic */
|
/* germanic */
|
||||||
if (StringAt
|
if (StringAt
|
||||||
(original, (current + 1), 4, "HEIM", "HOEK", "HOLM",
|
(original, (current + 1), 4, "HEIM", "HOEK", "HOLM",
|
||||||
"HOLZ", ""))
|
"HOLZ", ""))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "S");
|
MetaphAdd(primary, "S");
|
||||||
MetaphAdd(secondary, "S");
|
MetaphAdd(secondary, "S");
|
||||||
@ -1174,10 +1185,11 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* german & anglicisations, e.g. 'smith' match 'schmidt',
|
/*
|
||||||
'snider' match 'schneider'
|
* german & anglicisations, e.g. 'smith' match 'schmidt',
|
||||||
also, -sz- in slavic language altho in hungarian it is
|
* 'snider' match 'schneider' also, -sz- in slavic
|
||||||
pronounced 's' */
|
* language altho in hungarian it is pronounced 's'
|
||||||
|
*/
|
||||||
if (((current == 0)
|
if (((current == 0)
|
||||||
&& StringAt(original, (current + 1), 1,
|
&& StringAt(original, (current + 1), 1,
|
||||||
"M", "N", "L", "W", ""))
|
"M", "N", "L", "W", ""))
|
||||||
@ -1252,7 +1264,7 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
|
|
||||||
/* french e.g. 'resnais', 'artois' */
|
/* french e.g. 'resnais', 'artois' */
|
||||||
if ((current == last)
|
if ((current == last)
|
||||||
&& StringAt(original, (current - 2), 2, "AI", "OI", ""))
|
&& StringAt(original, (current - 2), 2, "AI", "OI", ""))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "");
|
MetaphAdd(primary, "");
|
||||||
MetaphAdd(secondary, "S");
|
MetaphAdd(secondary, "S");
|
||||||
@ -1353,8 +1365,8 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
|
|
||||||
/* Arnow should match Arnoff */
|
/* Arnow should match Arnoff */
|
||||||
if (((current == last) && IsVowel(original, current - 1))
|
if (((current == last) && IsVowel(original, current - 1))
|
||||||
|| StringAt(original, (current - 1), 5, "EWSKI", "EWSKY",
|
|| StringAt(original, (current - 1), 5, "EWSKI", "EWSKY",
|
||||||
"OWSKI", "OWSKY", "")
|
"OWSKI", "OWSKY", "")
|
||||||
|| StringAt(original, 0, 3, "SCH", ""))
|
|| StringAt(original, 0, 3, "SCH", ""))
|
||||||
{
|
{
|
||||||
MetaphAdd(primary, "");
|
MetaphAdd(primary, "");
|
||||||
@ -1427,37 +1439,41 @@ DoubleMetaphone(char *str, char **codes)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
current += 1;
|
current += 1;
|
||||||
}
|
}
|
||||||
/* printf("PRIMARY: %s\n", primary->str);
|
|
||||||
printf("SECONDARY: %s\n", secondary->str); */
|
/*
|
||||||
|
* printf("PRIMARY: %s\n", primary->str); printf("SECONDARY:
|
||||||
|
* %s\n", secondary->str);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (primary->length > 4)
|
if (primary->length > 4)
|
||||||
SetAt(primary, 4, '\0');
|
SetAt(primary, 4, '\0');
|
||||||
|
|
||||||
if (secondary->length > 4)
|
if (secondary->length > 4)
|
||||||
SetAt(secondary, 4, '\0');
|
SetAt(secondary, 4, '\0');
|
||||||
|
|
||||||
*codes = primary->str;
|
*codes = primary->str;
|
||||||
*++codes = secondary->str;
|
*++codes = secondary->str;
|
||||||
|
|
||||||
DestroyMetaString(original);
|
DestroyMetaString(original);
|
||||||
DestroyMetaString(primary);
|
DestroyMetaString(primary);
|
||||||
DestroyMetaString(secondary);
|
DestroyMetaString(secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DMETAPHONE_MAIN
|
#ifdef DMETAPHONE_MAIN
|
||||||
|
|
||||||
/* just for testing - not part of the perl code */
|
/* just for testing - not part of the perl code */
|
||||||
|
|
||||||
main(int argc, char ** argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char * codes[2];
|
char *codes[2];
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
DoubleMetaphone(argv[1],codes);
|
DoubleMetaphone(argv[1], codes);
|
||||||
printf("%s|%s\n",codes[0],codes[1]);
|
printf("%s|%s\n", codes[0], codes[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ g_int_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
g_int_union(PG_FUNCTION_ARGS)
|
g_int_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
int4 i;
|
int4 i;
|
||||||
ArrayType *res;
|
ArrayType *res;
|
||||||
@ -317,7 +317,7 @@ comparecost(const void *a, const void *b)
|
|||||||
Datum
|
Datum
|
||||||
g_int_picksplit(PG_FUNCTION_ARGS)
|
g_int_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber i,
|
OffsetNumber i,
|
||||||
j;
|
j;
|
||||||
@ -359,10 +359,10 @@ g_int_picksplit(PG_FUNCTION_ARGS)
|
|||||||
waste = 0.0;
|
waste = 0.0;
|
||||||
for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
|
for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
|
||||||
{
|
{
|
||||||
datum_alpha = GETENTRY(entryvec,i);
|
datum_alpha = GETENTRY(entryvec, i);
|
||||||
for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
|
for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
|
||||||
{
|
{
|
||||||
datum_beta = GETENTRY(entryvec,j);
|
datum_beta = GETENTRY(entryvec, j);
|
||||||
|
|
||||||
/* compute the wasted space by unioning these guys */
|
/* compute the wasted space by unioning these guys */
|
||||||
/* size_waste = size_union - size_inter; */
|
/* size_waste = size_union - size_inter; */
|
||||||
@ -402,10 +402,10 @@ g_int_picksplit(PG_FUNCTION_ARGS)
|
|||||||
seed_2 = 2;
|
seed_2 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
datum_alpha = GETENTRY(entryvec,seed_1);
|
datum_alpha = GETENTRY(entryvec, seed_1);
|
||||||
datum_l = copy_intArrayType(datum_alpha);
|
datum_l = copy_intArrayType(datum_alpha);
|
||||||
rt__int_size(datum_l, &size_l);
|
rt__int_size(datum_l, &size_l);
|
||||||
datum_beta = GETENTRY(entryvec,seed_2);
|
datum_beta = GETENTRY(entryvec, seed_2);
|
||||||
datum_r = copy_intArrayType(datum_beta);
|
datum_r = copy_intArrayType(datum_beta);
|
||||||
rt__int_size(datum_r, &size_r);
|
rt__int_size(datum_r, &size_r);
|
||||||
|
|
||||||
@ -418,7 +418,7 @@ g_int_picksplit(PG_FUNCTION_ARGS)
|
|||||||
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
||||||
{
|
{
|
||||||
costvector[i - 1].pos = i;
|
costvector[i - 1].pos = i;
|
||||||
datum_alpha = GETENTRY(entryvec,i);
|
datum_alpha = GETENTRY(entryvec, i);
|
||||||
union_d = inner_int_union(datum_l, datum_alpha);
|
union_d = inner_int_union(datum_l, datum_alpha);
|
||||||
rt__int_size(union_d, &size_alpha);
|
rt__int_size(union_d, &size_alpha);
|
||||||
pfree(union_d);
|
pfree(union_d);
|
||||||
@ -466,7 +466,7 @@ g_int_picksplit(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* okay, which page needs least enlargement? */
|
/* okay, which page needs least enlargement? */
|
||||||
datum_alpha = GETENTRY(entryvec,i);
|
datum_alpha = GETENTRY(entryvec, i);
|
||||||
union_dl = inner_int_union(datum_l, datum_alpha);
|
union_dl = inner_int_union(datum_l, datum_alpha);
|
||||||
union_dr = inner_int_union(datum_r, datum_alpha);
|
union_dr = inner_int_union(datum_r, datum_alpha);
|
||||||
rt__int_size(union_dl, &size_alpha);
|
rt__int_size(union_dl, &size_alpha);
|
||||||
|
@ -20,38 +20,40 @@ Datum g_intbig_picksplit(PG_FUNCTION_ARGS);
|
|||||||
Datum g_intbig_union(PG_FUNCTION_ARGS);
|
Datum g_intbig_union(PG_FUNCTION_ARGS);
|
||||||
Datum g_intbig_same(PG_FUNCTION_ARGS);
|
Datum g_intbig_same(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
#define SUMBIT(val) ( \
|
#define SUMBIT(val) ( \
|
||||||
GETBITBYTE((val),0) + \
|
GETBITBYTE((val),0) + \
|
||||||
GETBITBYTE((val),1) + \
|
GETBITBYTE((val),1) + \
|
||||||
GETBITBYTE((val),2) + \
|
GETBITBYTE((val),2) + \
|
||||||
GETBITBYTE((val),3) + \
|
GETBITBYTE((val),3) + \
|
||||||
GETBITBYTE((val),4) + \
|
GETBITBYTE((val),4) + \
|
||||||
GETBITBYTE((val),5) + \
|
GETBITBYTE((val),5) + \
|
||||||
GETBITBYTE((val),6) + \
|
GETBITBYTE((val),6) + \
|
||||||
GETBITBYTE((val),7) \
|
GETBITBYTE((val),7) \
|
||||||
)
|
)
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(_intbig_in);
|
PG_FUNCTION_INFO_V1(_intbig_in);
|
||||||
Datum _intbig_in(PG_FUNCTION_ARGS);
|
Datum _intbig_in(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(_intbig_out);
|
PG_FUNCTION_INFO_V1(_intbig_out);
|
||||||
Datum _intbig_out(PG_FUNCTION_ARGS);
|
Datum _intbig_out(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
_intbig_in(PG_FUNCTION_ARGS) {
|
_intbig_in(PG_FUNCTION_ARGS)
|
||||||
ereport(ERROR,
|
{
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
ereport(ERROR,
|
||||||
errmsg("_intbig_in() not implemented")));
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
PG_RETURN_DATUM(0);
|
errmsg("_intbig_in() not implemented")));
|
||||||
|
PG_RETURN_DATUM(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
_intbig_out(PG_FUNCTION_ARGS) {
|
_intbig_out(PG_FUNCTION_ARGS)
|
||||||
ereport(ERROR,
|
{
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
ereport(ERROR,
|
||||||
errmsg("_intbig_out() not implemented")));
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
PG_RETURN_DATUM(0);
|
errmsg("_intbig_out() not implemented")));
|
||||||
|
PG_RETURN_DATUM(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,13 +61,14 @@ _intbig_out(PG_FUNCTION_ARGS) {
|
|||||||
** intbig functions
|
** intbig functions
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
static bool
|
static bool
|
||||||
_intbig_overlap(GISTTYPE *a, ArrayType *b)
|
_intbig_overlap(GISTTYPE * a, ArrayType *b)
|
||||||
{
|
{
|
||||||
int num=ARRNELEMS(b);
|
int num = ARRNELEMS(b);
|
||||||
int4 *ptr=ARRPTR(b);
|
int4 *ptr = ARRPTR(b);
|
||||||
|
|
||||||
while(num--) {
|
while (num--)
|
||||||
if (GETBIT(GETSIGN(a),HASHVAL(*ptr)))
|
{
|
||||||
|
if (GETBIT(GETSIGN(a), HASHVAL(*ptr)))
|
||||||
return true;
|
return true;
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
@ -74,13 +77,14 @@ _intbig_overlap(GISTTYPE *a, ArrayType *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_intbig_contains(GISTTYPE *a, ArrayType *b)
|
_intbig_contains(GISTTYPE * a, ArrayType *b)
|
||||||
{
|
{
|
||||||
int num=ARRNELEMS(b);
|
int num = ARRNELEMS(b);
|
||||||
int4 *ptr=ARRPTR(b);
|
int4 *ptr = ARRPTR(b);
|
||||||
|
|
||||||
while(num--) {
|
while (num--)
|
||||||
if (!GETBIT(GETSIGN(a),HASHVAL(*ptr)))
|
{
|
||||||
|
if (!GETBIT(GETSIGN(a), HASHVAL(*ptr)))
|
||||||
return false;
|
return false;
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
@ -89,10 +93,11 @@ _intbig_contains(GISTTYPE *a, ArrayType *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
g_intbig_same(PG_FUNCTION_ARGS) {
|
g_intbig_same(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
|
GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
|
||||||
GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
|
GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
if (ISALLTRUE(a) && ISALLTRUE(b))
|
if (ISALLTRUE(a) && ISALLTRUE(b))
|
||||||
*result = true;
|
*result = true;
|
||||||
@ -100,16 +105,19 @@ g_intbig_same(PG_FUNCTION_ARGS) {
|
|||||||
*result = false;
|
*result = false;
|
||||||
else if (ISALLTRUE(b))
|
else if (ISALLTRUE(b))
|
||||||
*result = false;
|
*result = false;
|
||||||
else {
|
else
|
||||||
int4 i;
|
{
|
||||||
BITVECP sa = GETSIGN(a),
|
int4 i;
|
||||||
sb = GETSIGN(b);
|
BITVECP sa = GETSIGN(a),
|
||||||
|
sb = GETSIGN(b);
|
||||||
|
|
||||||
*result = true;
|
*result = true;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
if (sa[i] != sb[i]) {
|
if (sa[i] != sb[i])
|
||||||
*result = false;
|
{
|
||||||
break;
|
*result = false;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
@ -120,53 +128,57 @@ g_intbig_compress(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||||
|
|
||||||
if (entry->leafkey) {
|
if (entry->leafkey)
|
||||||
|
{
|
||||||
GISTENTRY *retval;
|
GISTENTRY *retval;
|
||||||
ArrayType *in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
|
ArrayType *in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
|
||||||
int4 *ptr;
|
int4 *ptr;
|
||||||
int num;
|
int num;
|
||||||
GISTTYPE *res=(GISTTYPE*)palloc(CALCGTSIZE(0));
|
GISTTYPE *res = (GISTTYPE *) palloc(CALCGTSIZE(0));
|
||||||
|
|
||||||
ARRISVOID(in);
|
ARRISVOID(in);
|
||||||
|
|
||||||
ptr=ARRPTR(in);
|
ptr = ARRPTR(in);
|
||||||
num=ARRNELEMS(in);
|
num = ARRNELEMS(in);
|
||||||
memset(res,0,CALCGTSIZE(0));
|
memset(res, 0, CALCGTSIZE(0));
|
||||||
res->len=CALCGTSIZE(0);
|
res->len = CALCGTSIZE(0);
|
||||||
|
|
||||||
while(num--) {
|
while (num--)
|
||||||
HASH(GETSIGN(res),*ptr);
|
{
|
||||||
|
HASH(GETSIGN(res), *ptr);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
|
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
|
||||||
gistentryinit(*retval, PointerGetDatum(res),
|
gistentryinit(*retval, PointerGetDatum(res),
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, res->len, FALSE);
|
entry->offset, res->len, FALSE);
|
||||||
|
|
||||||
if ( in!=(ArrayType *) PG_DETOAST_DATUM(entry->key) )
|
if (in != (ArrayType *) PG_DETOAST_DATUM(entry->key))
|
||||||
pfree(in);
|
pfree(in);
|
||||||
|
|
||||||
PG_RETURN_POINTER(retval);
|
PG_RETURN_POINTER(retval);
|
||||||
} else if ( !ISALLTRUE(DatumGetPointer(entry->key)) ) {
|
}
|
||||||
|
else if (!ISALLTRUE(DatumGetPointer(entry->key)))
|
||||||
|
{
|
||||||
GISTENTRY *retval;
|
GISTENTRY *retval;
|
||||||
int i;
|
int i;
|
||||||
BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
|
BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
|
||||||
GISTTYPE *res;
|
GISTTYPE *res;
|
||||||
|
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
if ((sign[i] & 0xff) != 0xff)
|
if ((sign[i] & 0xff) != 0xff)
|
||||||
PG_RETURN_POINTER(entry);
|
PG_RETURN_POINTER(entry);
|
||||||
);
|
);
|
||||||
|
|
||||||
res=(GISTTYPE*)palloc(CALCGTSIZE(ALLISTRUE));
|
res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE));
|
||||||
res->len=CALCGTSIZE(ALLISTRUE);
|
res->len = CALCGTSIZE(ALLISTRUE);
|
||||||
res->flag = ALLISTRUE;
|
res->flag = ALLISTRUE;
|
||||||
|
|
||||||
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
|
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
|
||||||
gistentryinit(*retval, PointerGetDatum(res),
|
gistentryinit(*retval, PointerGetDatum(res),
|
||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, res->len, FALSE);
|
entry->offset, res->len, FALSE);
|
||||||
|
|
||||||
PG_RETURN_POINTER(retval);
|
PG_RETURN_POINTER(retval);
|
||||||
}
|
}
|
||||||
@ -176,37 +188,45 @@ g_intbig_compress(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
static int4
|
static int4
|
||||||
sizebitvec(BITVECP sign) {
|
sizebitvec(BITVECP sign)
|
||||||
int4 size = 0, i;
|
{
|
||||||
|
int4 size = 0,
|
||||||
|
i;
|
||||||
|
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
size += SUMBIT(sign);
|
size += SUMBIT(sign);
|
||||||
sign = (BITVECP) (((char *) sign) + 1);
|
sign = (BITVECP) (((char *) sign) + 1);
|
||||||
);
|
);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistsign(BITVECP a, BITVECP b) {
|
hemdistsign(BITVECP a, BITVECP b)
|
||||||
int i,dist=0;
|
{
|
||||||
|
int i,
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
LOOPBIT(
|
LOOPBIT(
|
||||||
if ( GETBIT(a,i) != GETBIT(b,i) )
|
if (GETBIT(a, i) != GETBIT(b, i))
|
||||||
dist++;
|
dist++;
|
||||||
);
|
);
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdist(GISTTYPE *a, GISTTYPE *b) {
|
hemdist(GISTTYPE * a, GISTTYPE * b)
|
||||||
if ( ISALLTRUE(a) ) {
|
{
|
||||||
if (ISALLTRUE(b))
|
if (ISALLTRUE(a))
|
||||||
return 0;
|
{
|
||||||
else
|
if (ISALLTRUE(b))
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(b));
|
return 0;
|
||||||
} else if (ISALLTRUE(b))
|
else
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(a));
|
return SIGLENBIT - sizebitvec(GETSIGN(b));
|
||||||
|
}
|
||||||
|
else if (ISALLTRUE(b))
|
||||||
|
return SIGLENBIT - sizebitvec(GETSIGN(a));
|
||||||
|
|
||||||
return hemdistsign( GETSIGN(a), GETSIGN(b) );
|
return hemdistsign(GETSIGN(a), GETSIGN(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -218,29 +238,33 @@ g_intbig_decompress(PG_FUNCTION_ARGS)
|
|||||||
static int4
|
static int4
|
||||||
unionkey(BITVECP sbase, GISTTYPE * add)
|
unionkey(BITVECP sbase, GISTTYPE * add)
|
||||||
{
|
{
|
||||||
int4 i;
|
int4 i;
|
||||||
BITVECP sadd = GETSIGN(add);
|
BITVECP sadd = GETSIGN(add);
|
||||||
|
|
||||||
if (ISALLTRUE(add))
|
if (ISALLTRUE(add))
|
||||||
return 1;
|
return 1;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
sbase[i] |= sadd[i];
|
sbase[i] |= sadd[i];
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
g_intbig_union(PG_FUNCTION_ARGS) {
|
g_intbig_union(PG_FUNCTION_ARGS)
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
{
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
BITVEC base;
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
int4 i, len;
|
BITVEC base;
|
||||||
int4 flag = 0;
|
int4 i,
|
||||||
|
len;
|
||||||
|
int4 flag = 0;
|
||||||
GISTTYPE *result;
|
GISTTYPE *result;
|
||||||
|
|
||||||
MemSet((void *) base, 0, sizeof(BITVEC));
|
MemSet((void *) base, 0, sizeof(BITVEC));
|
||||||
for (i = 0; i < entryvec->n; i++) {
|
for (i = 0; i < entryvec->n; i++)
|
||||||
if (unionkey(base, GETENTRY(entryvec, i))) {
|
{
|
||||||
|
if (unionkey(base, GETENTRY(entryvec, i)))
|
||||||
|
{
|
||||||
flag = ALLISTRUE;
|
flag = ALLISTRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -257,182 +281,196 @@ g_intbig_union(PG_FUNCTION_ARGS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
g_intbig_penalty(PG_FUNCTION_ARGS) {
|
g_intbig_penalty(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
|
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
|
||||||
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
float *penalty = (float *) PG_GETARG_POINTER(2);
|
float *penalty = (float *) PG_GETARG_POINTER(2);
|
||||||
GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
|
GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
|
||||||
GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
|
GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
|
||||||
|
|
||||||
*penalty=hemdist(origval,newval);
|
*penalty = hemdist(origval, newval);
|
||||||
PG_RETURN_POINTER(penalty);
|
PG_RETURN_POINTER(penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
OffsetNumber pos;
|
OffsetNumber pos;
|
||||||
int4 cost;
|
int4 cost;
|
||||||
} SPLITCOST;
|
} SPLITCOST;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
comparecost(const void *a, const void *b) {
|
comparecost(const void *a, const void *b)
|
||||||
|
{
|
||||||
return ((SPLITCOST *) a)->cost - ((SPLITCOST *) b)->cost;
|
return ((SPLITCOST *) a)->cost - ((SPLITCOST *) b)->cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
g_intbig_picksplit(PG_FUNCTION_ARGS) {
|
g_intbig_picksplit(PG_FUNCTION_ARGS)
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
{
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
OffsetNumber k,
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
j;
|
OffsetNumber k,
|
||||||
GISTTYPE *datum_l,
|
j;
|
||||||
*datum_r;
|
GISTTYPE *datum_l,
|
||||||
BITVECP union_l,
|
*datum_r;
|
||||||
union_r;
|
BITVECP union_l,
|
||||||
int4 size_alpha, size_beta;
|
union_r;
|
||||||
int4 size_waste,
|
int4 size_alpha,
|
||||||
waste = -1;
|
size_beta;
|
||||||
int4 nbytes;
|
int4 size_waste,
|
||||||
OffsetNumber seed_1 = 0,
|
waste = -1;
|
||||||
seed_2 = 0;
|
int4 nbytes;
|
||||||
OffsetNumber *left,
|
OffsetNumber seed_1 = 0,
|
||||||
*right;
|
seed_2 = 0;
|
||||||
OffsetNumber maxoff;
|
OffsetNumber *left,
|
||||||
BITVECP ptr;
|
*right;
|
||||||
int i;
|
OffsetNumber maxoff;
|
||||||
SPLITCOST *costvector;
|
BITVECP ptr;
|
||||||
GISTTYPE *_k,
|
int i;
|
||||||
*_j;
|
SPLITCOST *costvector;
|
||||||
|
GISTTYPE *_k,
|
||||||
|
*_j;
|
||||||
|
|
||||||
maxoff = entryvec->n - 2;
|
maxoff = entryvec->n - 2;
|
||||||
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
|
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
|
||||||
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
||||||
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
||||||
|
|
||||||
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) {
|
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
|
||||||
_k = GETENTRY(entryvec, k);
|
{
|
||||||
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) {
|
_k = GETENTRY(entryvec, k);
|
||||||
size_waste=hemdist(_k, GETENTRY(entryvec, j));
|
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
|
||||||
if (size_waste > waste ) {
|
{
|
||||||
waste = size_waste;
|
size_waste = hemdist(_k, GETENTRY(entryvec, j));
|
||||||
seed_1 = k;
|
if (size_waste > waste)
|
||||||
seed_2 = j;
|
{
|
||||||
}
|
waste = size_waste;
|
||||||
}
|
seed_1 = k;
|
||||||
}
|
seed_2 = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
left = v->spl_left;
|
left = v->spl_left;
|
||||||
v->spl_nleft = 0;
|
v->spl_nleft = 0;
|
||||||
right = v->spl_right;
|
right = v->spl_right;
|
||||||
v->spl_nright = 0;
|
v->spl_nright = 0;
|
||||||
|
|
||||||
if (seed_1 == 0 || seed_2 == 0)
|
if (seed_1 == 0 || seed_2 == 0)
|
||||||
{
|
{
|
||||||
seed_1 = 1;
|
seed_1 = 1;
|
||||||
seed_2 = 2;
|
seed_2 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* form initial .. */
|
/* form initial .. */
|
||||||
if (ISALLTRUE(GETENTRY(entryvec, seed_1)))
|
if (ISALLTRUE(GETENTRY(entryvec, seed_1)))
|
||||||
{
|
{
|
||||||
datum_l = (GISTTYPE *) palloc(GTHDRSIZE);
|
datum_l = (GISTTYPE *) palloc(GTHDRSIZE);
|
||||||
datum_l->len = GTHDRSIZE;
|
datum_l->len = GTHDRSIZE;
|
||||||
datum_l->flag = ALLISTRUE;
|
datum_l->flag = ALLISTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
datum_l = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
|
datum_l = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
|
||||||
datum_l->len = GTHDRSIZE + SIGLEN;
|
datum_l->len = GTHDRSIZE + SIGLEN;
|
||||||
datum_l->flag = 0;
|
datum_l->flag = 0;
|
||||||
memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
if (ISALLTRUE(GETENTRY(entryvec, seed_2)))
|
if (ISALLTRUE(GETENTRY(entryvec, seed_2)))
|
||||||
{
|
{
|
||||||
datum_r = (GISTTYPE *) palloc(GTHDRSIZE);
|
datum_r = (GISTTYPE *) palloc(GTHDRSIZE);
|
||||||
datum_r->len = GTHDRSIZE;
|
datum_r->len = GTHDRSIZE;
|
||||||
datum_r->flag = ALLISTRUE;
|
datum_r->flag = ALLISTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
datum_r = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
|
datum_r = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
|
||||||
datum_r->len = GTHDRSIZE + SIGLEN;
|
datum_r->len = GTHDRSIZE + SIGLEN;
|
||||||
datum_r->flag = 0;
|
datum_r->flag = 0;
|
||||||
memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
|
|
||||||
maxoff = OffsetNumberNext(maxoff);
|
maxoff = OffsetNumberNext(maxoff);
|
||||||
/* sort before ... */
|
/* sort before ... */
|
||||||
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
||||||
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
|
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
|
||||||
{
|
{
|
||||||
costvector[j - 1].pos = j;
|
costvector[j - 1].pos = j;
|
||||||
_j = GETENTRY(entryvec, j);
|
_j = GETENTRY(entryvec, j);
|
||||||
size_alpha = hemdist(datum_l,_j);
|
size_alpha = hemdist(datum_l, _j);
|
||||||
size_beta = hemdist(datum_r,_j);
|
size_beta = hemdist(datum_r, _j);
|
||||||
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
||||||
}
|
}
|
||||||
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
||||||
|
|
||||||
union_l=GETSIGN(datum_l);
|
union_l = GETSIGN(datum_l);
|
||||||
union_r=GETSIGN(datum_r);
|
union_r = GETSIGN(datum_r);
|
||||||
|
|
||||||
for (k = 0; k < maxoff; k++)
|
for (k = 0; k < maxoff; k++)
|
||||||
{
|
{
|
||||||
j = costvector[k].pos;
|
j = costvector[k].pos;
|
||||||
if (j == seed_1)
|
if (j == seed_1)
|
||||||
{
|
{
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (j == seed_2)
|
else if (j == seed_2)
|
||||||
{
|
{
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
v->spl_nright++;
|
v->spl_nright++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_j = GETENTRY(entryvec, j);
|
_j = GETENTRY(entryvec, j);
|
||||||
size_alpha = hemdist(datum_l,_j);
|
size_alpha = hemdist(datum_l, _j);
|
||||||
size_beta = hemdist(datum_r,_j);
|
size_beta = hemdist(datum_r, _j);
|
||||||
|
|
||||||
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
|
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
|
||||||
{
|
{
|
||||||
if (ISALLTRUE(datum_l) || ISALLTRUE(_j) ) {
|
if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
|
||||||
if (!ISALLTRUE(datum_l))
|
{
|
||||||
MemSet((void *) union_l, 0xff, sizeof(BITVEC));
|
if (!ISALLTRUE(datum_l))
|
||||||
} else {
|
MemSet((void *) union_l, 0xff, sizeof(BITVEC));
|
||||||
ptr=GETSIGN(_j);
|
}
|
||||||
LOOPBYTE(
|
else
|
||||||
union_l[i] |= ptr[i];
|
{
|
||||||
);
|
ptr = GETSIGN(_j);
|
||||||
}
|
LOOPBYTE(
|
||||||
*left++ = j;
|
union_l[i] |= ptr[i];
|
||||||
v->spl_nleft++;
|
);
|
||||||
}
|
}
|
||||||
else
|
*left++ = j;
|
||||||
{
|
v->spl_nleft++;
|
||||||
if (ISALLTRUE(datum_r) || ISALLTRUE(_j) ) {
|
}
|
||||||
if (!ISALLTRUE(datum_r))
|
else
|
||||||
MemSet((void *) union_r, 0xff, sizeof(BITVEC));
|
{
|
||||||
} else {
|
if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
|
||||||
ptr=GETSIGN(_j);
|
{
|
||||||
LOOPBYTE(
|
if (!ISALLTRUE(datum_r))
|
||||||
union_r[i] |= ptr[i];
|
MemSet((void *) union_r, 0xff, sizeof(BITVEC));
|
||||||
);
|
}
|
||||||
}
|
else
|
||||||
*right++ = j;
|
{
|
||||||
v->spl_nright++;
|
ptr = GETSIGN(_j);
|
||||||
}
|
LOOPBYTE(
|
||||||
}
|
union_r[i] |= ptr[i];
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*right++ = j;
|
||||||
|
v->spl_nright++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*right = *left = FirstOffsetNumber;
|
*right = *left = FirstOffsetNumber;
|
||||||
pfree(costvector);
|
pfree(costvector);
|
||||||
|
|
||||||
v->spl_ldatum = PointerGetDatum(datum_l);
|
v->spl_ldatum = PointerGetDatum(datum_l);
|
||||||
v->spl_rdatum = PointerGetDatum(datum_r);
|
v->spl_rdatum = PointerGetDatum(datum_r);
|
||||||
|
|
||||||
PG_RETURN_POINTER(v);
|
PG_RETURN_POINTER(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -443,12 +481,13 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
|
|||||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool retval;
|
bool retval;
|
||||||
|
|
||||||
if ( ISALLTRUE(DatumGetPointer(entry->key)) )
|
if (ISALLTRUE(DatumGetPointer(entry->key)))
|
||||||
PG_RETURN_BOOL(true);
|
PG_RETURN_BOOL(true);
|
||||||
|
|
||||||
if (strategy == BooleanSearchStrategy) {
|
if (strategy == BooleanSearchStrategy)
|
||||||
|
{
|
||||||
PG_RETURN_BOOL(signconsistent((QUERYTYPE *) query,
|
PG_RETURN_BOOL(signconsistent((QUERYTYPE *) query,
|
||||||
GETSIGN(DatumGetPointer(entry->key)),
|
GETSIGN(DatumGetPointer(entry->key)),
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,58 +501,72 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
|
|||||||
retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
|
retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
|
||||||
break;
|
break;
|
||||||
case RTSameStrategyNumber:
|
case RTSameStrategyNumber:
|
||||||
if (GIST_LEAF(entry)) {
|
if (GIST_LEAF(entry))
|
||||||
int i,num=ARRNELEMS(query);
|
{
|
||||||
int4 *ptr=ARRPTR(query);
|
int i,
|
||||||
BITVEC qp;
|
num = ARRNELEMS(query);
|
||||||
BITVECP dq, de;
|
int4 *ptr = ARRPTR(query);
|
||||||
memset(qp,0,sizeof(BITVEC));
|
BITVEC qp;
|
||||||
|
BITVECP dq,
|
||||||
|
de;
|
||||||
|
|
||||||
while(num--) {
|
memset(qp, 0, sizeof(BITVEC));
|
||||||
|
|
||||||
|
while (num--)
|
||||||
|
{
|
||||||
HASH(qp, *ptr);
|
HASH(qp, *ptr);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
de=GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
|
de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
|
||||||
dq=qp;
|
dq = qp;
|
||||||
retval=true;
|
retval = true;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
if ( de[i] != dq[i] ) {
|
if (de[i] != dq[i])
|
||||||
retval=false;
|
{
|
||||||
break;
|
retval = false;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
|
retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
|
||||||
break;
|
break;
|
||||||
case RTContainsStrategyNumber:
|
case RTContainsStrategyNumber:
|
||||||
retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
|
retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
|
||||||
break;
|
break;
|
||||||
case RTContainedByStrategyNumber:
|
case RTContainedByStrategyNumber:
|
||||||
if (GIST_LEAF(entry)) {
|
if (GIST_LEAF(entry))
|
||||||
int i,num=ARRNELEMS(query);
|
{
|
||||||
int4 *ptr=ARRPTR(query);
|
int i,
|
||||||
BITVEC qp;
|
num = ARRNELEMS(query);
|
||||||
BITVECP dq, de;
|
int4 *ptr = ARRPTR(query);
|
||||||
memset(qp,0,sizeof(BITVEC));
|
BITVEC qp;
|
||||||
|
BITVECP dq,
|
||||||
|
de;
|
||||||
|
|
||||||
while(num--) {
|
memset(qp, 0, sizeof(BITVEC));
|
||||||
|
|
||||||
|
while (num--)
|
||||||
|
{
|
||||||
HASH(qp, *ptr);
|
HASH(qp, *ptr);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
de=GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
|
de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
|
||||||
dq=qp;
|
dq = qp;
|
||||||
retval=true;
|
retval = true;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
if ( de[i] & ~dq[i] ) {
|
if (de[i] & ~dq[i])
|
||||||
retval=false;
|
{
|
||||||
break;
|
retval = false;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
|
retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -521,5 +574,3 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
PG_RETURN_BOOL(retval);
|
PG_RETURN_BOOL(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ _ltree_compress(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (ARR_NDIM(val) != 1)
|
if (ARR_NDIM(val) != 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("array must be one-dimensional")));
|
errmsg("array must be one-dimensional")));
|
||||||
|
|
||||||
key = (ltree_gist *) palloc(len);
|
key = (ltree_gist *) palloc(len);
|
||||||
key->len = len;
|
key->len = len;
|
||||||
@ -98,7 +98,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
|
|||||||
entry->rel, entry->page,
|
entry->rel, entry->page,
|
||||||
entry->offset, key->len, FALSE);
|
entry->offset, key->len, FALSE);
|
||||||
}
|
}
|
||||||
else if ( !LTG_ISALLTRUE(entry->key) )
|
else if (!LTG_ISALLTRUE(entry->key))
|
||||||
{
|
{
|
||||||
int4 i,
|
int4 i,
|
||||||
len;
|
len;
|
||||||
@ -107,7 +107,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
|
|||||||
BITVECP sign = LTG_SIGN(DatumGetPointer(entry->key));
|
BITVECP sign = LTG_SIGN(DatumGetPointer(entry->key));
|
||||||
|
|
||||||
ALOOPBYTE(
|
ALOOPBYTE(
|
||||||
if ((sign[i]&0xff) != 0xff)
|
if ((sign[i] & 0xff) != 0xff)
|
||||||
PG_RETURN_POINTER(retval);
|
PG_RETURN_POINTER(retval);
|
||||||
);
|
);
|
||||||
len = LTG_HDRSIZE;
|
len = LTG_HDRSIZE;
|
||||||
@ -172,10 +172,11 @@ unionkey(BITVECP sbase, ltree_gist * add)
|
|||||||
Datum
|
Datum
|
||||||
_ltree_union(PG_FUNCTION_ARGS)
|
_ltree_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
ABITVEC base;
|
ABITVEC base;
|
||||||
int4 i,len;
|
int4 i,
|
||||||
|
len;
|
||||||
int4 flag = 0;
|
int4 flag = 0;
|
||||||
ltree_gist *result;
|
ltree_gist *result;
|
||||||
|
|
||||||
@ -213,27 +214,32 @@ sizebitvec(BITVECP sign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistsign(BITVECP a, BITVECP b) {
|
hemdistsign(BITVECP a, BITVECP b)
|
||||||
int i,dist=0;
|
{
|
||||||
|
int i,
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
ALOOPBIT(
|
ALOOPBIT(
|
||||||
if ( GETBIT(a,i) != GETBIT(b,i) )
|
if (GETBIT(a, i) != GETBIT(b, i))
|
||||||
dist++;
|
dist++;
|
||||||
);
|
);
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdist(ltree_gist *a, ltree_gist *b) {
|
hemdist(ltree_gist * a, ltree_gist * b)
|
||||||
if ( LTG_ISALLTRUE(a) ) {
|
{
|
||||||
if (LTG_ISALLTRUE(b))
|
if (LTG_ISALLTRUE(a))
|
||||||
return 0;
|
{
|
||||||
else
|
if (LTG_ISALLTRUE(b))
|
||||||
return ASIGLENBIT-sizebitvec(LTG_SIGN(b));
|
return 0;
|
||||||
} else if (LTG_ISALLTRUE(b))
|
else
|
||||||
return ASIGLENBIT-sizebitvec(LTG_SIGN(a));
|
return ASIGLENBIT - sizebitvec(LTG_SIGN(b));
|
||||||
|
}
|
||||||
|
else if (LTG_ISALLTRUE(b))
|
||||||
|
return ASIGLENBIT - sizebitvec(LTG_SIGN(a));
|
||||||
|
|
||||||
return hemdistsign( LTG_SIGN(a), LTG_SIGN(b) );
|
return hemdistsign(LTG_SIGN(a), LTG_SIGN(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -244,7 +250,7 @@ _ltree_penalty(PG_FUNCTION_ARGS)
|
|||||||
ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
|
||||||
float *penalty = (float *) PG_GETARG_POINTER(2);
|
float *penalty = (float *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
*penalty=hemdist(origval,newval);
|
*penalty = hemdist(origval, newval);
|
||||||
PG_RETURN_POINTER(penalty);
|
PG_RETURN_POINTER(penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +269,7 @@ comparecost(const void *a, const void *b)
|
|||||||
Datum
|
Datum
|
||||||
_ltree_picksplit(PG_FUNCTION_ARGS)
|
_ltree_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber k,
|
OffsetNumber k,
|
||||||
j;
|
j;
|
||||||
@ -271,7 +277,8 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
|
|||||||
*datum_r;
|
*datum_r;
|
||||||
BITVECP union_l,
|
BITVECP union_l,
|
||||||
union_r;
|
union_r;
|
||||||
int4 size_alpha, size_beta;
|
int4 size_alpha,
|
||||||
|
size_beta;
|
||||||
int4 size_waste,
|
int4 size_waste,
|
||||||
waste = -1;
|
waste = -1;
|
||||||
int4 nbytes;
|
int4 nbytes;
|
||||||
@ -291,11 +298,14 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
|
|||||||
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
||||||
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
||||||
|
|
||||||
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) {
|
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
|
||||||
|
{
|
||||||
_k = GETENTRY(entryvec, k);
|
_k = GETENTRY(entryvec, k);
|
||||||
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) {
|
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
|
||||||
size_waste=hemdist(_k, GETENTRY(entryvec, j));
|
{
|
||||||
if (size_waste > waste ) {
|
size_waste = hemdist(_k, GETENTRY(entryvec, j));
|
||||||
|
if (size_waste > waste)
|
||||||
|
{
|
||||||
waste = size_waste;
|
waste = size_waste;
|
||||||
seed_1 = k;
|
seed_1 = k;
|
||||||
seed_2 = j;
|
seed_2 = j;
|
||||||
@ -349,14 +359,14 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
costvector[j - 1].pos = j;
|
costvector[j - 1].pos = j;
|
||||||
_j = GETENTRY(entryvec, j);
|
_j = GETENTRY(entryvec, j);
|
||||||
size_alpha = hemdist(datum_l,_j);
|
size_alpha = hemdist(datum_l, _j);
|
||||||
size_beta = hemdist(datum_r,_j);
|
size_beta = hemdist(datum_r, _j);
|
||||||
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
||||||
}
|
}
|
||||||
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
||||||
|
|
||||||
union_l=LTG_SIGN(datum_l);
|
union_l = LTG_SIGN(datum_l);
|
||||||
union_r=LTG_SIGN(datum_r);
|
union_r = LTG_SIGN(datum_r);
|
||||||
|
|
||||||
for (k = 0; k < maxoff; k++)
|
for (k = 0; k < maxoff; k++)
|
||||||
{
|
{
|
||||||
@ -374,18 +384,21 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_j = GETENTRY(entryvec, j);
|
_j = GETENTRY(entryvec, j);
|
||||||
size_alpha = hemdist(datum_l,_j);
|
size_alpha = hemdist(datum_l, _j);
|
||||||
size_beta = hemdist(datum_r,_j);
|
size_beta = hemdist(datum_r, _j);
|
||||||
|
|
||||||
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
|
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
|
||||||
{
|
{
|
||||||
if (LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j) ) {
|
if (LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j))
|
||||||
|
{
|
||||||
if (!LTG_ISALLTRUE(datum_l))
|
if (!LTG_ISALLTRUE(datum_l))
|
||||||
MemSet((void *) union_l, 0xff, sizeof(ABITVEC));
|
MemSet((void *) union_l, 0xff, sizeof(ABITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=LTG_SIGN(_j);
|
else
|
||||||
|
{
|
||||||
|
ptr = LTG_SIGN(_j);
|
||||||
ALOOPBYTE(
|
ALOOPBYTE(
|
||||||
union_l[i] |= ptr[i];
|
union_l[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
@ -393,13 +406,16 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j) ) {
|
if (LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j))
|
||||||
|
{
|
||||||
if (!LTG_ISALLTRUE(datum_r))
|
if (!LTG_ISALLTRUE(datum_r))
|
||||||
MemSet((void *) union_r, 0xff, sizeof(ABITVEC));
|
MemSet((void *) union_r, 0xff, sizeof(ABITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=LTG_SIGN(_j);
|
else
|
||||||
|
{
|
||||||
|
ptr = LTG_SIGN(_j);
|
||||||
ALOOPBYTE(
|
ALOOPBYTE(
|
||||||
union_r[i] |= ptr[i];
|
union_r[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
@ -498,22 +514,24 @@ gist_qe(ltree_gist * key, lquery * query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_arrq_cons(ltree_gist *key, ArrayType *_query) {
|
_arrq_cons(ltree_gist * key, ArrayType *_query)
|
||||||
lquery *query = (lquery *) ARR_DATA_PTR(_query);
|
{
|
||||||
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
|
lquery *query = (lquery *) ARR_DATA_PTR(_query);
|
||||||
|
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
|
||||||
|
|
||||||
if (ARR_NDIM(_query) != 1)
|
if (ARR_NDIM(_query) != 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("array must be one-dimensional")));
|
errmsg("array must be one-dimensional")));
|
||||||
|
|
||||||
while (num > 0) {
|
while (num > 0)
|
||||||
if ( gist_qe(key, query) )
|
{
|
||||||
return true;
|
if (gist_qe(key, query))
|
||||||
num--;
|
return true;
|
||||||
query = (lquery*)NEXTVAL(query);
|
num--;
|
||||||
}
|
query = (lquery *) NEXTVAL(query);
|
||||||
return false;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
|
@ -166,7 +166,7 @@ hashing(BITVECP sign, ltree * t)
|
|||||||
Datum
|
Datum
|
||||||
ltree_union(PG_FUNCTION_ARGS)
|
ltree_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
BITVEC base;
|
BITVEC base;
|
||||||
int4 i,
|
int4 i,
|
||||||
@ -277,14 +277,14 @@ treekey_cmp(const void *a, const void *b)
|
|||||||
return ltree_compare(
|
return ltree_compare(
|
||||||
((RIX *) a)->r,
|
((RIX *) a)->r,
|
||||||
((RIX *) b)->r
|
((RIX *) b)->r
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
ltree_picksplit(PG_FUNCTION_ARGS)
|
ltree_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber j;
|
OffsetNumber j;
|
||||||
int4 i;
|
int4 i;
|
||||||
@ -602,21 +602,23 @@ gist_qtxt(ltree_gist * key, ltxtquery * query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
arrq_cons(ltree_gist *key, ArrayType *_query) {
|
arrq_cons(ltree_gist * key, ArrayType *_query)
|
||||||
lquery *query = (lquery *) ARR_DATA_PTR(_query);
|
{
|
||||||
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
|
lquery *query = (lquery *) ARR_DATA_PTR(_query);
|
||||||
|
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
|
||||||
|
|
||||||
if (ARR_NDIM(_query) != 1)
|
if (ARR_NDIM(_query) != 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||||
errmsg("array must be one-dimensional")));
|
errmsg("array must be one-dimensional")));
|
||||||
|
|
||||||
while (num > 0) {
|
while (num > 0)
|
||||||
if ( gist_qe(key, query) && gist_between(key, query) )
|
{
|
||||||
return true;
|
if (gist_qe(key, query) && gist_between(key, query))
|
||||||
num--;
|
return true;
|
||||||
query = NEXTVAL(query);
|
num--;
|
||||||
}
|
query = NEXTVAL(query);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +702,7 @@ ltree_consistent(PG_FUNCTION_ARGS)
|
|||||||
if (GIST_LEAF(entry))
|
if (GIST_LEAF(entry))
|
||||||
res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
|
res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
|
||||||
PointerGetDatum(LTG_NODE(key)),
|
PointerGetDatum(LTG_NODE(key)),
|
||||||
PointerGetDatum((ArrayType *) query)
|
PointerGetDatum((ArrayType *) query)
|
||||||
));
|
));
|
||||||
else
|
else
|
||||||
res = arrq_cons(key, (ArrayType *) query);
|
res = arrq_cons(key, (ArrayType *) query);
|
||||||
|
@ -230,18 +230,18 @@ update_table_list(db_info * dbi)
|
|||||||
t = PQntuples(res);
|
t = PQntuples(res);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First: use the tbl_list as the outer loop and the result set as
|
* First: use the tbl_list as the outer loop and the result
|
||||||
* the inner loop, this will determine what tables should be
|
* set as the inner loop, this will determine what tables
|
||||||
* removed
|
* should be removed
|
||||||
*/
|
*/
|
||||||
while (tbl_elem != NULL)
|
while (tbl_elem != NULL)
|
||||||
{
|
{
|
||||||
tbl = ((tbl_info *) DLE_VAL(tbl_elem));
|
tbl = ((tbl_info *) DLE_VAL(tbl_elem));
|
||||||
found_match = 0;
|
found_match = 0;
|
||||||
|
|
||||||
for (i = 0; i < t; i++)
|
for (i = 0; i < t; i++)
|
||||||
{ /* loop through result set looking for a
|
{ /* loop through result set looking for a
|
||||||
* match */
|
* match */
|
||||||
if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
|
if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
|
||||||
{
|
{
|
||||||
found_match = 1;
|
found_match = 1;
|
||||||
@ -249,8 +249,8 @@ update_table_list(db_info * dbi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found_match == 0)
|
if (found_match == 0)
|
||||||
{ /* then we didn't find this tbl_elem in
|
{ /* then we didn't find this tbl_elem in
|
||||||
* the result set */
|
* the result set */
|
||||||
Dlelem *elem_to_remove = tbl_elem;
|
Dlelem *elem_to_remove = tbl_elem;
|
||||||
|
|
||||||
tbl_elem = DLGetSucc(tbl_elem);
|
tbl_elem = DLGetSucc(tbl_elem);
|
||||||
@ -258,13 +258,13 @@ update_table_list(db_info * dbi)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
tbl_elem = DLGetSucc(tbl_elem);
|
tbl_elem = DLGetSucc(tbl_elem);
|
||||||
} /* Done removing dropped tables from the
|
} /* Done removing dropped tables from the
|
||||||
* table_list */
|
* table_list */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Then loop use result set as outer loop and tbl_list as the
|
* Then loop use result set as outer loop and tbl_list as the
|
||||||
* inner loop to determine what tables are new
|
* inner loop to determine what tables are new
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < t; i++)
|
for (i = 0; i < t; i++)
|
||||||
{
|
{
|
||||||
tbl_elem = DLGetHead(dbi->table_list);
|
tbl_elem = DLGetHead(dbi->table_list);
|
||||||
@ -279,8 +279,8 @@ update_table_list(db_info * dbi)
|
|||||||
}
|
}
|
||||||
tbl_elem = DLGetSucc(tbl_elem);
|
tbl_elem = DLGetSucc(tbl_elem);
|
||||||
}
|
}
|
||||||
if (found_match == 0) /* then we didn't find this result
|
if (found_match == 0) /* then we didn't find this result
|
||||||
* now in the tbl_list */
|
* now in the tbl_list */
|
||||||
{
|
{
|
||||||
DLAddTail(dbi->table_list, DLNewElem(init_table_info(res, i, dbi)));
|
DLAddTail(dbi->table_list, DLNewElem(init_table_info(res, i, dbi)));
|
||||||
if (args->debug >= 1)
|
if (args->debug >= 1)
|
||||||
@ -290,7 +290,7 @@ update_table_list(db_info * dbi)
|
|||||||
log_entry(logbuffer);
|
log_entry(logbuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* end of for loop that adds tables */
|
} /* end of for loop that adds tables */
|
||||||
}
|
}
|
||||||
fflush(LOGOUTPUT);
|
fflush(LOGOUTPUT);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -501,33 +501,33 @@ update_db_list(Dllist *db_list)
|
|||||||
t = PQntuples(res);
|
t = PQntuples(res);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First: use the db_list as the outer loop and the result set as
|
* First: use the db_list as the outer loop and the result set
|
||||||
* the inner loop, this will determine what databases should be
|
* as the inner loop, this will determine what databases
|
||||||
* removed
|
* should be removed
|
||||||
*/
|
*/
|
||||||
while (db_elem != NULL)
|
while (db_elem != NULL)
|
||||||
{
|
{
|
||||||
dbi = ((db_info *) DLE_VAL(db_elem));
|
dbi = ((db_info *) DLE_VAL(db_elem));
|
||||||
found_match = 0;
|
found_match = 0;
|
||||||
|
|
||||||
for (i = 0; i < t; i++)
|
for (i = 0; i < t; i++)
|
||||||
{ /* loop through result set looking for a
|
{ /* loop through result set looking for a
|
||||||
* match */
|
* match */
|
||||||
if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
|
if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
|
||||||
{
|
{
|
||||||
found_match = 1;
|
found_match = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update the dbi->age so that we ensure
|
* update the dbi->age so that we ensure
|
||||||
* xid_wraparound won't happen
|
* xid_wraparound won't happen
|
||||||
*/
|
*/
|
||||||
dbi->age = atol(PQgetvalue(res, i, PQfnumber(res, "age")));
|
dbi->age = atol(PQgetvalue(res, i, PQfnumber(res, "age")));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found_match == 0)
|
if (found_match == 0)
|
||||||
{ /* then we didn't find this db_elem in the
|
{ /* then we didn't find this db_elem in the
|
||||||
* result set */
|
* result set */
|
||||||
Dlelem *elem_to_remove = db_elem;
|
Dlelem *elem_to_remove = db_elem;
|
||||||
|
|
||||||
db_elem = DLGetSucc(db_elem);
|
db_elem = DLGetSucc(db_elem);
|
||||||
@ -535,13 +535,13 @@ update_db_list(Dllist *db_list)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
db_elem = DLGetSucc(db_elem);
|
db_elem = DLGetSucc(db_elem);
|
||||||
} /* Done removing dropped databases from
|
} /* Done removing dropped databases from
|
||||||
* the table_list */
|
* the table_list */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Then loop use result set as outer loop and db_list as the inner
|
* Then loop use result set as outer loop and db_list as the
|
||||||
* loop to determine what databases are new
|
* inner loop to determine what databases are new
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < t; i++)
|
for (i = 0; i < t; i++)
|
||||||
{
|
{
|
||||||
db_elem = DLGetHead(db_list);
|
db_elem = DLGetHead(db_list);
|
||||||
@ -556,20 +556,20 @@ update_db_list(Dllist *db_list)
|
|||||||
}
|
}
|
||||||
db_elem = DLGetSucc(db_elem);
|
db_elem = DLGetSucc(db_elem);
|
||||||
}
|
}
|
||||||
if (found_match == 0) /* then we didn't find this result
|
if (found_match == 0) /* then we didn't find this result
|
||||||
* now in the tbl_list */
|
* now in the tbl_list */
|
||||||
{
|
{
|
||||||
DLAddTail(db_list, DLNewElem(init_dbinfo
|
DLAddTail(db_list, DLNewElem(init_dbinfo
|
||||||
(PQgetvalue(res, i, PQfnumber(res, "datname")),
|
(PQgetvalue(res, i, PQfnumber(res, "datname")),
|
||||||
atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))),
|
atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))),
|
||||||
atol(PQgetvalue(res, i, PQfnumber(res, "age"))))));
|
atol(PQgetvalue(res, i, PQfnumber(res, "age"))))));
|
||||||
if (args->debug >= 1)
|
if (args->debug >= 1)
|
||||||
{
|
{
|
||||||
sprintf(logbuffer, "added database: %s", ((db_info *) DLE_VAL(DLGetTail(db_list)))->dbname);
|
sprintf(logbuffer, "added database: %s", ((db_info *) DLE_VAL(DLGetTail(db_list)))->dbname);
|
||||||
log_entry(logbuffer);
|
log_entry(logbuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* end of for loop that adds tables */
|
} /* end of for loop that adds tables */
|
||||||
}
|
}
|
||||||
fflush(LOGOUTPUT);
|
fflush(LOGOUTPUT);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -604,16 +604,14 @@ xid_wraparound_check(db_info * dbi)
|
|||||||
* 500million xacts to work with so we should be able to spread the
|
* 500million xacts to work with so we should be able to spread the
|
||||||
* load of full database vacuums a bit
|
* load of full database vacuums a bit
|
||||||
*/
|
*/
|
||||||
if (dbi->age > 1500000000 )
|
if (dbi->age > 1500000000)
|
||||||
{
|
{
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
|
|
||||||
res = send_query("VACUUM", dbi);
|
res = send_query("VACUUM", dbi);
|
||||||
/* FIXME: Perhaps should add a check for PQ_COMMAND_OK */
|
/* FIXME: Perhaps should add a check for PQ_COMMAND_OK */
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
{
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1096,38 +1094,40 @@ main(int argc, char *argv[])
|
|||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
{
|
{
|
||||||
for (j = 0; j < PQntuples(res); j++)
|
for (j = 0; j < PQntuples(res); j++)
|
||||||
{ /* loop through result set */
|
{ /* loop through result set */
|
||||||
tbl_elem = DLGetHead(dbs->table_list); /* Reset tbl_elem to top
|
tbl_elem = DLGetHead(dbs->table_list); /* Reset tbl_elem to top
|
||||||
* of dbs->table_list */
|
* of dbs->table_list */
|
||||||
while (tbl_elem != NULL)
|
while (tbl_elem != NULL)
|
||||||
{ /* Loop through tables in list */
|
{ /* Loop through tables in list */
|
||||||
tbl = ((tbl_info *) DLE_VAL(tbl_elem)); /* set tbl_info =
|
tbl = ((tbl_info *) DLE_VAL(tbl_elem)); /* set tbl_info =
|
||||||
* current_table */
|
* current_table */
|
||||||
if (tbl->relid == atooid(PQgetvalue(res, j, PQfnumber(res, "oid"))))
|
if (tbl->relid == atooid(PQgetvalue(res, j, PQfnumber(res, "oid"))))
|
||||||
{
|
{
|
||||||
tbl->curr_analyze_count =
|
tbl->curr_analyze_count =
|
||||||
(atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_ins"))) +
|
(atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_ins"))) +
|
||||||
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))) +
|
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))) +
|
||||||
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))));
|
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))));
|
||||||
tbl->curr_vacuum_count =
|
tbl->curr_vacuum_count =
|
||||||
(atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))) +
|
(atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))) +
|
||||||
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))));
|
atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check numDeletes to see if we need to
|
* Check numDeletes to see if we need
|
||||||
* vacuum, if so: Run vacuum analyze
|
* to vacuum, if so: Run vacuum
|
||||||
* (adding analyze is small so we might as
|
* analyze (adding analyze is small so
|
||||||
* well) Update table thresholds and
|
* we might as well) Update table
|
||||||
* related information if numDeletes is
|
* thresholds and related information
|
||||||
* not big enough for vacuum then check
|
* if numDeletes is not big enough for
|
||||||
* numInserts for analyze
|
* vacuum then check numInserts for
|
||||||
*/
|
* analyze
|
||||||
|
*/
|
||||||
if (tbl->curr_vacuum_count - tbl->CountAtLastVacuum >= tbl->vacuum_threshold)
|
if (tbl->curr_vacuum_count - tbl->CountAtLastVacuum >= tbl->vacuum_threshold)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* if relisshared = t and database !=
|
* if relisshared = t and database
|
||||||
* template1 then only do an analyze
|
* != template1 then only do an
|
||||||
*/
|
* analyze
|
||||||
|
*/
|
||||||
if (tbl->relisshared > 0 && strcmp("template1", dbs->dbname))
|
if (tbl->relisshared > 0 && strcmp("template1", dbs->dbname))
|
||||||
snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
|
snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
|
||||||
else
|
else
|
||||||
@ -1158,18 +1158,19 @@ main(int argc, char *argv[])
|
|||||||
print_table_info(tbl);
|
print_table_info(tbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
break; /* once we have found a match, no
|
break; /* once we have found a
|
||||||
* need to keep checking. */
|
* match, no need to keep
|
||||||
|
* checking. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Advance the table pointers for the next
|
* Advance the table pointers for the next
|
||||||
* loop
|
* loop
|
||||||
*/
|
*/
|
||||||
tbl_elem = DLGetSucc(tbl_elem);
|
tbl_elem = DLGetSucc(tbl_elem);
|
||||||
|
|
||||||
} /* end for table while loop */
|
} /* end for table while loop */
|
||||||
} /* end for j loop (tuples in PGresult) */
|
} /* end for j loop (tuples in PGresult) */
|
||||||
} /* end if (res != NULL) */
|
} /* end if (res != NULL) */
|
||||||
} /* close of if(xid_wraparound_check()) */
|
} /* close of if(xid_wraparound_check()) */
|
||||||
/* Done working on this db, Clean up, then advance cur_db */
|
/* Done working on this db, Clean up, then advance cur_db */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* -------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------
|
||||||
* pg_dumplo
|
* pg_dumplo
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/contrib/pg_dumplo/utils.c,v 1.8 2003/11/29 19:51:35 pgsql Exp $
|
* $PostgreSQL: pgsql/contrib/pg_dumplo/utils.c,v 1.9 2004/08/29 05:06:36 momjian Exp $
|
||||||
*
|
*
|
||||||
* Karel Zak 1999-2000
|
* Karel Zak 1999-2000
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
@ -30,7 +30,7 @@ void
|
|||||||
index_file(LODumpMaster * pgLO)
|
index_file(LODumpMaster * pgLO)
|
||||||
{
|
{
|
||||||
char path[BUFSIZ];
|
char path[BUFSIZ];
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
if (pgLO->action == ACTION_SHOW)
|
if (pgLO->action == ACTION_SHOW)
|
||||||
return;
|
return;
|
||||||
@ -51,7 +51,7 @@ index_file(LODumpMaster * pgLO)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sz = strlen(path);
|
sz = strlen(path);
|
||||||
strncat(path, "/lo_dump.index", BUFSIZ-sz);
|
strncat(path, "/lo_dump.index", BUFSIZ - sz);
|
||||||
|
|
||||||
if ((pgLO->index = fopen(path, "w")) == NULL)
|
if ((pgLO->index = fopen(path, "w")) == NULL)
|
||||||
{
|
{
|
||||||
@ -63,7 +63,7 @@ index_file(LODumpMaster * pgLO)
|
|||||||
else if (pgLO->action != ACTION_NONE)
|
else if (pgLO->action != ACTION_NONE)
|
||||||
{
|
{
|
||||||
sz = strlen(path);
|
sz = strlen(path);
|
||||||
strncat(path, "/lo_dump.index", BUFSIZ-sz);
|
strncat(path, "/lo_dump.index", BUFSIZ - sz);
|
||||||
|
|
||||||
if ((pgLO->index = fopen(path, "r")) == NULL)
|
if ((pgLO->index = fopen(path, "r")) == NULL)
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
#include "storage/bufpage.h"
|
#include "storage/bufpage.h"
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
#define LPADDING 2
|
#define LPADDING 2
|
||||||
#define RPADDING 1
|
#define RPADDING 1
|
||||||
#define KEEPONLYALNUM
|
#define KEEPONLYALNUM
|
||||||
#define IGNORECASE
|
#define IGNORECASE
|
||||||
#define DIVUNION
|
#define DIVUNION
|
||||||
@ -24,40 +24,41 @@ typedef char trgm[3];
|
|||||||
#define CMPPCHAR(a,b,i) CMPCHAR( *(((char*)(a))+i), *(((char*)(b))+i) )
|
#define CMPPCHAR(a,b,i) CMPCHAR( *(((char*)(a))+i), *(((char*)(b))+i) )
|
||||||
#define CMPTRGM(a,b) ( CMPPCHAR(a,b,0) ? CMPPCHAR(a,b,0) : ( CMPPCHAR(a,b,1) ? CMPPCHAR(a,b,1) : CMPPCHAR(a,b,2) ) )
|
#define CMPTRGM(a,b) ( CMPPCHAR(a,b,0) ? CMPPCHAR(a,b,0) : ( CMPPCHAR(a,b,1) ? CMPPCHAR(a,b,1) : CMPPCHAR(a,b,2) ) )
|
||||||
|
|
||||||
#define CPTRGM(a,b) do { \
|
#define CPTRGM(a,b) do { \
|
||||||
*(((char*)(a))+0) = *(((char*)(b))+0); \
|
*(((char*)(a))+0) = *(((char*)(b))+0); \
|
||||||
*(((char*)(a))+1) = *(((char*)(b))+1); \
|
*(((char*)(a))+1) = *(((char*)(b))+1); \
|
||||||
*(((char*)(a))+2) = *(((char*)(b))+2); \
|
*(((char*)(a))+2) = *(((char*)(b))+2); \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
int4 len;
|
{
|
||||||
uint8 flag;
|
int4 len;
|
||||||
char data[1];
|
uint8 flag;
|
||||||
} TRGM;
|
char data[1];
|
||||||
|
} TRGM;
|
||||||
|
|
||||||
#define TRGMHRDSIZE (sizeof(int4)+sizeof(uint8))
|
#define TRGMHRDSIZE (sizeof(int4)+sizeof(uint8))
|
||||||
|
|
||||||
/* gist */
|
/* gist */
|
||||||
#define BITBYTE 8
|
#define BITBYTE 8
|
||||||
#define SIGLENINT 3 /* >122 => key will toast, so very slow!!! */
|
#define SIGLENINT 3 /* >122 => key will toast, so very slow!!! */
|
||||||
#define SIGLEN ( sizeof(int)*SIGLENINT )
|
#define SIGLEN ( sizeof(int)*SIGLENINT )
|
||||||
|
|
||||||
#define SIGLENBIT (SIGLEN*BITBYTE - 1) /* see makesign */
|
#define SIGLENBIT (SIGLEN*BITBYTE - 1) /* see makesign */
|
||||||
|
|
||||||
typedef char BITVEC[SIGLEN];
|
typedef char BITVEC[SIGLEN];
|
||||||
typedef char *BITVECP;
|
typedef char *BITVECP;
|
||||||
|
|
||||||
#define LOOPBYTE(a) \
|
#define LOOPBYTE(a) \
|
||||||
for(i=0;i<SIGLEN;i++) {\
|
for(i=0;i<SIGLEN;i++) {\
|
||||||
a;\
|
a;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOOPBIT(a) \
|
#define LOOPBIT(a) \
|
||||||
for(i=0;i<SIGLENBIT;i++) {\
|
for(i=0;i<SIGLENBIT;i++) {\
|
||||||
a;\
|
a;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
|
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
|
||||||
#define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 )
|
#define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 )
|
||||||
@ -68,21 +69,21 @@ typedef char *BITVECP;
|
|||||||
#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
|
#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
|
||||||
#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
|
#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
|
||||||
|
|
||||||
#define ARRKEY 0x01
|
#define ARRKEY 0x01
|
||||||
#define SIGNKEY 0x02
|
#define SIGNKEY 0x02
|
||||||
#define ALLISTRUE 0x04
|
#define ALLISTRUE 0x04
|
||||||
|
|
||||||
#define ISARRKEY(x) ( ((TRGM*)x)->flag & ARRKEY )
|
#define ISARRKEY(x) ( ((TRGM*)x)->flag & ARRKEY )
|
||||||
#define ISSIGNKEY(x) ( ((TRGM*)x)->flag & SIGNKEY )
|
#define ISSIGNKEY(x) ( ((TRGM*)x)->flag & SIGNKEY )
|
||||||
#define ISALLTRUE(x) ( ((TRGM*)x)->flag & ALLISTRUE )
|
#define ISALLTRUE(x) ( ((TRGM*)x)->flag & ALLISTRUE )
|
||||||
|
|
||||||
#define CALCGTSIZE(flag, len) ( TRGMHRDSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(trgm)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) )
|
#define CALCGTSIZE(flag, len) ( TRGMHRDSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(trgm)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) )
|
||||||
#define GETSIGN(x) ( (BITVECP)( (char*)x+TRGMHRDSIZE ) )
|
#define GETSIGN(x) ( (BITVECP)( (char*)x+TRGMHRDSIZE ) )
|
||||||
#define GETARR(x) ( (trgm*)( (char*)x+TRGMHRDSIZE ) )
|
#define GETARR(x) ( (trgm*)( (char*)x+TRGMHRDSIZE ) )
|
||||||
#define ARRNELEM(x) ( ( ((TRGM*)x)->len - TRGMHRDSIZE )/sizeof(trgm) )
|
#define ARRNELEM(x) ( ( ((TRGM*)x)->len - TRGMHRDSIZE )/sizeof(trgm) )
|
||||||
|
|
||||||
extern float4 trgm_limit;
|
extern float4 trgm_limit;
|
||||||
TRGM* generate_trgm(char *str, int slen);
|
TRGM *generate_trgm(char *str, int slen);
|
||||||
float4 cnt_sml(TRGM *trg1, TRGM *trg2);
|
float4 cnt_sml(TRGM * trg1, TRGM * trg2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,12 +71,13 @@ makesign(BITVECP sign, TRGM * a)
|
|||||||
int4 k,
|
int4 k,
|
||||||
len = ARRNELEM(a);
|
len = ARRNELEM(a);
|
||||||
trgm *ptr = GETARR(a);
|
trgm *ptr = GETARR(a);
|
||||||
int4 tmp=0;
|
int4 tmp = 0;
|
||||||
|
|
||||||
MemSet((void *) sign, 0, sizeof(BITVEC));
|
MemSet((void *) sign, 0, sizeof(BITVEC));
|
||||||
SETBIT(sign, SIGLENBIT); /*set last unused bit*/
|
SETBIT(sign, SIGLENBIT); /* set last unused bit */
|
||||||
for (k = 0; k < len; k++) {
|
for (k = 0; k < len; k++)
|
||||||
CPTRGM( ((char*)&tmp), ptr+k );
|
{
|
||||||
|
CPTRGM(((char *) &tmp), ptr + k);
|
||||||
HASH(sign, tmp);
|
HASH(sign, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +90,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{ /* trgm */
|
{ /* trgm */
|
||||||
TRGM *res;
|
TRGM *res;
|
||||||
text *toastedval = (text *) DatumGetPointer(entry->key);
|
text *toastedval = (text *) DatumGetPointer(entry->key);
|
||||||
text *val = (text *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
text *val = (text *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ gtrgm_compress(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
int4 i,
|
int4 i,
|
||||||
len;
|
len;
|
||||||
TRGM *res;
|
TRGM *res;
|
||||||
BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
|
BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
|
||||||
|
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
@ -137,36 +138,44 @@ gtrgm_decompress(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gtrgm_consistent(PG_FUNCTION_ARGS)
|
gtrgm_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *query = (text *) PG_GETARG_TEXT_P(1);
|
text *query = (text *) PG_GETARG_TEXT_P(1);
|
||||||
TRGM *key = (TRGM *) DatumGetPointer( ((GISTENTRY *) PG_GETARG_POINTER(0))->key );
|
TRGM *key = (TRGM *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
TRGM *qtrg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
|
TRGM *qtrg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
|
||||||
int res=false;
|
int res = false;
|
||||||
|
|
||||||
if ( GIST_LEAF( (GISTENTRY *) PG_GETARG_POINTER(0) ) ) { /* all leafs contains orig trgm */
|
if (GIST_LEAF((GISTENTRY *) PG_GETARG_POINTER(0)))
|
||||||
float4 tmpsml = cnt_sml(key,qtrg);
|
{ /* all leafs contains orig trgm */
|
||||||
/* strange bug at freebsd 5.2.1 and gcc 3.3.3 */
|
float4 tmpsml = cnt_sml(key, qtrg);
|
||||||
res = ( *(int*)&tmpsml==*(int*)&trgm_limit || tmpsml > trgm_limit ) ? true : false;
|
|
||||||
} else if ( ISALLTRUE(key) ) { /* non-leaf contains signature */
|
/* strange bug at freebsd 5.2.1 and gcc 3.3.3 */
|
||||||
|
res = (*(int *) &tmpsml == *(int *) &trgm_limit || tmpsml > trgm_limit) ? true : false;
|
||||||
|
}
|
||||||
|
else if (ISALLTRUE(key))
|
||||||
|
{ /* non-leaf contains signature */
|
||||||
res = true;
|
res = true;
|
||||||
} else { /* non-leaf contains signature */
|
}
|
||||||
int4 count=0;
|
else
|
||||||
int4 k, len = ARRNELEM(qtrg);
|
{ /* non-leaf contains signature */
|
||||||
|
int4 count = 0;
|
||||||
|
int4 k,
|
||||||
|
len = ARRNELEM(qtrg);
|
||||||
trgm *ptr = GETARR(qtrg);
|
trgm *ptr = GETARR(qtrg);
|
||||||
BITVECP sign = GETSIGN(key);
|
BITVECP sign = GETSIGN(key);
|
||||||
int4 tmp=0;
|
int4 tmp = 0;
|
||||||
|
|
||||||
for (k = 0; k < len; k++) {
|
for (k = 0; k < len; k++)
|
||||||
CPTRGM( ((char*)&tmp), ptr+k );
|
{
|
||||||
|
CPTRGM(((char *) &tmp), ptr + k);
|
||||||
count += GETBIT(sign, HASHVAL(tmp));
|
count += GETBIT(sign, HASHVAL(tmp));
|
||||||
}
|
}
|
||||||
#ifdef DIVUNION
|
#ifdef DIVUNION
|
||||||
res = ( len==count ) ? true : ( ( ( ( ((float4)count) / ((float4)(len-count)) ) ) >= trgm_limit ) ? true : false );
|
res = (len == count) ? true : ((((((float4) count) / ((float4) (len - count)))) >= trgm_limit) ? true : false);
|
||||||
#else
|
#else
|
||||||
res = (len==0) ? false : ( ( ( ( ((float4)count) / ((float4)len) ) ) >= trgm_limit ) ? true : false );
|
res = (len == 0) ? false : ((((((float4) count) / ((float4) len))) >= trgm_limit) ? true : false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_FREE_IF_COPY(query,1);
|
PG_FREE_IF_COPY(query, 1);
|
||||||
pfree(qtrg);
|
pfree(qtrg);
|
||||||
|
|
||||||
PG_RETURN_BOOL(res);
|
PG_RETURN_BOOL(res);
|
||||||
@ -191,10 +200,11 @@ unionkey(BITVECP sbase, TRGM * add)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
trgm *ptr = GETARR(add);
|
trgm *ptr = GETARR(add);
|
||||||
int4 tmp=0;
|
int4 tmp = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRNELEM(add); i++) {
|
for (i = 0; i < ARRNELEM(add); i++)
|
||||||
CPTRGM( ((char*)&tmp), ptr+i );
|
{
|
||||||
|
CPTRGM(((char *) &tmp), ptr + i);
|
||||||
HASH(sbase, tmp);
|
HASH(sbase, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,13 +215,13 @@ unionkey(BITVECP sbase, TRGM * add)
|
|||||||
Datum
|
Datum
|
||||||
gtrgm_union(PG_FUNCTION_ARGS)
|
gtrgm_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int4 len = entryvec->n;
|
int4 len = entryvec->n;
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
BITVEC base;
|
BITVEC base;
|
||||||
int4 i;
|
int4 i;
|
||||||
int4 flag = 0;
|
int4 flag = 0;
|
||||||
TRGM *result;
|
TRGM *result;
|
||||||
|
|
||||||
MemSet((void *) base, 0, sizeof(BITVEC));
|
MemSet((void *) base, 0, sizeof(BITVEC));
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
@ -237,8 +247,8 @@ gtrgm_union(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gtrgm_same(PG_FUNCTION_ARGS)
|
gtrgm_same(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
TRGM *a = (TRGM *) PG_GETARG_POINTER(0);
|
TRGM *a = (TRGM *) PG_GETARG_POINTER(0);
|
||||||
TRGM *b = (TRGM *) PG_GETARG_POINTER(1);
|
TRGM *b = (TRGM *) PG_GETARG_POINTER(1);
|
||||||
bool *result = (bool *) PG_GETARG_POINTER(2);
|
bool *result = (bool *) PG_GETARG_POINTER(2);
|
||||||
|
|
||||||
if (ISSIGNKEY(a))
|
if (ISSIGNKEY(a))
|
||||||
@ -280,7 +290,7 @@ gtrgm_same(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
*result = true;
|
*result = true;
|
||||||
for (i = 0; i < lena; i++)
|
for (i = 0; i < lena; i++)
|
||||||
if (CMPTRGM(ptra+i, ptrb+i))
|
if (CMPTRGM(ptra + i, ptrb + i))
|
||||||
{
|
{
|
||||||
*result = false;
|
*result = false;
|
||||||
break;
|
break;
|
||||||
@ -298,34 +308,39 @@ sizebitvec(BITVECP sign)
|
|||||||
i;
|
i;
|
||||||
|
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
size += SUMBIT(*(char *) sign);
|
size += SUMBIT(*(char *) sign);
|
||||||
sign = (BITVECP) (((char *) sign) + 1);
|
sign = (BITVECP) (((char *) sign) + 1);
|
||||||
);
|
);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistsign(BITVECP a, BITVECP b) {
|
hemdistsign(BITVECP a, BITVECP b)
|
||||||
int i,dist=0;
|
{
|
||||||
|
int i,
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
LOOPBIT(
|
LOOPBIT(
|
||||||
if ( GETBIT(a,i) != GETBIT(b,i) )
|
if (GETBIT(a, i) != GETBIT(b, i))
|
||||||
dist++;
|
dist++;
|
||||||
);
|
);
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdist(TRGM *a, TRGM *b) {
|
hemdist(TRGM * a, TRGM * b)
|
||||||
if ( ISALLTRUE(a) ) {
|
{
|
||||||
|
if (ISALLTRUE(a))
|
||||||
|
{
|
||||||
if (ISALLTRUE(b))
|
if (ISALLTRUE(b))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(b));
|
return SIGLENBIT - sizebitvec(GETSIGN(b));
|
||||||
} else if (ISALLTRUE(b))
|
}
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(a));
|
else if (ISALLTRUE(b))
|
||||||
|
return SIGLENBIT - sizebitvec(GETSIGN(a));
|
||||||
|
|
||||||
return hemdistsign( GETSIGN(a), GETSIGN(b) );
|
return hemdistsign(GETSIGN(a), GETSIGN(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -334,23 +349,25 @@ gtrgm_penalty(PG_FUNCTION_ARGS)
|
|||||||
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
|
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
|
||||||
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
|
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
|
||||||
float *penalty = (float *) PG_GETARG_POINTER(2);
|
float *penalty = (float *) PG_GETARG_POINTER(2);
|
||||||
TRGM *origval = (TRGM *) DatumGetPointer(origentry->key);
|
TRGM *origval = (TRGM *) DatumGetPointer(origentry->key);
|
||||||
TRGM *newval = (TRGM *) DatumGetPointer(newentry->key);
|
TRGM *newval = (TRGM *) DatumGetPointer(newentry->key);
|
||||||
BITVECP orig = GETSIGN(origval);
|
BITVECP orig = GETSIGN(origval);
|
||||||
|
|
||||||
*penalty = 0.0;
|
*penalty = 0.0;
|
||||||
|
|
||||||
if (ISARRKEY(newval)) {
|
if (ISARRKEY(newval))
|
||||||
BITVEC sign;
|
{
|
||||||
|
BITVEC sign;
|
||||||
|
|
||||||
makesign(sign, newval);
|
makesign(sign, newval);
|
||||||
|
|
||||||
if ( ISALLTRUE(origval) )
|
if (ISALLTRUE(origval))
|
||||||
*penalty=((float)(SIGLENBIT-sizebitvec(sign)))/(float)(SIGLENBIT+1);
|
*penalty = ((float) (SIGLENBIT - sizebitvec(sign))) / (float) (SIGLENBIT + 1);
|
||||||
else
|
else
|
||||||
*penalty=hemdistsign(sign,orig);
|
*penalty = hemdistsign(sign, orig);
|
||||||
} else {
|
|
||||||
*penalty=hemdist(origval,newval);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
*penalty = hemdist(origval, newval);
|
||||||
PG_RETURN_POINTER(penalty);
|
PG_RETURN_POINTER(penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,27 +407,30 @@ comparecost(const void *a, const void *b)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistcache(CACHESIGN *a, CACHESIGN *b) {
|
hemdistcache(CACHESIGN * a, CACHESIGN * b)
|
||||||
if ( a->allistrue ) {
|
{
|
||||||
|
if (a->allistrue)
|
||||||
|
{
|
||||||
if (b->allistrue)
|
if (b->allistrue)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return SIGLENBIT-sizebitvec(b->sign);
|
return SIGLENBIT - sizebitvec(b->sign);
|
||||||
} else if (b->allistrue)
|
}
|
||||||
return SIGLENBIT-sizebitvec(a->sign);
|
else if (b->allistrue)
|
||||||
|
return SIGLENBIT - sizebitvec(a->sign);
|
||||||
|
|
||||||
return hemdistsign( a->sign, b->sign );
|
return hemdistsign(a->sign, b->sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gtrgm_picksplit(PG_FUNCTION_ARGS)
|
gtrgm_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
OffsetNumber maxoff = entryvec->n - 2;
|
OffsetNumber maxoff = entryvec->n - 2;
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber k,
|
OffsetNumber k,
|
||||||
j;
|
j;
|
||||||
TRGM *datum_l,
|
TRGM *datum_l,
|
||||||
*datum_r;
|
*datum_r;
|
||||||
BITVECP union_l,
|
BITVECP union_l,
|
||||||
union_r;
|
union_r;
|
||||||
@ -435,13 +455,16 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
|
|||||||
cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
|
cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
|
||||||
fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
|
fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
|
||||||
|
|
||||||
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) {
|
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
|
||||||
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) {
|
{
|
||||||
|
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
|
||||||
|
{
|
||||||
if (k == FirstOffsetNumber)
|
if (k == FirstOffsetNumber)
|
||||||
fillcache(&cache[j], GETENTRY(entryvec, j));
|
fillcache(&cache[j], GETENTRY(entryvec, j));
|
||||||
|
|
||||||
size_waste=hemdistcache(&(cache[j]),&(cache[k]));
|
size_waste = hemdistcache(&(cache[j]), &(cache[k]));
|
||||||
if (size_waste > waste) {
|
if (size_waste > waste)
|
||||||
|
{
|
||||||
waste = size_waste;
|
waste = size_waste;
|
||||||
seed_1 = k;
|
seed_1 = k;
|
||||||
seed_2 = j;
|
seed_2 = j;
|
||||||
@ -454,101 +477,124 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
|
|||||||
right = v->spl_right;
|
right = v->spl_right;
|
||||||
v->spl_nright = 0;
|
v->spl_nright = 0;
|
||||||
|
|
||||||
if (seed_1 == 0 || seed_2 == 0) {
|
if (seed_1 == 0 || seed_2 == 0)
|
||||||
|
{
|
||||||
seed_1 = 1;
|
seed_1 = 1;
|
||||||
seed_2 = 2;
|
seed_2 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* form initial .. */
|
/* form initial .. */
|
||||||
if (cache[seed_1].allistrue) {
|
if (cache[seed_1].allistrue)
|
||||||
|
{
|
||||||
datum_l = (TRGM *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
datum_l = (TRGM *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
||||||
datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
||||||
datum_l->flag = SIGNKEY | ALLISTRUE;
|
datum_l->flag = SIGNKEY | ALLISTRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
datum_l = (TRGM *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
datum_l = (TRGM *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
||||||
datum_l->len = CALCGTSIZE(SIGNKEY, 0);
|
datum_l->len = CALCGTSIZE(SIGNKEY, 0);
|
||||||
datum_l->flag = SIGNKEY;
|
datum_l->flag = SIGNKEY;
|
||||||
memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
if (cache[seed_2].allistrue) {
|
if (cache[seed_2].allistrue)
|
||||||
|
{
|
||||||
datum_r = (TRGM *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
datum_r = (TRGM *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
||||||
datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
||||||
datum_r->flag = SIGNKEY | ALLISTRUE;
|
datum_r->flag = SIGNKEY | ALLISTRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
datum_r = (TRGM *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
datum_r = (TRGM *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
||||||
datum_r->len = CALCGTSIZE(SIGNKEY, 0);
|
datum_r->len = CALCGTSIZE(SIGNKEY, 0);
|
||||||
datum_r->flag = SIGNKEY;
|
datum_r->flag = SIGNKEY;
|
||||||
memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
|
|
||||||
union_l=GETSIGN(datum_l);
|
union_l = GETSIGN(datum_l);
|
||||||
union_r=GETSIGN(datum_r);
|
union_r = GETSIGN(datum_r);
|
||||||
maxoff = OffsetNumberNext(maxoff);
|
maxoff = OffsetNumberNext(maxoff);
|
||||||
fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
|
fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
|
||||||
/* sort before ... */
|
/* sort before ... */
|
||||||
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
||||||
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) {
|
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
|
||||||
|
{
|
||||||
costvector[j - 1].pos = j;
|
costvector[j - 1].pos = j;
|
||||||
size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
|
size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
|
||||||
size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
|
size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
|
||||||
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
||||||
}
|
}
|
||||||
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
||||||
|
|
||||||
for (k = 0; k < maxoff; k++) {
|
for (k = 0; k < maxoff; k++)
|
||||||
|
{
|
||||||
j = costvector[k].pos;
|
j = costvector[k].pos;
|
||||||
if (j == seed_1) {
|
if (j == seed_1)
|
||||||
|
{
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
continue;
|
continue;
|
||||||
} else if (j == seed_2) {
|
}
|
||||||
|
else if (j == seed_2)
|
||||||
|
{
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
v->spl_nright++;
|
v->spl_nright++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISALLTRUE(datum_l) || cache[j].allistrue) {
|
if (ISALLTRUE(datum_l) || cache[j].allistrue)
|
||||||
if ( ISALLTRUE(datum_l) && cache[j].allistrue )
|
{
|
||||||
size_alpha=0;
|
if (ISALLTRUE(datum_l) && cache[j].allistrue)
|
||||||
|
size_alpha = 0;
|
||||||
else
|
else
|
||||||
size_alpha = SIGLENBIT-sizebitvec(
|
size_alpha = SIGLENBIT - sizebitvec(
|
||||||
( cache[j].allistrue ) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign)
|
(cache[j].allistrue) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign)
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
size_alpha=hemdistsign(cache[j].sign,GETSIGN(datum_l));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));
|
||||||
|
|
||||||
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
|
if (ISALLTRUE(datum_r) || cache[j].allistrue)
|
||||||
if ( ISALLTRUE(datum_r) && cache[j].allistrue )
|
{
|
||||||
size_beta=0;
|
if (ISALLTRUE(datum_r) && cache[j].allistrue)
|
||||||
|
size_beta = 0;
|
||||||
else
|
else
|
||||||
size_beta = SIGLENBIT-sizebitvec(
|
size_beta = SIGLENBIT - sizebitvec(
|
||||||
( cache[j].allistrue ) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
|
(cache[j].allistrue) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
size_beta=hemdistsign(cache[j].sign,GETSIGN(datum_r));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r));
|
||||||
|
|
||||||
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1)) {
|
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
|
||||||
if (ISALLTRUE(datum_l) || cache[j].allistrue) {
|
{
|
||||||
if (! ISALLTRUE(datum_l) )
|
if (ISALLTRUE(datum_l) || cache[j].allistrue)
|
||||||
|
{
|
||||||
|
if (!ISALLTRUE(datum_l))
|
||||||
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
|
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=cache[j].sign;
|
else
|
||||||
|
{
|
||||||
|
ptr = cache[j].sign;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
union_l[i] |= ptr[i];
|
union_l[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
} else {
|
}
|
||||||
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
|
else
|
||||||
if (! ISALLTRUE(datum_r) )
|
{
|
||||||
|
if (ISALLTRUE(datum_r) || cache[j].allistrue)
|
||||||
|
{
|
||||||
|
if (!ISALLTRUE(datum_r))
|
||||||
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
|
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=cache[j].sign;
|
else
|
||||||
|
{
|
||||||
|
ptr = cache[j].sign;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
union_r[i] |= ptr[i];
|
union_r[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
|
@ -3,136 +3,162 @@
|
|||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
|
||||||
float4 trgm_limit = 0.3;
|
float4 trgm_limit = 0.3;
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(set_limit);
|
PG_FUNCTION_INFO_V1(set_limit);
|
||||||
Datum set_limit(PG_FUNCTION_ARGS);
|
Datum set_limit(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
set_limit(PG_FUNCTION_ARGS) {
|
set_limit(PG_FUNCTION_ARGS)
|
||||||
float4 nlimit = PG_GETARG_FLOAT4(0);
|
{
|
||||||
if ( nlimit < 0 || nlimit > 1.0 )
|
float4 nlimit = PG_GETARG_FLOAT4(0);
|
||||||
elog(ERROR,"Wrong limit, should be between 0 and 1");
|
|
||||||
|
if (nlimit < 0 || nlimit > 1.0)
|
||||||
|
elog(ERROR, "Wrong limit, should be between 0 and 1");
|
||||||
trgm_limit = nlimit;
|
trgm_limit = nlimit;
|
||||||
PG_RETURN_FLOAT4(trgm_limit);
|
PG_RETURN_FLOAT4(trgm_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(show_limit);
|
PG_FUNCTION_INFO_V1(show_limit);
|
||||||
Datum show_limit(PG_FUNCTION_ARGS);
|
Datum show_limit(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
show_limit(PG_FUNCTION_ARGS) {
|
show_limit(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
PG_RETURN_FLOAT4(trgm_limit);
|
PG_RETURN_FLOAT4(trgm_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WORDWAIT 0
|
#define WORDWAIT 0
|
||||||
#define INWORD 1
|
#define INWORD 1
|
||||||
|
|
||||||
static int
|
static int
|
||||||
comp_trgm(const void *a, const void *b) {
|
comp_trgm(const void *a, const void *b)
|
||||||
return CMPTRGM(a,b);
|
{
|
||||||
|
return CMPTRGM(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unique_array (trgm *a, int len) {
|
unique_array(trgm * a, int len)
|
||||||
trgm *curend, *tmp;
|
{
|
||||||
|
trgm *curend,
|
||||||
|
*tmp;
|
||||||
|
|
||||||
curend = tmp = a;
|
curend = tmp = a;
|
||||||
while (tmp - a < len)
|
while (tmp - a < len)
|
||||||
if ( CMPTRGM(tmp, curend) ) {
|
if (CMPTRGM(tmp, curend))
|
||||||
|
{
|
||||||
curend++;
|
curend++;
|
||||||
CPTRGM(curend,tmp);
|
CPTRGM(curend, tmp);
|
||||||
tmp++;
|
tmp++;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
tmp++;
|
tmp++;
|
||||||
|
|
||||||
return curend + 1 - a;
|
return curend + 1 - a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRGM*
|
TRGM *
|
||||||
generate_trgm(char *str, int slen) {
|
generate_trgm(char *str, int slen)
|
||||||
TRGM* trg;
|
{
|
||||||
char *buf,*sptr,*bufptr;
|
TRGM *trg;
|
||||||
trgm *tptr;
|
char *buf,
|
||||||
int state=WORDWAIT;
|
*sptr,
|
||||||
int wl,len;
|
*bufptr;
|
||||||
|
trgm *tptr;
|
||||||
|
int state = WORDWAIT;
|
||||||
|
int wl,
|
||||||
|
len;
|
||||||
|
|
||||||
trg = (TRGM*) palloc(TRGMHRDSIZE+sizeof(trgm) * (slen/2 + 1) * 3);
|
trg = (TRGM *) palloc(TRGMHRDSIZE + sizeof(trgm) * (slen / 2 + 1) * 3);
|
||||||
trg->flag = ARRKEY;
|
trg->flag = ARRKEY;
|
||||||
trg->len = TRGMHRDSIZE;
|
trg->len = TRGMHRDSIZE;
|
||||||
|
|
||||||
if ( slen+LPADDING+RPADDING<3 || slen == 0 )
|
if (slen + LPADDING + RPADDING < 3 || slen == 0)
|
||||||
return trg;
|
return trg;
|
||||||
|
|
||||||
tptr = GETARR(trg);
|
tptr = GETARR(trg);
|
||||||
|
|
||||||
buf = palloc(sizeof(char) * (slen+4));
|
buf = palloc(sizeof(char) * (slen + 4));
|
||||||
sptr = str;
|
sptr = str;
|
||||||
|
|
||||||
if ( LPADDING > 0 ) {
|
if (LPADDING > 0)
|
||||||
|
{
|
||||||
*buf = ' ';
|
*buf = ' ';
|
||||||
if ( LPADDING > 1 )
|
if (LPADDING > 1)
|
||||||
*(buf+1) = ' ';
|
*(buf + 1) = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
bufptr = buf+LPADDING;
|
bufptr = buf + LPADDING;
|
||||||
while( sptr-str < slen ) {
|
while (sptr - str < slen)
|
||||||
if ( state == WORDWAIT ) {
|
{
|
||||||
|
if (state == WORDWAIT)
|
||||||
|
{
|
||||||
if (
|
if (
|
||||||
#ifdef KEEPONLYALNUM
|
#ifdef KEEPONLYALNUM
|
||||||
isalnum((unsigned char)*sptr)
|
isalnum((unsigned char) *sptr)
|
||||||
#else
|
#else
|
||||||
!isspace( (unsigned char)*sptr )
|
!isspace((unsigned char) *sptr)
|
||||||
#endif
|
#endif
|
||||||
) {
|
)
|
||||||
*bufptr = *sptr; /* start put word in buffer */
|
{
|
||||||
|
*bufptr = *sptr; /* start put word in buffer */
|
||||||
bufptr++;
|
bufptr++;
|
||||||
state = INWORD;
|
state = INWORD;
|
||||||
if ( sptr-str == slen-1 /* last char */ )
|
if (sptr - str == slen - 1 /* last char */ )
|
||||||
goto gettrg;
|
goto gettrg;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (
|
if (
|
||||||
#ifdef KEEPONLYALNUM
|
#ifdef KEEPONLYALNUM
|
||||||
!isalnum((unsigned char)*sptr)
|
!isalnum((unsigned char) *sptr)
|
||||||
#else
|
#else
|
||||||
isspace( (unsigned char)*sptr )
|
isspace((unsigned char) *sptr)
|
||||||
#endif
|
#endif
|
||||||
) {
|
)
|
||||||
gettrg:
|
{
|
||||||
|
gettrg:
|
||||||
/* word in buffer, so count trigrams */
|
/* word in buffer, so count trigrams */
|
||||||
*bufptr = ' ';
|
*bufptr = ' ';
|
||||||
*(bufptr+1) = ' ';
|
*(bufptr + 1) = ' ';
|
||||||
wl = bufptr - (buf+LPADDING) - 2 + LPADDING + RPADDING;
|
wl = bufptr - (buf + LPADDING) - 2 + LPADDING + RPADDING;
|
||||||
if ( wl<=0 ) {
|
if (wl <= 0)
|
||||||
bufptr = buf+LPADDING;
|
{
|
||||||
|
bufptr = buf + LPADDING;
|
||||||
state = WORDWAIT;
|
state = WORDWAIT;
|
||||||
sptr++;
|
sptr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IGNORECASE
|
#ifdef IGNORECASE
|
||||||
do { /* lower word */
|
do
|
||||||
int wwl = bufptr-buf;
|
{ /* lower word */
|
||||||
bufptr = buf+LPADDING;
|
int wwl = bufptr - buf;
|
||||||
while( bufptr-buf < wwl ) {
|
|
||||||
*bufptr = tolower( (unsigned char) *bufptr );
|
bufptr = buf + LPADDING;
|
||||||
|
while (bufptr - buf < wwl)
|
||||||
|
{
|
||||||
|
*bufptr = tolower((unsigned char) *bufptr);
|
||||||
bufptr++;
|
bufptr++;
|
||||||
}
|
}
|
||||||
} while(0);
|
} while (0);
|
||||||
#endif
|
#endif
|
||||||
bufptr = buf;
|
bufptr = buf;
|
||||||
/* set trigrams */
|
/* set trigrams */
|
||||||
while( bufptr-buf < wl ) {
|
while (bufptr - buf < wl)
|
||||||
|
{
|
||||||
CPTRGM(tptr, bufptr);
|
CPTRGM(tptr, bufptr);
|
||||||
bufptr++;
|
bufptr++;
|
||||||
tptr++;
|
tptr++;
|
||||||
}
|
}
|
||||||
bufptr = buf+LPADDING;
|
bufptr = buf + LPADDING;
|
||||||
state = WORDWAIT;
|
state = WORDWAIT;
|
||||||
} else {
|
}
|
||||||
*bufptr = *sptr; /* put in buffer */
|
else
|
||||||
|
{
|
||||||
|
*bufptr = *sptr; /* put in buffer */
|
||||||
bufptr++;
|
bufptr++;
|
||||||
if ( sptr-str == slen-1 )
|
if (sptr - str == slen - 1)
|
||||||
goto gettrg;
|
goto gettrg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,12 +167,13 @@ gettrg:
|
|||||||
|
|
||||||
pfree(buf);
|
pfree(buf);
|
||||||
|
|
||||||
if ( (len=tptr-GETARR(trg)) == 0 )
|
if ((len = tptr - GETARR(trg)) == 0)
|
||||||
return trg;
|
return trg;
|
||||||
|
|
||||||
if ( len>0 ) {
|
if (len > 0)
|
||||||
qsort( (void*)GETARR(trg), len, sizeof(trgm), comp_trgm );
|
{
|
||||||
len = unique_array( GETARR(trg), len );
|
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
|
||||||
|
len = unique_array(GETARR(trg), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
trg->len = CALCGTSIZE(ARRKEY, len);
|
trg->len = CALCGTSIZE(ARRKEY, len);
|
||||||
@ -156,54 +183,61 @@ gettrg:
|
|||||||
|
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(show_trgm);
|
PG_FUNCTION_INFO_V1(show_trgm);
|
||||||
Datum show_trgm(PG_FUNCTION_ARGS);
|
Datum show_trgm(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
show_trgm(PG_FUNCTION_ARGS) {
|
show_trgm(PG_FUNCTION_ARGS)
|
||||||
text *in = PG_GETARG_TEXT_P(0);
|
{
|
||||||
TRGM *trg;
|
text *in = PG_GETARG_TEXT_P(0);
|
||||||
Datum *d;
|
TRGM *trg;
|
||||||
ArrayType *a;
|
Datum *d;
|
||||||
trgm *ptr;
|
ArrayType *a;
|
||||||
|
trgm *ptr;
|
||||||
|
|
||||||
trg = generate_trgm(VARDATA(in), VARSIZE(in) - VARHDRSZ);
|
trg = generate_trgm(VARDATA(in), VARSIZE(in) - VARHDRSZ);
|
||||||
d = (Datum*)palloc( sizeof(Datum)*(1+ARRNELEM(trg)) );
|
d = (Datum *) palloc(sizeof(Datum) * (1 + ARRNELEM(trg)));
|
||||||
|
|
||||||
ptr = GETARR(trg);
|
ptr = GETARR(trg);
|
||||||
while( ptr-GETARR(trg) < ARRNELEM(trg) ) {
|
while (ptr - GETARR(trg) < ARRNELEM(trg))
|
||||||
text *item=(text*)palloc(VARHDRSZ + 3);
|
{
|
||||||
VARATT_SIZEP(item) = VARHDRSZ+3;
|
text *item = (text *) palloc(VARHDRSZ + 3);
|
||||||
|
|
||||||
|
VARATT_SIZEP(item) = VARHDRSZ + 3;
|
||||||
CPTRGM(VARDATA(item), ptr);
|
CPTRGM(VARDATA(item), ptr);
|
||||||
d[ ptr-GETARR(trg) ] = PointerGetDatum(item);
|
d[ptr - GETARR(trg)] = PointerGetDatum(item);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = construct_array(
|
a = construct_array(
|
||||||
d,
|
d,
|
||||||
ARRNELEM(trg),
|
ARRNELEM(trg),
|
||||||
TEXTOID,
|
TEXTOID,
|
||||||
-1,
|
-1,
|
||||||
false,
|
false,
|
||||||
'i'
|
'i'
|
||||||
);
|
);
|
||||||
|
|
||||||
ptr = GETARR(trg);
|
ptr = GETARR(trg);
|
||||||
while( ptr-GETARR(trg) < ARRNELEM(trg) ) {
|
while (ptr - GETARR(trg) < ARRNELEM(trg))
|
||||||
pfree(DatumGetPointer(d[ ptr-GETARR(trg) ]));
|
{
|
||||||
|
pfree(DatumGetPointer(d[ptr - GETARR(trg)]));
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(d);
|
pfree(d);
|
||||||
pfree(trg);
|
pfree(trg);
|
||||||
PG_FREE_IF_COPY(in,0);
|
PG_FREE_IF_COPY(in, 0);
|
||||||
|
|
||||||
PG_RETURN_POINTER(a);
|
PG_RETURN_POINTER(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
float4
|
float4
|
||||||
cnt_sml(TRGM *trg1, TRGM *trg2) {
|
cnt_sml(TRGM * trg1, TRGM * trg2)
|
||||||
trgm *ptr1, *ptr2;
|
{
|
||||||
int count=0;
|
trgm *ptr1,
|
||||||
int len1, len2;
|
*ptr2;
|
||||||
|
int count = 0;
|
||||||
|
int len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
ptr1 = GETARR(trg1);
|
ptr1 = GETARR(trg1);
|
||||||
ptr2 = GETARR(trg2);
|
ptr2 = GETARR(trg2);
|
||||||
@ -211,13 +245,16 @@ cnt_sml(TRGM *trg1, TRGM *trg2) {
|
|||||||
len1 = ARRNELEM(trg1);
|
len1 = ARRNELEM(trg1);
|
||||||
len2 = ARRNELEM(trg2);
|
len2 = ARRNELEM(trg2);
|
||||||
|
|
||||||
while( ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2 ) {
|
while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2)
|
||||||
int res = CMPTRGM(ptr1,ptr2);
|
{
|
||||||
if ( res < 0 ) {
|
int res = CMPTRGM(ptr1, ptr2);
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
ptr1++;
|
ptr1++;
|
||||||
} else if ( res > 0 ) {
|
else if (res > 0)
|
||||||
ptr2++;
|
ptr2++;
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
ptr1++;
|
ptr1++;
|
||||||
ptr2++;
|
ptr2++;
|
||||||
count++;
|
count++;
|
||||||
@ -225,45 +262,47 @@ cnt_sml(TRGM *trg1, TRGM *trg2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DIVUNION
|
#ifdef DIVUNION
|
||||||
return ( ( ((float4)count) / ((float4)(len1+len2-count)) ) );
|
return ((((float4) count) / ((float4) (len1 + len2 - count))));
|
||||||
#else
|
#else
|
||||||
return ( ((float)count) / ((float)( (len1>len2) ? len1 : len2 )) );
|
return (((float) count) / ((float) ((len1 > len2) ? len1 : len2)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(similarity);
|
PG_FUNCTION_INFO_V1(similarity);
|
||||||
Datum similarity(PG_FUNCTION_ARGS);
|
Datum similarity(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
similarity(PG_FUNCTION_ARGS) {
|
similarity(PG_FUNCTION_ARGS)
|
||||||
text *in1 = PG_GETARG_TEXT_P(0);
|
{
|
||||||
text *in2 = PG_GETARG_TEXT_P(1);
|
text *in1 = PG_GETARG_TEXT_P(0);
|
||||||
TRGM *trg1, *trg2;
|
text *in2 = PG_GETARG_TEXT_P(1);
|
||||||
float4 res;
|
TRGM *trg1,
|
||||||
|
*trg2;
|
||||||
|
float4 res;
|
||||||
|
|
||||||
trg1 = generate_trgm(VARDATA(in1), VARSIZE(in1) - VARHDRSZ);
|
trg1 = generate_trgm(VARDATA(in1), VARSIZE(in1) - VARHDRSZ);
|
||||||
trg2 = generate_trgm(VARDATA(in2), VARSIZE(in2) - VARHDRSZ);
|
trg2 = generate_trgm(VARDATA(in2), VARSIZE(in2) - VARHDRSZ);
|
||||||
|
|
||||||
res = cnt_sml(trg1,trg2);
|
res = cnt_sml(trg1, trg2);
|
||||||
|
|
||||||
pfree(trg1);
|
pfree(trg1);
|
||||||
pfree(trg2);
|
pfree(trg2);
|
||||||
PG_FREE_IF_COPY(in1,0);
|
PG_FREE_IF_COPY(in1, 0);
|
||||||
PG_FREE_IF_COPY(in2,1);
|
PG_FREE_IF_COPY(in2, 1);
|
||||||
|
|
||||||
PG_RETURN_FLOAT4(res);
|
PG_RETURN_FLOAT4(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(similarity_op);
|
PG_FUNCTION_INFO_V1(similarity_op);
|
||||||
Datum similarity_op(PG_FUNCTION_ARGS);
|
Datum similarity_op(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
similarity_op(PG_FUNCTION_ARGS) {
|
similarity_op(PG_FUNCTION_ARGS)
|
||||||
float4 res=DatumGetFloat4( DirectFunctionCall2(
|
{
|
||||||
similarity,
|
float4 res = DatumGetFloat4(DirectFunctionCall2(
|
||||||
PG_GETARG_DATUM(0),
|
similarity,
|
||||||
PG_GETARG_DATUM(1)
|
PG_GETARG_DATUM(0),
|
||||||
) );
|
PG_GETARG_DATUM(1)
|
||||||
PG_RETURN_BOOL( res >= trgm_limit );
|
));
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(res >= trgm_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.31 2004/06/14 11:00:12 ishii Exp $
|
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.32 2004/08/29 05:06:36 momjian Exp $
|
||||||
*
|
*
|
||||||
* pgbench: a simple TPC-B like benchmark program for PostgreSQL
|
* pgbench: a simple TPC-B like benchmark program for PostgreSQL
|
||||||
* written by Tatsuo Ishii
|
* written by Tatsuo Ishii
|
||||||
@ -261,7 +261,7 @@ doOne(CState * state, int n, int debug, int ttype)
|
|||||||
*/
|
*/
|
||||||
if (use_log)
|
if (use_log)
|
||||||
{
|
{
|
||||||
double diff;
|
double diff;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
gettimeofday(&now, 0);
|
gettimeofday(&now, 0);
|
||||||
@ -492,7 +492,7 @@ init(void)
|
|||||||
static char *DDLAFTERs[] = {
|
static char *DDLAFTERs[] = {
|
||||||
"alter table branches add primary key (bid)",
|
"alter table branches add primary key (bid)",
|
||||||
"alter table tellers add primary key (tid)",
|
"alter table tellers add primary key (tid)",
|
||||||
"alter table accounts add primary key (aid)"};
|
"alter table accounts add primary key (aid)"};
|
||||||
|
|
||||||
|
|
||||||
char sql[256];
|
char sql[256];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.15 2004/05/08 19:09:24 tgl Exp $
|
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.16 2004/08/29 05:06:37 momjian Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001,2002 Tatsuo Ishii
|
* Copyright (c) 2001,2002 Tatsuo Ishii
|
||||||
*
|
*
|
||||||
@ -129,7 +129,7 @@ pgstattuple_real(Relation rel)
|
|||||||
|
|
||||||
scan = heap_beginscan(rel, SnapshotAny, 0, NULL);
|
scan = heap_beginscan(rel, SnapshotAny, 0, NULL);
|
||||||
|
|
||||||
nblocks = scan->rs_nblocks; /* # blocks to be scanned */
|
nblocks = scan->rs_nblocks; /* # blocks to be scanned */
|
||||||
|
|
||||||
/* scan the relation */
|
/* scan the relation */
|
||||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||||
@ -189,9 +189,9 @@ pgstattuple_real(Relation rel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare a values array for constructing the tuple. This should be an
|
* Prepare a values array for constructing the tuple. This should be
|
||||||
* array of C strings which will be processed later by the appropriate
|
* an array of C strings which will be processed later by the
|
||||||
* "in" functions.
|
* appropriate "in" functions.
|
||||||
*/
|
*/
|
||||||
values = (char **) palloc(NCOLUMNS * sizeof(char *));
|
values = (char **) palloc(NCOLUMNS * sizeof(char *));
|
||||||
for (i = 0; i < NCOLUMNS; i++)
|
for (i = 0; i < NCOLUMNS; i++)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.9 2004/03/30 15:45:33 teodor Exp $
|
* $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.10 2004/08/29 05:06:37 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -98,7 +98,7 @@ gbox_consistent(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
gbox_union(PG_FUNCTION_ARGS)
|
gbox_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *sizep = (int *) PG_GETARG_POINTER(1);
|
int *sizep = (int *) PG_GETARG_POINTER(1);
|
||||||
int numranges,
|
int numranges,
|
||||||
i;
|
i;
|
||||||
@ -186,7 +186,7 @@ compare_KB(const void *a, const void *b)
|
|||||||
Datum
|
Datum
|
||||||
gbox_picksplit(PG_FUNCTION_ARGS)
|
gbox_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber i;
|
OffsetNumber i;
|
||||||
OffsetNumber *listL,
|
OffsetNumber *listL,
|
||||||
|
@ -240,7 +240,7 @@ gseg_union(GistEntryVector *entryvec, int *sizep)
|
|||||||
for (i = 1; i < numranges; i++)
|
for (i = 1; i < numranges; i++)
|
||||||
{
|
{
|
||||||
out = gseg_binary_union(tmp, (SEG *)
|
out = gseg_binary_union(tmp, (SEG *)
|
||||||
DatumGetPointer(entryvec->vector[i].key),
|
DatumGetPointer(entryvec->vector[i].key),
|
||||||
sizep);
|
sizep);
|
||||||
if (i > 1)
|
if (i > 1)
|
||||||
pfree(tmp);
|
pfree(tmp);
|
||||||
@ -755,8 +755,8 @@ seg_cmp(SEG * a, SEG * b)
|
|||||||
* a->lower == b->lower, so consider type of boundary.
|
* a->lower == b->lower, so consider type of boundary.
|
||||||
*
|
*
|
||||||
* A '-' lower bound is < any other kind (this could only be relevant if
|
* A '-' lower bound is < any other kind (this could only be relevant if
|
||||||
* -HUGE_VAL is used as a regular data value). A '<' lower bound is < any
|
* -HUGE_VAL is used as a regular data value). A '<' lower bound is <
|
||||||
* other kind except '-'. A '>' lower bound is > any other kind.
|
* any other kind except '-'. A '>' lower bound is > any other kind.
|
||||||
*/
|
*/
|
||||||
if (a->l_ext != b->l_ext)
|
if (a->l_ext != b->l_ext)
|
||||||
{
|
{
|
||||||
@ -813,8 +813,8 @@ seg_cmp(SEG * a, SEG * b)
|
|||||||
* a->upper == b->upper, so consider type of boundary.
|
* a->upper == b->upper, so consider type of boundary.
|
||||||
*
|
*
|
||||||
* A '-' upper bound is > any other kind (this could only be relevant if
|
* A '-' upper bound is > any other kind (this could only be relevant if
|
||||||
* HUGE_VAL is used as a regular data value). A '<' upper bound is < any
|
* HUGE_VAL is used as a regular data value). A '<' upper bound is <
|
||||||
* other kind. A '>' upper bound is > any other kind except '-'.
|
* any other kind. A '>' upper bound is > any other kind except '-'.
|
||||||
*/
|
*/
|
||||||
if (a->u_ext != b->u_ext)
|
if (a->u_ext != b->u_ext)
|
||||||
{
|
{
|
||||||
|
@ -309,7 +309,7 @@ timetravel(PG_FUNCTION_ARGS)
|
|||||||
void *pplan;
|
void *pplan;
|
||||||
Oid *ctypes;
|
Oid *ctypes;
|
||||||
char sql[8192];
|
char sql[8192];
|
||||||
char separ=' ';
|
char separ = ' ';
|
||||||
|
|
||||||
/* allocate ctypes for preparation */
|
/* allocate ctypes for preparation */
|
||||||
ctypes = (Oid *) palloc(natts * sizeof(Oid));
|
ctypes = (Oid *) palloc(natts * sizeof(Oid));
|
||||||
@ -323,8 +323,8 @@ timetravel(PG_FUNCTION_ARGS)
|
|||||||
ctypes[i - 1] = SPI_gettypeid(tupdesc, i);
|
ctypes[i - 1] = SPI_gettypeid(tupdesc, i);
|
||||||
if (!(tupdesc->attrs[i - 1]->attisdropped)) /* skip dropped columns */
|
if (!(tupdesc->attrs[i - 1]->attisdropped)) /* skip dropped columns */
|
||||||
{
|
{
|
||||||
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%c$%d", separ,i);
|
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%c$%d", separ, i);
|
||||||
separ = ',';
|
separ = ',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ")");
|
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ")");
|
||||||
|
@ -875,7 +875,7 @@ get_crosstab_tuplestore(char *sql,
|
|||||||
/* no qualifying category tuples */
|
/* no qualifying category tuples */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("provided \"categories\" SQL must " \
|
errmsg("provided \"categories\" SQL must " \
|
||||||
"return 1 column of at least one row")));
|
"return 1 column of at least one row")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,10 +326,11 @@ unionkey(BITVECP sbase, GISTTYPE * add)
|
|||||||
Datum
|
Datum
|
||||||
gtxtidx_union(PG_FUNCTION_ARGS)
|
gtxtidx_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
BITVEC base;
|
BITVEC base;
|
||||||
int4 i,len;
|
int4 i,
|
||||||
|
len;
|
||||||
int4 flag = 0;
|
int4 flag = 0;
|
||||||
GISTTYPE *result;
|
GISTTYPE *result;
|
||||||
|
|
||||||
@ -512,7 +513,7 @@ comparecost(const void *a, const void *b)
|
|||||||
Datum
|
Datum
|
||||||
gtxtidx_picksplit(PG_FUNCTION_ARGS)
|
gtxtidx_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber k,
|
OffsetNumber k,
|
||||||
j;
|
j;
|
||||||
|
@ -241,15 +241,19 @@ pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval)
|
|||||||
lemm = lemmatize(token, &lenlemm, type);
|
lemm = lemmatize(token, &lenlemm, type);
|
||||||
if (lemm)
|
if (lemm)
|
||||||
{
|
{
|
||||||
if ( lemm==token ) {
|
if (lemm == token)
|
||||||
char *ptrs=token,*ptrd;
|
{
|
||||||
ptrd = lemm = palloc(lenlemm+1);
|
char *ptrs = token,
|
||||||
while(ptrs-token<lenlemm) {
|
*ptrd;
|
||||||
|
|
||||||
|
ptrd = lemm = palloc(lenlemm + 1);
|
||||||
|
while (ptrs - token < lenlemm)
|
||||||
|
{
|
||||||
*ptrd = tolower((unsigned char) *ptrs);
|
*ptrd = tolower((unsigned char) *ptrs);
|
||||||
ptrs++;
|
ptrs++;
|
||||||
ptrd++;
|
ptrd++;
|
||||||
}
|
}
|
||||||
*ptrd='\0';
|
*ptrd = '\0';
|
||||||
}
|
}
|
||||||
pushval_asis(state, VAL, lemm, lenlemm);
|
pushval_asis(state, VAL, lemm, lenlemm);
|
||||||
pfree(lemm);
|
pfree(lemm);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
|
|
||||||
|
|
||||||
Oid TSNSP_FunctionOid = InvalidOid;
|
Oid TSNSP_FunctionOid = InvalidOid;
|
||||||
|
|
||||||
|
|
||||||
text *
|
text *
|
||||||
@ -121,44 +121,45 @@ text_cmp(text *a, text *b)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char *
|
||||||
get_namespace(Oid funcoid) {
|
get_namespace(Oid funcoid)
|
||||||
HeapTuple tuple;
|
{
|
||||||
Form_pg_proc proc;
|
HeapTuple tuple;
|
||||||
Form_pg_namespace nsp;
|
Form_pg_proc proc;
|
||||||
Oid nspoid;
|
Form_pg_namespace nsp;
|
||||||
char *txt;
|
Oid nspoid;
|
||||||
|
char *txt;
|
||||||
|
|
||||||
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0);
|
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "cache lookup failed for proc oid %u", funcoid);
|
elog(ERROR, "cache lookup failed for proc oid %u", funcoid);
|
||||||
proc=(Form_pg_proc) GETSTRUCT(tuple);
|
proc = (Form_pg_proc) GETSTRUCT(tuple);
|
||||||
nspoid = proc->pronamespace;
|
nspoid = proc->pronamespace;
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
tuple = SearchSysCache(NAMESPACEOID, ObjectIdGetDatum(nspoid), 0, 0, 0);
|
tuple = SearchSysCache(NAMESPACEOID, ObjectIdGetDatum(nspoid), 0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "cache lookup failed for namespace oid %u", nspoid);
|
elog(ERROR, "cache lookup failed for namespace oid %u", nspoid);
|
||||||
nsp = (Form_pg_namespace) GETSTRUCT(tuple);
|
nsp = (Form_pg_namespace) GETSTRUCT(tuple);
|
||||||
txt = pstrdup( NameStr((nsp->nspname)) );
|
txt = pstrdup(NameStr((nsp->nspname)));
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
return txt;
|
return txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Oid
|
Oid
|
||||||
get_oidnamespace(Oid funcoid) {
|
get_oidnamespace(Oid funcoid)
|
||||||
HeapTuple tuple;
|
{
|
||||||
Form_pg_proc proc;
|
HeapTuple tuple;
|
||||||
Oid nspoid;
|
Form_pg_proc proc;
|
||||||
|
Oid nspoid;
|
||||||
|
|
||||||
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0);
|
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "cache lookup failed for proc oid %u", funcoid);
|
elog(ERROR, "cache lookup failed for proc oid %u", funcoid);
|
||||||
proc=(Form_pg_proc) GETSTRUCT(tuple);
|
proc = (Form_pg_proc) GETSTRUCT(tuple);
|
||||||
nspoid = proc->pronamespace;
|
nspoid = proc->pronamespace;
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
return nspoid;
|
return nspoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,13 +21,14 @@ int text_cmp(text *a, text *b);
|
|||||||
|
|
||||||
void ts_error(int state, const char *format,...);
|
void ts_error(int state, const char *format,...);
|
||||||
|
|
||||||
extern Oid TSNSP_FunctionOid; /* oid of called function, needed only for determ namespace, no more */
|
extern Oid TSNSP_FunctionOid; /* oid of called function, needed only for
|
||||||
char* get_namespace(Oid funcoid);
|
* determ namespace, no more */
|
||||||
Oid get_oidnamespace(Oid funcoid);
|
char *get_namespace(Oid funcoid);
|
||||||
|
Oid get_oidnamespace(Oid funcoid);
|
||||||
|
|
||||||
#define SET_FUNCOID() do { \
|
#define SET_FUNCOID() do { \
|
||||||
if ( fcinfo->flinfo && fcinfo->flinfo->fn_oid != InvalidOid ) \
|
if ( fcinfo->flinfo && fcinfo->flinfo->fn_oid != InvalidOid ) \
|
||||||
TSNSP_FunctionOid = fcinfo->flinfo->fn_oid; \
|
TSNSP_FunctionOid = fcinfo->flinfo->fn_oid; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,18 +26,18 @@ init_dict(Oid id, DictInfo * dict)
|
|||||||
bool isnull;
|
bool isnull;
|
||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
int stat;
|
int stat;
|
||||||
void *plan;
|
void *plan;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *nsp = get_namespace(TSNSP_FunctionOid);
|
char *nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
|
|
||||||
arg[0] = OIDOID;
|
arg[0] = OIDOID;
|
||||||
pars[0] = ObjectIdGetDatum(id);
|
pars[0] = ObjectIdGetDatum(id);
|
||||||
|
|
||||||
memset(dict, 0, sizeof(DictInfo));
|
memset(dict, 0, sizeof(DictInfo));
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
sprintf(buf,"select dict_init, dict_initoption, dict_lexize from %s.pg_ts_dict where oid = $1", nsp);
|
sprintf(buf, "select dict_init, dict_initoption, dict_lexize from %s.pg_ts_dict where oid = $1", nsp);
|
||||||
pfree(nsp);
|
pfree(nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -142,8 +142,9 @@ name2id_dict(text *name)
|
|||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
int stat;
|
int stat;
|
||||||
Oid id = findSNMap_t(&(DList.name2id_map), name);
|
Oid id = findSNMap_t(&(DList.name2id_map), name);
|
||||||
void *plan;
|
void *plan;
|
||||||
char buf[1024], *nsp;
|
char buf[1024],
|
||||||
|
*nsp;
|
||||||
|
|
||||||
arg[0] = TEXTOID;
|
arg[0] = TEXTOID;
|
||||||
pars[0] = PointerGetDatum(name);
|
pars[0] = PointerGetDatum(name);
|
||||||
@ -153,9 +154,9 @@ name2id_dict(text *name)
|
|||||||
|
|
||||||
nsp = get_namespace(TSNSP_FunctionOid);
|
nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
sprintf(buf,"select oid from %s.pg_ts_dict where dict_name = $1", nsp);
|
sprintf(buf, "select oid from %s.pg_ts_dict where dict_name = $1", nsp);
|
||||||
pfree(nsp);
|
pfree(nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -245,7 +246,8 @@ lexize_byname(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
text *dictname = PG_GETARG_TEXT_P(0);
|
text *dictname = PG_GETARG_TEXT_P(0);
|
||||||
Datum res;
|
Datum res;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
|
|
||||||
res = DirectFunctionCall3(
|
res = DirectFunctionCall3(
|
||||||
lexize,
|
lexize,
|
||||||
@ -267,7 +269,7 @@ Datum set_curdict(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
set_curdict(PG_FUNCTION_ARGS)
|
set_curdict(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
finddict(PG_GETARG_OID(0));
|
finddict(PG_GETARG_OID(0));
|
||||||
currect_dictionary_id = PG_GETARG_OID(0);
|
currect_dictionary_id = PG_GETARG_OID(0);
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
@ -279,7 +281,8 @@ Datum
|
|||||||
set_curdict_byname(PG_FUNCTION_ARGS)
|
set_curdict_byname(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *dictname = PG_GETARG_TEXT_P(0);
|
text *dictname = PG_GETARG_TEXT_P(0);
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
DirectFunctionCall1(
|
DirectFunctionCall1(
|
||||||
set_curdict,
|
set_curdict,
|
||||||
ObjectIdGetDatum(name2id_dict(dictname))
|
ObjectIdGetDatum(name2id_dict(dictname))
|
||||||
@ -294,7 +297,8 @@ Datum
|
|||||||
lexize_bycurrent(PG_FUNCTION_ARGS)
|
lexize_bycurrent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum res;
|
Datum res;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (currect_dictionary_id == 0)
|
if (currect_dictionary_id == 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
|
@ -123,8 +123,8 @@ gtsvector_compress(PG_FUNCTION_ARGS)
|
|||||||
if (entry->leafkey)
|
if (entry->leafkey)
|
||||||
{ /* tsvector */
|
{ /* tsvector */
|
||||||
GISTTYPE *res;
|
GISTTYPE *res;
|
||||||
tsvector *toastedval = (tsvector *) DatumGetPointer(entry->key);
|
tsvector *toastedval = (tsvector *) DatumGetPointer(entry->key);
|
||||||
tsvector *val = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
tsvector *val = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
|
||||||
int4 len;
|
int4 len;
|
||||||
int4 *arr;
|
int4 *arr;
|
||||||
WordEntry *ptr = ARRPTR(val);
|
WordEntry *ptr = ARRPTR(val);
|
||||||
@ -277,10 +277,10 @@ gtsvector_consistent(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_BOOL(true);
|
PG_RETURN_BOOL(true);
|
||||||
|
|
||||||
PG_RETURN_BOOL(TS_execute(
|
PG_RETURN_BOOL(TS_execute(
|
||||||
GETQUERY(query),
|
GETQUERY(query),
|
||||||
(void *) GETSIGN(key), false,
|
(void *) GETSIGN(key), false,
|
||||||
checkcondition_bit
|
checkcondition_bit
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* only leaf pages */
|
{ /* only leaf pages */
|
||||||
@ -289,10 +289,10 @@ gtsvector_consistent(PG_FUNCTION_ARGS)
|
|||||||
chkval.arrb = GETARR(key);
|
chkval.arrb = GETARR(key);
|
||||||
chkval.arre = chkval.arrb + ARRNELEM(key);
|
chkval.arre = chkval.arrb + ARRNELEM(key);
|
||||||
PG_RETURN_BOOL(TS_execute(
|
PG_RETURN_BOOL(TS_execute(
|
||||||
GETQUERY(query),
|
GETQUERY(query),
|
||||||
(void *) &chkval, true,
|
(void *) &chkval, true,
|
||||||
checkcondition_arr
|
checkcondition_arr
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,10 +326,11 @@ unionkey(BITVECP sbase, GISTTYPE * add)
|
|||||||
Datum
|
Datum
|
||||||
gtsvector_union(PG_FUNCTION_ARGS)
|
gtsvector_union(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
int *size = (int *) PG_GETARG_POINTER(1);
|
int *size = (int *) PG_GETARG_POINTER(1);
|
||||||
BITVEC base;
|
BITVEC base;
|
||||||
int4 i,len;
|
int4 i,
|
||||||
|
len;
|
||||||
int4 flag = 0;
|
int4 flag = 0;
|
||||||
GISTTYPE *result;
|
GISTTYPE *result;
|
||||||
|
|
||||||
@ -418,34 +419,39 @@ sizebitvec(BITVECP sign)
|
|||||||
i;
|
i;
|
||||||
|
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
size += SUMBIT(*(char *) sign);
|
size += SUMBIT(*(char *) sign);
|
||||||
sign = (BITVECP) (((char *) sign) + 1);
|
sign = (BITVECP) (((char *) sign) + 1);
|
||||||
);
|
);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistsign(BITVECP a, BITVECP b) {
|
hemdistsign(BITVECP a, BITVECP b)
|
||||||
int i,dist=0;
|
{
|
||||||
|
int i,
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
LOOPBIT(
|
LOOPBIT(
|
||||||
if ( GETBIT(a,i) != GETBIT(b,i) )
|
if (GETBIT(a, i) != GETBIT(b, i))
|
||||||
dist++;
|
dist++;
|
||||||
);
|
);
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdist(GISTTYPE *a, GISTTYPE *b) {
|
hemdist(GISTTYPE * a, GISTTYPE * b)
|
||||||
if ( ISALLTRUE(a) ) {
|
{
|
||||||
|
if (ISALLTRUE(a))
|
||||||
|
{
|
||||||
if (ISALLTRUE(b))
|
if (ISALLTRUE(b))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(b));
|
return SIGLENBIT - sizebitvec(GETSIGN(b));
|
||||||
} else if (ISALLTRUE(b))
|
}
|
||||||
return SIGLENBIT-sizebitvec(GETSIGN(a));
|
else if (ISALLTRUE(b))
|
||||||
|
return SIGLENBIT - sizebitvec(GETSIGN(a));
|
||||||
|
|
||||||
return hemdistsign( GETSIGN(a), GETSIGN(b) );
|
return hemdistsign(GETSIGN(a), GETSIGN(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -460,17 +466,19 @@ gtsvector_penalty(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
*penalty = 0.0;
|
*penalty = 0.0;
|
||||||
|
|
||||||
if (ISARRKEY(newval)) {
|
if (ISARRKEY(newval))
|
||||||
BITVEC sign;
|
{
|
||||||
|
BITVEC sign;
|
||||||
|
|
||||||
makesign(sign, newval);
|
makesign(sign, newval);
|
||||||
|
|
||||||
if ( ISALLTRUE(origval) )
|
if (ISALLTRUE(origval))
|
||||||
*penalty=((float)(SIGLENBIT-sizebitvec(sign)))/(float)(SIGLENBIT+1);
|
*penalty = ((float) (SIGLENBIT - sizebitvec(sign))) / (float) (SIGLENBIT + 1);
|
||||||
else
|
else
|
||||||
*penalty=hemdistsign(sign,orig);
|
*penalty = hemdistsign(sign, orig);
|
||||||
} else {
|
|
||||||
*penalty=hemdist(origval,newval);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
*penalty = hemdist(origval, newval);
|
||||||
PG_RETURN_POINTER(penalty);
|
PG_RETURN_POINTER(penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,22 +518,25 @@ comparecost(const void *a, const void *b)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hemdistcache(CACHESIGN *a, CACHESIGN *b) {
|
hemdistcache(CACHESIGN * a, CACHESIGN * b)
|
||||||
if ( a->allistrue ) {
|
{
|
||||||
|
if (a->allistrue)
|
||||||
|
{
|
||||||
if (b->allistrue)
|
if (b->allistrue)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return SIGLENBIT-sizebitvec(b->sign);
|
return SIGLENBIT - sizebitvec(b->sign);
|
||||||
} else if (b->allistrue)
|
}
|
||||||
return SIGLENBIT-sizebitvec(a->sign);
|
else if (b->allistrue)
|
||||||
|
return SIGLENBIT - sizebitvec(a->sign);
|
||||||
|
|
||||||
return hemdistsign( a->sign, b->sign );
|
return hemdistsign(a->sign, b->sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gtsvector_picksplit(PG_FUNCTION_ARGS)
|
gtsvector_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
OffsetNumber k,
|
OffsetNumber k,
|
||||||
j;
|
j;
|
||||||
@ -556,13 +567,16 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
|
|||||||
cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
|
cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
|
||||||
fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
|
fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
|
||||||
|
|
||||||
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) {
|
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
|
||||||
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) {
|
{
|
||||||
|
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
|
||||||
|
{
|
||||||
if (k == FirstOffsetNumber)
|
if (k == FirstOffsetNumber)
|
||||||
fillcache(&cache[j], GETENTRY(entryvec, j));
|
fillcache(&cache[j], GETENTRY(entryvec, j));
|
||||||
|
|
||||||
size_waste=hemdistcache(&(cache[j]),&(cache[k]));
|
size_waste = hemdistcache(&(cache[j]), &(cache[k]));
|
||||||
if (size_waste > waste) {
|
if (size_waste > waste)
|
||||||
|
{
|
||||||
waste = size_waste;
|
waste = size_waste;
|
||||||
seed_1 = k;
|
seed_1 = k;
|
||||||
seed_2 = j;
|
seed_2 = j;
|
||||||
@ -575,101 +589,124 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
|
|||||||
right = v->spl_right;
|
right = v->spl_right;
|
||||||
v->spl_nright = 0;
|
v->spl_nright = 0;
|
||||||
|
|
||||||
if (seed_1 == 0 || seed_2 == 0) {
|
if (seed_1 == 0 || seed_2 == 0)
|
||||||
|
{
|
||||||
seed_1 = 1;
|
seed_1 = 1;
|
||||||
seed_2 = 2;
|
seed_2 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* form initial .. */
|
/* form initial .. */
|
||||||
if (cache[seed_1].allistrue) {
|
if (cache[seed_1].allistrue)
|
||||||
|
{
|
||||||
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
||||||
datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
||||||
datum_l->flag = SIGNKEY | ALLISTRUE;
|
datum_l->flag = SIGNKEY | ALLISTRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
||||||
datum_l->len = CALCGTSIZE(SIGNKEY, 0);
|
datum_l->len = CALCGTSIZE(SIGNKEY, 0);
|
||||||
datum_l->flag = SIGNKEY;
|
datum_l->flag = SIGNKEY;
|
||||||
memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
if (cache[seed_2].allistrue) {
|
if (cache[seed_2].allistrue)
|
||||||
|
{
|
||||||
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
|
||||||
datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
|
||||||
datum_r->flag = SIGNKEY | ALLISTRUE;
|
datum_r->flag = SIGNKEY | ALLISTRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
|
||||||
datum_r->len = CALCGTSIZE(SIGNKEY, 0);
|
datum_r->len = CALCGTSIZE(SIGNKEY, 0);
|
||||||
datum_r->flag = SIGNKEY;
|
datum_r->flag = SIGNKEY;
|
||||||
memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
|
memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
|
||||||
}
|
}
|
||||||
|
|
||||||
union_l=GETSIGN(datum_l);
|
union_l = GETSIGN(datum_l);
|
||||||
union_r=GETSIGN(datum_r);
|
union_r = GETSIGN(datum_r);
|
||||||
maxoff = OffsetNumberNext(maxoff);
|
maxoff = OffsetNumberNext(maxoff);
|
||||||
fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
|
fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
|
||||||
/* sort before ... */
|
/* sort before ... */
|
||||||
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
|
||||||
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) {
|
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
|
||||||
|
{
|
||||||
costvector[j - 1].pos = j;
|
costvector[j - 1].pos = j;
|
||||||
size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
|
size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
|
||||||
size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
|
size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
|
||||||
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
costvector[j - 1].cost = abs(size_alpha - size_beta);
|
||||||
}
|
}
|
||||||
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
|
||||||
|
|
||||||
for (k = 0; k < maxoff; k++) {
|
for (k = 0; k < maxoff; k++)
|
||||||
|
{
|
||||||
j = costvector[k].pos;
|
j = costvector[k].pos;
|
||||||
if (j == seed_1) {
|
if (j == seed_1)
|
||||||
|
{
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
continue;
|
continue;
|
||||||
} else if (j == seed_2) {
|
}
|
||||||
|
else if (j == seed_2)
|
||||||
|
{
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
v->spl_nright++;
|
v->spl_nright++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISALLTRUE(datum_l) || cache[j].allistrue) {
|
if (ISALLTRUE(datum_l) || cache[j].allistrue)
|
||||||
if ( ISALLTRUE(datum_l) && cache[j].allistrue )
|
{
|
||||||
size_alpha=0;
|
if (ISALLTRUE(datum_l) && cache[j].allistrue)
|
||||||
|
size_alpha = 0;
|
||||||
else
|
else
|
||||||
size_alpha = SIGLENBIT-sizebitvec(
|
size_alpha = SIGLENBIT - sizebitvec(
|
||||||
( cache[j].allistrue ) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign)
|
(cache[j].allistrue) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign)
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
size_alpha=hemdistsign(cache[j].sign,GETSIGN(datum_l));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));
|
||||||
|
|
||||||
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
|
if (ISALLTRUE(datum_r) || cache[j].allistrue)
|
||||||
if ( ISALLTRUE(datum_r) && cache[j].allistrue )
|
{
|
||||||
size_beta=0;
|
if (ISALLTRUE(datum_r) && cache[j].allistrue)
|
||||||
|
size_beta = 0;
|
||||||
else
|
else
|
||||||
size_beta = SIGLENBIT-sizebitvec(
|
size_beta = SIGLENBIT - sizebitvec(
|
||||||
( cache[j].allistrue ) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
|
(cache[j].allistrue) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
size_beta=hemdistsign(cache[j].sign,GETSIGN(datum_r));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r));
|
||||||
|
|
||||||
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1)) {
|
if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
|
||||||
if (ISALLTRUE(datum_l) || cache[j].allistrue) {
|
{
|
||||||
if (! ISALLTRUE(datum_l) )
|
if (ISALLTRUE(datum_l) || cache[j].allistrue)
|
||||||
|
{
|
||||||
|
if (!ISALLTRUE(datum_l))
|
||||||
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
|
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=cache[j].sign;
|
else
|
||||||
|
{
|
||||||
|
ptr = cache[j].sign;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
union_l[i] |= ptr[i];
|
union_l[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*left++ = j;
|
*left++ = j;
|
||||||
v->spl_nleft++;
|
v->spl_nleft++;
|
||||||
} else {
|
}
|
||||||
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
|
else
|
||||||
if (! ISALLTRUE(datum_r) )
|
{
|
||||||
|
if (ISALLTRUE(datum_r) || cache[j].allistrue)
|
||||||
|
{
|
||||||
|
if (!ISALLTRUE(datum_r))
|
||||||
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
|
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
|
||||||
} else {
|
}
|
||||||
ptr=cache[j].sign;
|
else
|
||||||
|
{
|
||||||
|
ptr = cache[j].sign;
|
||||||
LOOPBYTE(
|
LOOPBYTE(
|
||||||
union_r[i] |= ptr[i];
|
union_r[i] |= ptr[i];
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*right++ = j;
|
*right++ = j;
|
||||||
|
@ -7,100 +7,127 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
RS_isRegis(const char *str) {
|
RS_isRegis(const char *str)
|
||||||
unsigned char *ptr=(unsigned char *)str;
|
{
|
||||||
|
unsigned char *ptr = (unsigned char *) str;
|
||||||
|
|
||||||
while(ptr && *ptr)
|
while (ptr && *ptr)
|
||||||
if ( isalpha(*ptr) || *ptr=='[' || *ptr==']' || *ptr=='^')
|
if (isalpha(*ptr) || *ptr == '[' || *ptr == ']' || *ptr == '^')
|
||||||
ptr++;
|
ptr++;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RS_IN_ONEOF 1
|
#define RS_IN_ONEOF 1
|
||||||
#define RS_IN_ONEOF_IN 2
|
#define RS_IN_ONEOF_IN 2
|
||||||
#define RS_IN_NONEOF 3
|
#define RS_IN_NONEOF 3
|
||||||
#define RS_IN_WAIT 4
|
#define RS_IN_WAIT 4
|
||||||
|
|
||||||
static RegisNode*
|
static RegisNode *
|
||||||
newRegisNode(RegisNode *prev, int len) {
|
newRegisNode(RegisNode * prev, int len)
|
||||||
RegisNode *ptr;
|
{
|
||||||
ptr = (RegisNode*)malloc(RNHDRSZ+len+1);
|
RegisNode *ptr;
|
||||||
|
|
||||||
|
ptr = (RegisNode *) malloc(RNHDRSZ + len + 1);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
ts_error(ERROR, "No memory");
|
ts_error(ERROR, "No memory");
|
||||||
memset(ptr,0,RNHDRSZ+len+1);
|
memset(ptr, 0, RNHDRSZ + len + 1);
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next=ptr;
|
prev->next = ptr;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RS_compile(Regis *r, int issuffix, const char *str) {
|
RS_compile(Regis * r, int issuffix, const char *str)
|
||||||
int i,len = strlen(str);
|
{
|
||||||
int state = RS_IN_WAIT;
|
int i,
|
||||||
RegisNode *ptr=NULL;
|
len = strlen(str);
|
||||||
|
int state = RS_IN_WAIT;
|
||||||
|
RegisNode *ptr = NULL;
|
||||||
|
|
||||||
memset(r,0,sizeof(Regis));
|
memset(r, 0, sizeof(Regis));
|
||||||
r->issuffix = (issuffix) ? 1 : 0;
|
r->issuffix = (issuffix) ? 1 : 0;
|
||||||
|
|
||||||
for(i=0;i<len;i++) {
|
for (i = 0; i < len; i++)
|
||||||
unsigned char c = *( ( (unsigned char*)str ) + i );
|
{
|
||||||
if ( state == RS_IN_WAIT ) {
|
unsigned char c = *(((unsigned char *) str) + i);
|
||||||
if ( isalpha(c) ) {
|
|
||||||
if ( ptr )
|
if (state == RS_IN_WAIT)
|
||||||
ptr = newRegisNode(ptr,len);
|
{
|
||||||
|
if (isalpha(c))
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
ptr = newRegisNode(ptr, len);
|
||||||
else
|
else
|
||||||
ptr = r->node = newRegisNode(NULL,len);
|
ptr = r->node = newRegisNode(NULL, len);
|
||||||
ptr->data[ 0 ] = c;
|
ptr->data[0] = c;
|
||||||
ptr->type = RSF_ONEOF;
|
ptr->type = RSF_ONEOF;
|
||||||
ptr->len=1;
|
ptr->len = 1;
|
||||||
} else if ( c=='[' ) {
|
}
|
||||||
if ( ptr )
|
else if (c == '[')
|
||||||
ptr = newRegisNode(ptr,len);
|
{
|
||||||
|
if (ptr)
|
||||||
|
ptr = newRegisNode(ptr, len);
|
||||||
else
|
else
|
||||||
ptr = r->node = newRegisNode(NULL,len);
|
ptr = r->node = newRegisNode(NULL, len);
|
||||||
ptr->type = RSF_ONEOF;
|
ptr->type = RSF_ONEOF;
|
||||||
state=RS_IN_ONEOF;
|
state = RS_IN_ONEOF;
|
||||||
} else
|
}
|
||||||
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
else
|
||||||
} else if ( state == RS_IN_ONEOF ) {
|
ts_error(ERROR, "Error in regis: %s at pos %d\n", str, i + 1);
|
||||||
if ( c=='^' ) {
|
}
|
||||||
|
else if (state == RS_IN_ONEOF)
|
||||||
|
{
|
||||||
|
if (c == '^')
|
||||||
|
{
|
||||||
ptr->type = RSF_NONEOF;
|
ptr->type = RSF_NONEOF;
|
||||||
state=RS_IN_NONEOF;
|
state = RS_IN_NONEOF;
|
||||||
} else if ( isalpha(c) ) {
|
}
|
||||||
ptr->data[ 0 ] = c;
|
else if (isalpha(c))
|
||||||
ptr->len=1;
|
{
|
||||||
state=RS_IN_ONEOF_IN;
|
ptr->data[0] = c;
|
||||||
} else
|
ptr->len = 1;
|
||||||
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
state = RS_IN_ONEOF_IN;
|
||||||
} else if ( state == RS_IN_ONEOF_IN || state == RS_IN_NONEOF ) {
|
}
|
||||||
if ( isalpha(c) ) {
|
else
|
||||||
ptr->data[ ptr->len ] = c;
|
ts_error(ERROR, "Error in regis: %s at pos %d\n", str, i + 1);
|
||||||
|
}
|
||||||
|
else if (state == RS_IN_ONEOF_IN || state == RS_IN_NONEOF)
|
||||||
|
{
|
||||||
|
if (isalpha(c))
|
||||||
|
{
|
||||||
|
ptr->data[ptr->len] = c;
|
||||||
ptr->len++;
|
ptr->len++;
|
||||||
} else if ( c==']' ) {
|
}
|
||||||
state=RS_IN_WAIT;
|
else if (c == ']')
|
||||||
} else
|
state = RS_IN_WAIT;
|
||||||
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
else
|
||||||
} else
|
ts_error(ERROR, "Error in regis: %s at pos %d\n", str, i + 1);
|
||||||
ts_error(ERROR,"Internal error in RS_compile: %d\n", state);
|
}
|
||||||
|
else
|
||||||
|
ts_error(ERROR, "Internal error in RS_compile: %d\n", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = r->node;
|
ptr = r->node;
|
||||||
while(ptr) {
|
while (ptr)
|
||||||
|
{
|
||||||
r->nchar++;
|
r->nchar++;
|
||||||
ptr=ptr->next;
|
ptr = ptr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RS_free(Regis *r) {
|
RS_free(Regis * r)
|
||||||
RegisNode *ptr=r->node,*tmp;
|
{
|
||||||
|
RegisNode *ptr = r->node,
|
||||||
|
*tmp;
|
||||||
|
|
||||||
while(ptr) {
|
while (ptr)
|
||||||
tmp=ptr->next;
|
{
|
||||||
|
tmp = ptr->next;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
ptr = tmp;
|
ptr = tmp;
|
||||||
}
|
}
|
||||||
@ -109,41 +136,48 @@ RS_free(Regis *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RS_execute(Regis *r, const char *str, int len) {
|
RS_execute(Regis * r, const char *str, int len)
|
||||||
RegisNode *ptr=r->node;
|
{
|
||||||
|
RegisNode *ptr = r->node;
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
|
|
||||||
if (len<0)
|
if (len < 0)
|
||||||
len=strlen(str);
|
len = strlen(str);
|
||||||
|
|
||||||
if (len<r->nchar)
|
if (len < r->nchar)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ( r->issuffix )
|
if (r->issuffix)
|
||||||
c = ((unsigned char*)str) + len - r->nchar;
|
c = ((unsigned char *) str) + len - r->nchar;
|
||||||
else
|
else
|
||||||
c = (unsigned char*)str;
|
c = (unsigned char *) str;
|
||||||
|
|
||||||
while(ptr) {
|
while (ptr)
|
||||||
switch(ptr->type) {
|
{
|
||||||
|
switch (ptr->type)
|
||||||
|
{
|
||||||
case RSF_ONEOF:
|
case RSF_ONEOF:
|
||||||
if ( ptr->len==0 ) {
|
if (ptr->len == 0)
|
||||||
if ( *c != *(ptr->data) )
|
{
|
||||||
|
if (*c != *(ptr->data))
|
||||||
return 0;
|
return 0;
|
||||||
} else if ( strchr((char*)ptr->data, *c) == NULL )
|
}
|
||||||
|
else if (strchr((char *) ptr->data, *c) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case RSF_NONEOF:
|
case RSF_NONEOF:
|
||||||
if ( ptr->len==0 ) {
|
if (ptr->len == 0)
|
||||||
if ( *c == *(ptr->data) )
|
{
|
||||||
|
if (*c == *(ptr->data))
|
||||||
return 0;
|
return 0;
|
||||||
} else if ( strchr((char*)ptr->data, *c) != NULL )
|
}
|
||||||
|
else if (strchr((char *) ptr->data, *c) != NULL)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ts_error(ERROR,"RS_execute: Unknown type node: %d\n", ptr->type);
|
ts_error(ERROR, "RS_execute: Unknown type node: %d\n", ptr->type);
|
||||||
}
|
}
|
||||||
ptr=ptr->next;
|
ptr = ptr->next;
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,32 +3,36 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
typedef struct RegisNode {
|
typedef struct RegisNode
|
||||||
|
{
|
||||||
uint32
|
uint32
|
||||||
type:2,
|
type:2,
|
||||||
len:16,
|
len:16,
|
||||||
unused:14;
|
unused:14;
|
||||||
struct RegisNode *next;
|
struct RegisNode *next;
|
||||||
unsigned char data[1];
|
unsigned char data[1];
|
||||||
} RegisNode;
|
} RegisNode;
|
||||||
|
|
||||||
#define RNHDRSZ (sizeof(uint32)+sizeof(void*))
|
#define RNHDRSZ (sizeof(uint32)+sizeof(void*))
|
||||||
|
|
||||||
#define RSF_ONEOF 1
|
#define RSF_ONEOF 1
|
||||||
#define RSF_NONEOF 2
|
#define RSF_NONEOF 2
|
||||||
|
|
||||||
typedef struct Regis {
|
typedef struct Regis
|
||||||
RegisNode *node;
|
{
|
||||||
|
RegisNode *node;
|
||||||
uint32
|
uint32
|
||||||
issuffix:1,
|
issuffix:1,
|
||||||
nchar:16,
|
nchar:16,
|
||||||
unused:15;
|
unused:15;
|
||||||
} Regis;
|
} Regis;
|
||||||
|
|
||||||
int RS_isRegis(const char *str);
|
int RS_isRegis(const char *str);
|
||||||
|
|
||||||
|
int RS_compile(Regis * r, int issuffix, const char *str);
|
||||||
|
void RS_free(Regis * r);
|
||||||
|
|
||||||
int RS_compile(Regis *r, int issuffix, const char *str);
|
|
||||||
void RS_free(Regis *r);
|
|
||||||
/*×ÏÚ×ÒÁÝÁÅÔ 1 ÅÓÌÉ ÍÁÔÞÉÔÓÑ */
|
/*×ÏÚ×ÒÁÝÁÅÔ 1 ÅÓÌÉ ÍÁÔÞÉÔÓÑ */
|
||||||
int RS_execute(Regis *r, const char *str, int len);
|
int RS_execute(Regis * r, const char *str, int len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,19 +10,21 @@
|
|||||||
struct SPNode;
|
struct SPNode;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
uint32
|
uint32
|
||||||
val:8,
|
val:8,
|
||||||
isword:1,
|
isword:1,
|
||||||
compoundallow:1,
|
compoundallow:1,
|
||||||
affix:22;
|
affix:22;
|
||||||
struct SPNode *node;
|
struct SPNode *node;
|
||||||
} SPNodeData;
|
} SPNodeData;
|
||||||
|
|
||||||
typedef struct SPNode {
|
typedef struct SPNode
|
||||||
uint32 length;
|
{
|
||||||
|
uint32 length;
|
||||||
SPNodeData data[1];
|
SPNodeData data[1];
|
||||||
} SPNode;
|
} SPNode;
|
||||||
|
|
||||||
#define SPNHRDSZ (sizeof(uint32))
|
#define SPNHRDSZ (sizeof(uint32))
|
||||||
|
|
||||||
@ -30,81 +32,87 @@ typedef struct SPNode {
|
|||||||
typedef struct spell_struct
|
typedef struct spell_struct
|
||||||
{
|
{
|
||||||
char *word;
|
char *word;
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
char flag[16];
|
char flag[16];
|
||||||
struct {
|
struct
|
||||||
int affix;
|
{
|
||||||
int len;
|
int affix;
|
||||||
} d;
|
int len;
|
||||||
} p;
|
} d;
|
||||||
|
} p;
|
||||||
} SPELL;
|
} SPELL;
|
||||||
|
|
||||||
typedef struct aff_struct
|
typedef struct aff_struct
|
||||||
{
|
{
|
||||||
uint32
|
uint32
|
||||||
flag:8,
|
flag:8,
|
||||||
type:2,
|
type:2,
|
||||||
compile:1,
|
compile:1,
|
||||||
flagflags:3,
|
flagflags:3,
|
||||||
issimple:1,
|
issimple:1,
|
||||||
isregis:1,
|
isregis:1,
|
||||||
unused:1,
|
unused:1,
|
||||||
replen:16;
|
replen:16;
|
||||||
char mask[32];
|
char mask[32];
|
||||||
char find[16];
|
char find[16];
|
||||||
char repl[16];
|
char repl[16];
|
||||||
union {
|
union
|
||||||
regex_t regex;
|
{
|
||||||
Regis regis;
|
regex_t regex;
|
||||||
} reg;
|
Regis regis;
|
||||||
|
} reg;
|
||||||
} AFFIX;
|
} AFFIX;
|
||||||
|
|
||||||
#define FF_CROSSPRODUCT 0x01
|
#define FF_CROSSPRODUCT 0x01
|
||||||
#define FF_COMPOUNDWORD 0x02
|
#define FF_COMPOUNDWORD 0x02
|
||||||
#define FF_COMPOUNDONLYAFX 0x04
|
#define FF_COMPOUNDONLYAFX 0x04
|
||||||
#define FF_SUFFIX 2
|
#define FF_SUFFIX 2
|
||||||
#define FF_PREFIX 1
|
#define FF_PREFIX 1
|
||||||
|
|
||||||
struct AffixNode;
|
struct AffixNode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
uint32
|
uint32
|
||||||
val:8,
|
val:8,
|
||||||
naff:24;
|
naff:24;
|
||||||
AFFIX **aff;
|
AFFIX **aff;
|
||||||
struct AffixNode *node;
|
struct AffixNode *node;
|
||||||
} AffixNodeData;
|
} AffixNodeData;
|
||||||
|
|
||||||
typedef struct AffixNode {
|
typedef struct AffixNode
|
||||||
uint32 isvoid:1,
|
{
|
||||||
length:31;
|
uint32 isvoid:1,
|
||||||
AffixNodeData data[1];
|
length:31;
|
||||||
} AffixNode;
|
AffixNodeData data[1];
|
||||||
|
} AffixNode;
|
||||||
|
|
||||||
#define ANHRDSZ (sizeof(uint32))
|
#define ANHRDSZ (sizeof(uint32))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
char *affix;
|
{
|
||||||
int len;
|
char *affix;
|
||||||
} CMPDAffix;
|
int len;
|
||||||
|
} CMPDAffix;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int maffixes;
|
int maffixes;
|
||||||
int naffixes;
|
int naffixes;
|
||||||
AFFIX *Affix;
|
AFFIX *Affix;
|
||||||
char compoundcontrol;
|
char compoundcontrol;
|
||||||
|
|
||||||
int nspell;
|
int nspell;
|
||||||
int mspell;
|
int mspell;
|
||||||
SPELL *Spell;
|
SPELL *Spell;
|
||||||
|
|
||||||
AffixNode *Suffix;
|
AffixNode *Suffix;
|
||||||
AffixNode *Prefix;
|
AffixNode *Prefix;
|
||||||
|
|
||||||
SPNode *Dictionary;
|
SPNode *Dictionary;
|
||||||
char **AffixData;
|
char **AffixData;
|
||||||
CMPDAffix *CompoundAffix;
|
CMPDAffix *CompoundAffix;
|
||||||
|
|
||||||
} IspellDict;
|
} IspellDict;
|
||||||
|
|
||||||
|
@ -469,7 +469,7 @@ TS_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *
|
|||||||
Datum
|
Datum
|
||||||
rexectsq(PG_FUNCTION_ARGS)
|
rexectsq(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
return DirectFunctionCall2(
|
return DirectFunctionCall2(
|
||||||
exectsq,
|
exectsq,
|
||||||
PG_GETARG_DATUM(1),
|
PG_GETARG_DATUM(1),
|
||||||
@ -484,7 +484,8 @@ exectsq(PG_FUNCTION_ARGS)
|
|||||||
QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
|
QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
|
||||||
CHKVAL chkval;
|
CHKVAL chkval;
|
||||||
bool result;
|
bool result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (!val->size || !query->size)
|
if (!val->size || !query->size)
|
||||||
{
|
{
|
||||||
PG_FREE_IF_COPY(val, 0);
|
PG_FREE_IF_COPY(val, 0);
|
||||||
@ -639,7 +640,7 @@ static QUERYTYPE *
|
|||||||
Datum
|
Datum
|
||||||
tsquery_in(PG_FUNCTION_ARGS)
|
tsquery_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0), pushval_asis, 0));
|
PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0), pushval_asis, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +866,8 @@ to_tsquery(PG_FUNCTION_ARGS)
|
|||||||
QUERYTYPE *query;
|
QUERYTYPE *query;
|
||||||
ITEM *res;
|
ITEM *res;
|
||||||
int4 len;
|
int4 len;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
|
|
||||||
str = text2char(in);
|
str = text2char(in);
|
||||||
PG_FREE_IF_COPY(in, 1);
|
PG_FREE_IF_COPY(in, 1);
|
||||||
@ -888,10 +890,11 @@ to_tsquery_name(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
text *name = PG_GETARG_TEXT_P(0);
|
text *name = PG_GETARG_TEXT_P(0);
|
||||||
Datum res;
|
Datum res;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
res = DirectFunctionCall2(to_tsquery,
|
res = DirectFunctionCall2(to_tsquery,
|
||||||
Int32GetDatum(name2id_cfg(name)),
|
Int32GetDatum(name2id_cfg(name)),
|
||||||
PG_GETARG_DATUM(1));
|
PG_GETARG_DATUM(1));
|
||||||
|
|
||||||
PG_FREE_IF_COPY(name, 0);
|
PG_FREE_IF_COPY(name, 0);
|
||||||
PG_RETURN_DATUM(res);
|
PG_RETURN_DATUM(res);
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
static int
|
static int
|
||||||
compareSNMapEntry(const void *a, const void *b)
|
compareSNMapEntry(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
if ( ((SNMapEntry *) a)->nsp < ((SNMapEntry *) b)->nsp )
|
if (((SNMapEntry *) a)->nsp < ((SNMapEntry *) b)->nsp)
|
||||||
return -1;
|
return -1;
|
||||||
else if ( ((SNMapEntry *) a)->nsp > ((SNMapEntry *) b)->nsp )
|
else if (((SNMapEntry *) a)->nsp > ((SNMapEntry *) b)->nsp)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return strcmp(((SNMapEntry *) a)->key, ((SNMapEntry *) b)->key);
|
return strcmp(((SNMapEntry *) a)->key, ((SNMapEntry *) b)->key);
|
||||||
|
@ -38,10 +38,10 @@ init_cfg(Oid id, TSCfgInfo * cfg)
|
|||||||
j;
|
j;
|
||||||
text *ptr;
|
text *ptr;
|
||||||
text *prsname = NULL;
|
text *prsname = NULL;
|
||||||
char *nsp=get_namespace(TSNSP_FunctionOid);
|
char *nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
void *plan;
|
void *plan;
|
||||||
|
|
||||||
arg[0] = OIDOID;
|
arg[0] = OIDOID;
|
||||||
arg[1] = OIDOID;
|
arg[1] = OIDOID;
|
||||||
@ -52,7 +52,7 @@ init_cfg(Oid id, TSCfgInfo * cfg)
|
|||||||
SPI_connect();
|
SPI_connect();
|
||||||
|
|
||||||
sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp);
|
sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ init_cfg(Oid id, TSCfgInfo * cfg)
|
|||||||
|
|
||||||
arg[0] = TEXTOID;
|
arg[0] = TEXTOID;
|
||||||
sprintf(buf, "select lt.tokid, map.dict_name from %s.pg_ts_cfgmap as map, %s.pg_ts_cfg as cfg, %s.token_type( $1 ) as lt where lt.alias = map.tok_alias and map.ts_name = cfg.ts_name and cfg.oid= $2 order by lt.tokid desc;", nsp, nsp, nsp);
|
sprintf(buf, "select lt.tokid, map.dict_name from %s.pg_ts_cfgmap as map, %s.pg_ts_cfg as cfg, %s.token_type( $1 ) as lt where lt.alias = map.tok_alias and map.ts_name = cfg.ts_name and cfg.oid= $2 order by lt.tokid desc;", nsp, nsp, nsp);
|
||||||
plan= SPI_prepare(buf, 2, arg);
|
plan = SPI_prepare(buf, 2, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ init_cfg(Oid id, TSCfgInfo * cfg)
|
|||||||
cfg->map[lexid].len = ARRNELEMS(a);
|
cfg->map[lexid].len = ARRNELEMS(a);
|
||||||
cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len);
|
cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len);
|
||||||
if (!cfg->map[lexid].dict_id)
|
if (!cfg->map[lexid].dict_id)
|
||||||
ts_error(ERROR, "No memory");
|
ts_error(ERROR, "No memory");
|
||||||
|
|
||||||
memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len);
|
memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len);
|
||||||
ptr = (text *) ARR_DATA_PTR(a);
|
ptr = (text *) ARR_DATA_PTR(a);
|
||||||
@ -235,9 +235,9 @@ name2id_cfg(text *name)
|
|||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
int stat;
|
int stat;
|
||||||
Oid id = findSNMap_t(&(CList.name2id_map), name);
|
Oid id = findSNMap_t(&(CList.name2id_map), name);
|
||||||
void *plan;
|
void *plan;
|
||||||
char *nsp;
|
char *nsp;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
arg[0] = TEXTOID;
|
arg[0] = TEXTOID;
|
||||||
pars[0] = PointerGetDatum(name);
|
pars[0] = PointerGetDatum(name);
|
||||||
@ -245,10 +245,10 @@ name2id_cfg(text *name)
|
|||||||
if (id)
|
if (id)
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
nsp=get_namespace(TSNSP_FunctionOid);
|
nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
sprintf(buf, "select oid from %s.pg_ts_cfg where ts_name = $1", nsp);
|
sprintf(buf, "select oid from %s.pg_ts_cfg where ts_name = $1", nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
/* internal error */
|
/* internal error */
|
||||||
elog(ERROR, "SPI_prepare() failed");
|
elog(ERROR, "SPI_prepare() failed");
|
||||||
@ -301,7 +301,8 @@ parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen)
|
|||||||
PointerGetDatum(&lenlemm)))) != 0)
|
PointerGetDatum(&lenlemm)))) != 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (lenlemm >= MAXSTRLEN) {
|
if (lenlemm >= MAXSTRLEN)
|
||||||
|
{
|
||||||
#ifdef IGNORE_LONGLEXEME
|
#ifdef IGNORE_LONGLEXEME
|
||||||
ereport(NOTICE,
|
ereport(NOTICE,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
@ -435,7 +436,8 @@ hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4
|
|||||||
PointerGetDatum(&lenlemm)))) != 0)
|
PointerGetDatum(&lenlemm)))) != 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (lenlemm >= MAXSTRLEN) {
|
if (lenlemm >= MAXSTRLEN)
|
||||||
|
{
|
||||||
#ifdef IGNORE_LONGLEXEME
|
#ifdef IGNORE_LONGLEXEME
|
||||||
ereport(NOTICE,
|
ereport(NOTICE,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
@ -532,9 +534,8 @@ genhl(HLPRSTEXT * prs)
|
|||||||
ptr += prs->stopsellen;
|
ptr += prs->stopsellen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else if (!wrd->repeated)
|
||||||
if (!wrd->repeated)
|
|
||||||
pfree(wrd->word);
|
pfree(wrd->word);
|
||||||
|
|
||||||
wrd++;
|
wrd++;
|
||||||
@ -552,16 +553,16 @@ get_currcfg(void)
|
|||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
bool isnull;
|
bool isnull;
|
||||||
int stat;
|
int stat;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *nsp;
|
char *nsp;
|
||||||
void *plan;
|
void *plan;
|
||||||
|
|
||||||
if (current_cfg_id > 0)
|
if (current_cfg_id > 0)
|
||||||
return current_cfg_id;
|
return current_cfg_id;
|
||||||
|
|
||||||
nsp=get_namespace(TSNSP_FunctionOid);
|
nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
sprintf(buf, "select oid from %s.pg_ts_cfg where locale = $1 ", nsp);
|
sprintf(buf, "select oid from %s.pg_ts_cfg where locale = $1 ", nsp);
|
||||||
pfree(nsp);
|
pfree(nsp);
|
||||||
plan = SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
@ -593,7 +594,7 @@ Datum set_curcfg(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
set_curcfg(PG_FUNCTION_ARGS)
|
set_curcfg(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
findcfg(PG_GETARG_OID(0));
|
findcfg(PG_GETARG_OID(0));
|
||||||
current_cfg_id = PG_GETARG_OID(0);
|
current_cfg_id = PG_GETARG_OID(0);
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
@ -605,7 +606,8 @@ Datum
|
|||||||
set_curcfg_byname(PG_FUNCTION_ARGS)
|
set_curcfg_byname(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *name = PG_GETARG_TEXT_P(0);
|
text *name = PG_GETARG_TEXT_P(0);
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
DirectFunctionCall1(
|
DirectFunctionCall1(
|
||||||
set_curcfg,
|
set_curcfg,
|
||||||
ObjectIdGetDatum(name2id_cfg(name))
|
ObjectIdGetDatum(name2id_cfg(name))
|
||||||
@ -619,7 +621,7 @@ Datum show_curcfg(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
show_curcfg(PG_FUNCTION_ARGS)
|
show_curcfg(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
PG_RETURN_OID(get_currcfg());
|
PG_RETURN_OID(get_currcfg());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,8 +630,7 @@ Datum reset_tsearch(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
reset_tsearch(PG_FUNCTION_ARGS)
|
reset_tsearch(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
ts_error(NOTICE, "TSearch cache cleaned");
|
ts_error(NOTICE, "TSearch cache cleaned");
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,12 +34,14 @@ tsstat_out(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_weight(tsvector *txt, WordEntry *wptr, int8 weight) {
|
check_weight(tsvector * txt, WordEntry * wptr, int8 weight)
|
||||||
int len = POSDATALEN(txt, wptr);
|
{
|
||||||
int num=0;
|
int len = POSDATALEN(txt, wptr);
|
||||||
WordEntryPos *ptr = POSDATAPTR(txt, wptr);
|
int num = 0;
|
||||||
|
WordEntryPos *ptr = POSDATAPTR(txt, wptr);
|
||||||
|
|
||||||
while (len--) {
|
while (len--)
|
||||||
|
{
|
||||||
if (weight & (1 << ptr->weight))
|
if (weight & (1 << ptr->weight))
|
||||||
num++;
|
num++;
|
||||||
ptr++;
|
ptr++;
|
||||||
@ -123,9 +125,9 @@ formstat(tsstat * stat, tsvector * txt, WordEntry ** entry, uint32 len)
|
|||||||
}
|
}
|
||||||
nptr = STATPTR(newstat) + (StopLow - STATPTR(stat));
|
nptr = STATPTR(newstat) + (StopLow - STATPTR(stat));
|
||||||
memcpy(STATPTR(newstat), STATPTR(stat), sizeof(StatEntry) * (StopLow - STATPTR(stat)));
|
memcpy(STATPTR(newstat), STATPTR(stat), sizeof(StatEntry) * (StopLow - STATPTR(stat)));
|
||||||
if ( (*ptr)->haspos ) {
|
if ((*ptr)->haspos)
|
||||||
nptr->nentry = ( stat->weight ) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
nptr->nentry = (stat->weight) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
||||||
} else
|
else
|
||||||
nptr->nentry = 1;
|
nptr->nentry = 1;
|
||||||
nptr->ndoc = 1;
|
nptr->ndoc = 1;
|
||||||
nptr->len = (*ptr)->len;
|
nptr->len = (*ptr)->len;
|
||||||
@ -144,9 +146,9 @@ formstat(tsstat * stat, tsvector * txt, WordEntry ** entry, uint32 len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( (*ptr)->haspos ) {
|
if ((*ptr)->haspos)
|
||||||
nptr->nentry = ( stat->weight ) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
nptr->nentry = (stat->weight) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
||||||
} else
|
else
|
||||||
nptr->nentry = 1;
|
nptr->nentry = 1;
|
||||||
nptr->ndoc = 1;
|
nptr->ndoc = 1;
|
||||||
nptr->len = (*ptr)->len;
|
nptr->len = (*ptr)->len;
|
||||||
@ -162,9 +164,9 @@ formstat(tsstat * stat, tsvector * txt, WordEntry ** entry, uint32 len)
|
|||||||
|
|
||||||
while (ptr - entry < len)
|
while (ptr - entry < len)
|
||||||
{
|
{
|
||||||
if ( (*ptr)->haspos ) {
|
if ((*ptr)->haspos)
|
||||||
nptr->nentry = ( stat->weight ) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
nptr->nentry = (stat->weight) ? check_weight(txt, *ptr, stat->weight) : POSDATALEN(txt, *ptr);
|
||||||
} else
|
else
|
||||||
nptr->nentry = 1;
|
nptr->nentry = 1;
|
||||||
nptr->ndoc = 1;
|
nptr->ndoc = 1;
|
||||||
nptr->len = (*ptr)->len;
|
nptr->len = (*ptr)->len;
|
||||||
@ -192,7 +194,7 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
cur = 0;
|
cur = 0;
|
||||||
StatEntry *sptr;
|
StatEntry *sptr;
|
||||||
WordEntry *wptr;
|
WordEntry *wptr;
|
||||||
int n=0;
|
int n = 0;
|
||||||
|
|
||||||
if (stat == NULL || PG_ARGISNULL(0))
|
if (stat == NULL || PG_ARGISNULL(0))
|
||||||
{ /* Init in first */
|
{ /* Init in first */
|
||||||
@ -222,10 +224,13 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
sptr++;
|
sptr++;
|
||||||
else if (cmp == 0)
|
else if (cmp == 0)
|
||||||
{
|
{
|
||||||
if ( stat->weight == 0 ) {
|
if (stat->weight == 0)
|
||||||
|
{
|
||||||
sptr->ndoc++;
|
sptr->ndoc++;
|
||||||
sptr->nentry += (wptr->haspos) ? POSDATALEN(txt, wptr) : 1;
|
sptr->nentry += (wptr->haspos) ? POSDATALEN(txt, wptr) : 1;
|
||||||
} else if ( wptr->haspos && (n=check_weight(txt, wptr, stat->weight))!=0 ) {
|
}
|
||||||
|
else if (wptr->haspos && (n = check_weight(txt, wptr, stat->weight)) != 0)
|
||||||
|
{
|
||||||
sptr->ndoc++;
|
sptr->ndoc++;
|
||||||
sptr->nentry += n;
|
sptr->nentry += n;
|
||||||
}
|
}
|
||||||
@ -234,7 +239,8 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( stat->weight == 0 || check_weight(txt, wptr, stat->weight)!=0 ) {
|
if (stat->weight == 0 || check_weight(txt, wptr, stat->weight) != 0)
|
||||||
|
{
|
||||||
if (cur == len)
|
if (cur == len)
|
||||||
newentry = SEI_realloc(newentry, &len);
|
newentry = SEI_realloc(newentry, &len);
|
||||||
newentry[cur] = wptr;
|
newentry[cur] = wptr;
|
||||||
@ -246,7 +252,8 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
while (wptr - ARRPTR(txt) < txt->size)
|
while (wptr - ARRPTR(txt) < txt->size)
|
||||||
{
|
{
|
||||||
if ( stat->weight == 0 || check_weight(txt, wptr, stat->weight)!=0 ) {
|
if (stat->weight == 0 || check_weight(txt, wptr, stat->weight) != 0)
|
||||||
|
{
|
||||||
if (cur == len)
|
if (cur == len)
|
||||||
newentry = SEI_realloc(newentry, &len);
|
newentry = SEI_realloc(newentry, &len);
|
||||||
newentry[cur] = wptr;
|
newentry[cur] = wptr;
|
||||||
@ -269,10 +276,13 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
cmp = compareStatWord(sptr, wptr, stat, txt);
|
cmp = compareStatWord(sptr, wptr, stat, txt);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
if ( stat->weight == 0 ) {
|
if (stat->weight == 0)
|
||||||
|
{
|
||||||
sptr->ndoc++;
|
sptr->ndoc++;
|
||||||
sptr->nentry += (wptr->haspos) ? POSDATALEN(txt, wptr) : 1;
|
sptr->nentry += (wptr->haspos) ? POSDATALEN(txt, wptr) : 1;
|
||||||
} else if ( wptr->haspos && (n=check_weight(txt, wptr, stat->weight))!=0 ) {
|
}
|
||||||
|
else if (wptr->haspos && (n = check_weight(txt, wptr, stat->weight)) != 0)
|
||||||
|
{
|
||||||
sptr->ndoc++;
|
sptr->ndoc++;
|
||||||
sptr->nentry += n;
|
sptr->nentry += n;
|
||||||
}
|
}
|
||||||
@ -286,7 +296,8 @@ ts_accum(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (StopLow >= StopHigh)
|
if (StopLow >= StopHigh)
|
||||||
{ /* not found */
|
{ /* not found */
|
||||||
if ( stat->weight == 0 || check_weight(txt, wptr, stat->weight)!=0 ) {
|
if (stat->weight == 0 || check_weight(txt, wptr, stat->weight) != 0)
|
||||||
|
{
|
||||||
if (cur == len)
|
if (cur == len)
|
||||||
newentry = SEI_realloc(newentry, &len);
|
newentry = SEI_realloc(newentry, &len);
|
||||||
newentry[cur] = wptr;
|
newentry[cur] = wptr;
|
||||||
@ -454,11 +465,15 @@ ts_stat_sql(text *txt, text *ws)
|
|||||||
stat->size = 0;
|
stat->size = 0;
|
||||||
stat->weight = 0;
|
stat->weight = 0;
|
||||||
|
|
||||||
if ( ws ) {
|
if (ws)
|
||||||
char *buf;
|
{
|
||||||
|
char *buf;
|
||||||
|
|
||||||
buf = VARDATA(ws);
|
buf = VARDATA(ws);
|
||||||
while( buf - VARDATA(ws) < VARSIZE(ws) - VARHDRSZ ) {
|
while (buf - VARDATA(ws) < VARSIZE(ws) - VARHDRSZ)
|
||||||
switch (tolower(*buf)) {
|
{
|
||||||
|
switch (tolower(*buf))
|
||||||
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
stat->weight |= 1 << 3;
|
stat->weight |= 1 << 3;
|
||||||
break;
|
break;
|
||||||
@ -521,13 +536,14 @@ ts_stat(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
tsstat *stat;
|
tsstat *stat;
|
||||||
text *txt = PG_GETARG_TEXT_P(0);
|
text *txt = PG_GETARG_TEXT_P(0);
|
||||||
text *ws = (PG_NARGS() > 1) ? PG_GETARG_TEXT_P(1) : NULL;
|
text *ws = (PG_NARGS() > 1) ? PG_GETARG_TEXT_P(1) : NULL;
|
||||||
|
|
||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
stat = ts_stat_sql(txt,ws);
|
stat = ts_stat_sql(txt, ws);
|
||||||
PG_FREE_IF_COPY(txt, 0);
|
PG_FREE_IF_COPY(txt, 0);
|
||||||
if (PG_NARGS() > 1 ) PG_FREE_IF_COPY(ws, 1);
|
if (PG_NARGS() > 1)
|
||||||
|
PG_FREE_IF_COPY(ws, 1);
|
||||||
ts_setup_firstcall(funcctx, stat);
|
ts_setup_firstcall(funcctx, stat);
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,8 @@ tsvector_in(PG_FUNCTION_ARGS)
|
|||||||
*cur;
|
*cur;
|
||||||
int4 i,
|
int4 i,
|
||||||
buflen = 256;
|
buflen = 256;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
state.prsbuf = buf;
|
state.prsbuf = buf;
|
||||||
state.len = 32;
|
state.len = 32;
|
||||||
state.word = (char *) palloc(state.len);
|
state.word = (char *) palloc(state.len);
|
||||||
@ -453,7 +454,7 @@ tsvector_in(PG_FUNCTION_ARGS)
|
|||||||
if (len > 0)
|
if (len > 0)
|
||||||
len = uniqueentry(arr, len, tmpbuf, &buflen);
|
len = uniqueentry(arr, len, tmpbuf, &buflen);
|
||||||
else
|
else
|
||||||
buflen=0;
|
buflen = 0;
|
||||||
totallen = CALCDATASIZE(len, buflen);
|
totallen = CALCDATASIZE(len, buflen);
|
||||||
in = (tsvector *) palloc(totallen);
|
in = (tsvector *) palloc(totallen);
|
||||||
memset(in, 0, totallen);
|
memset(in, 0, totallen);
|
||||||
@ -638,7 +639,8 @@ uniqueWORD(TSWORD * a, int4 l)
|
|||||||
res->alen *= 2;
|
res->alen *= 2;
|
||||||
res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
|
res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
|
||||||
}
|
}
|
||||||
if ( res->pos.apos[0]==0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos) ) {
|
if (res->pos.apos[0] == 0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
|
||||||
|
{
|
||||||
res->pos.apos[res->pos.apos[0] + 1] = LIMITPOS(ptr->pos.pos);
|
res->pos.apos[res->pos.apos[0] + 1] = LIMITPOS(ptr->pos.pos);
|
||||||
res->pos.apos[0]++;
|
res->pos.apos[0]++;
|
||||||
}
|
}
|
||||||
@ -725,7 +727,7 @@ to_tsvector(PG_FUNCTION_ARGS)
|
|||||||
tsvector *out = NULL;
|
tsvector *out = NULL;
|
||||||
TSCfgInfo *cfg;
|
TSCfgInfo *cfg;
|
||||||
|
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
cfg = findcfg(PG_GETARG_INT32(0));
|
cfg = findcfg(PG_GETARG_INT32(0));
|
||||||
|
|
||||||
prs.lenwords = 32;
|
prs.lenwords = 32;
|
||||||
@ -753,13 +755,14 @@ to_tsvector_name(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
text *cfg = PG_GETARG_TEXT_P(0);
|
text *cfg = PG_GETARG_TEXT_P(0);
|
||||||
Datum res;
|
Datum res;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
res = DirectFunctionCall3(
|
res = DirectFunctionCall3(
|
||||||
to_tsvector,
|
to_tsvector,
|
||||||
Int32GetDatum(name2id_cfg(cfg)),
|
Int32GetDatum(name2id_cfg(cfg)),
|
||||||
PG_GETARG_DATUM(1),
|
PG_GETARG_DATUM(1),
|
||||||
(Datum) 0
|
(Datum) 0
|
||||||
);
|
);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(cfg, 0);
|
PG_FREE_IF_COPY(cfg, 0);
|
||||||
PG_RETURN_DATUM(res);
|
PG_RETURN_DATUM(res);
|
||||||
@ -769,13 +772,14 @@ Datum
|
|||||||
to_tsvector_current(PG_FUNCTION_ARGS)
|
to_tsvector_current(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Datum res;
|
Datum res;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
res = DirectFunctionCall3(
|
res = DirectFunctionCall3(
|
||||||
to_tsvector,
|
to_tsvector,
|
||||||
Int32GetDatum(get_currcfg()),
|
Int32GetDatum(get_currcfg()),
|
||||||
PG_GETARG_DATUM(0),
|
PG_GETARG_DATUM(0),
|
||||||
(Datum) 0
|
(Datum) 0
|
||||||
);
|
);
|
||||||
|
|
||||||
PG_RETURN_DATUM(res);
|
PG_RETURN_DATUM(res);
|
||||||
}
|
}
|
||||||
@ -823,7 +827,7 @@ tsearch2(PG_FUNCTION_ARGS)
|
|||||||
Oid funcoid = InvalidOid;
|
Oid funcoid = InvalidOid;
|
||||||
TSCfgInfo *cfg;
|
TSCfgInfo *cfg;
|
||||||
|
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
cfg = findcfg(get_currcfg());
|
cfg = findcfg(get_currcfg());
|
||||||
|
|
||||||
if (!CALLED_AS_TRIGGER(fcinfo))
|
if (!CALLED_AS_TRIGGER(fcinfo))
|
||||||
@ -947,23 +951,27 @@ tsearch2(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
silly_cmp_tsvector(const tsvector *a, const tsvector *b) {
|
silly_cmp_tsvector(const tsvector * a, const tsvector * b)
|
||||||
if ( a->len < b->len )
|
{
|
||||||
|
if (a->len < b->len)
|
||||||
return -1;
|
return -1;
|
||||||
else if ( a->len > b->len )
|
else if (a->len > b->len)
|
||||||
return 1;
|
return 1;
|
||||||
else if ( a->size < b->size )
|
else if (a->size < b->size)
|
||||||
return -1;
|
return -1;
|
||||||
else if ( a->size > b->size )
|
else if (a->size > b->size)
|
||||||
return 1;
|
return 1;
|
||||||
else {
|
else
|
||||||
unsigned char *aptr=(unsigned char *)(a->data) + DATAHDRSIZE;
|
{
|
||||||
unsigned char *bptr=(unsigned char *)(b->data) + DATAHDRSIZE;
|
unsigned char *aptr = (unsigned char *) (a->data) + DATAHDRSIZE;
|
||||||
|
unsigned char *bptr = (unsigned char *) (b->data) + DATAHDRSIZE;
|
||||||
|
|
||||||
while( aptr - ( (unsigned char *)(a->data) ) < a->len ) {
|
while (aptr - ((unsigned char *) (a->data)) < a->len)
|
||||||
if ( *aptr != *bptr )
|
{
|
||||||
return ( *aptr < *bptr ) ? -1 : 1;
|
if (*aptr != *bptr)
|
||||||
aptr++; bptr++;
|
return (*aptr < *bptr) ? -1 : 1;
|
||||||
|
aptr++;
|
||||||
|
bptr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -976,60 +984,66 @@ PG_FUNCTION_INFO_V1(tsvector_eq);
|
|||||||
PG_FUNCTION_INFO_V1(tsvector_ne);
|
PG_FUNCTION_INFO_V1(tsvector_ne);
|
||||||
PG_FUNCTION_INFO_V1(tsvector_ge);
|
PG_FUNCTION_INFO_V1(tsvector_ge);
|
||||||
PG_FUNCTION_INFO_V1(tsvector_gt);
|
PG_FUNCTION_INFO_V1(tsvector_gt);
|
||||||
Datum tsvector_cmp(PG_FUNCTION_ARGS);
|
Datum tsvector_cmp(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_lt(PG_FUNCTION_ARGS);
|
Datum tsvector_lt(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_le(PG_FUNCTION_ARGS);
|
Datum tsvector_le(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_eq(PG_FUNCTION_ARGS);
|
Datum tsvector_eq(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_ne(PG_FUNCTION_ARGS);
|
Datum tsvector_ne(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_ge(PG_FUNCTION_ARGS);
|
Datum tsvector_ge(PG_FUNCTION_ARGS);
|
||||||
Datum tsvector_gt(PG_FUNCTION_ARGS);
|
Datum tsvector_gt(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
#define RUNCMP \
|
#define RUNCMP \
|
||||||
tsvector *a = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));\
|
tsvector *a = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));\
|
||||||
tsvector *b = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));\
|
tsvector *b = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));\
|
||||||
int res = silly_cmp_tsvector(a,b); \
|
int res = silly_cmp_tsvector(a,b); \
|
||||||
PG_FREE_IF_COPY(a,0); \
|
PG_FREE_IF_COPY(a,0); \
|
||||||
PG_FREE_IF_COPY(b,1); \
|
PG_FREE_IF_COPY(b,1); \
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_cmp(PG_FUNCTION_ARGS) {
|
tsvector_cmp(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_INT32(res);
|
PG_RETURN_INT32(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_lt(PG_FUNCTION_ARGS) {
|
tsvector_lt(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res < 0) ? true : false);
|
PG_RETURN_BOOL((res < 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_le(PG_FUNCTION_ARGS) {
|
tsvector_le(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res <= 0) ? true : false);
|
PG_RETURN_BOOL((res <= 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_eq(PG_FUNCTION_ARGS) {
|
tsvector_eq(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res == 0) ? true : false);
|
PG_RETURN_BOOL((res == 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_ge(PG_FUNCTION_ARGS) {
|
tsvector_ge(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res >= 0) ? true : false);
|
PG_RETURN_BOOL((res >= 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_gt(PG_FUNCTION_ARGS) {
|
tsvector_gt(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res > 0) ? true : false);
|
PG_RETURN_BOOL((res > 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
tsvector_ne(PG_FUNCTION_ARGS) {
|
tsvector_ne(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
RUNCMP
|
RUNCMP
|
||||||
PG_RETURN_BOOL((res != 0) ? true : false);
|
PG_RETURN_BOOL((res != 0) ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#ifndef __PARSER_H__
|
#ifndef __PARSER_H__
|
||||||
#define __PARSER_H__
|
#define __PARSER_H__
|
||||||
|
|
||||||
extern char *token;
|
extern char *token;
|
||||||
extern int tokenlen;
|
extern int tokenlen;
|
||||||
int tsearch2_yylex(void);
|
int tsearch2_yylex(void);
|
||||||
void tsearch2_start_parse_str(char *, int);
|
void tsearch2_start_parse_str(char *, int);
|
||||||
void tsearch2_end_parse(void);
|
void tsearch2_end_parse(void);
|
||||||
|
@ -30,18 +30,19 @@ init_prs(Oid id, WParserInfo * prs)
|
|||||||
bool isnull;
|
bool isnull;
|
||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
int stat;
|
int stat;
|
||||||
void *plan;
|
void *plan;
|
||||||
char buf[1024], *nsp;
|
char buf[1024],
|
||||||
|
*nsp;
|
||||||
|
|
||||||
arg[0] = OIDOID;
|
arg[0] = OIDOID;
|
||||||
pars[0] = ObjectIdGetDatum(id);
|
pars[0] = ObjectIdGetDatum(id);
|
||||||
|
|
||||||
memset(prs, 0, sizeof(WParserInfo));
|
memset(prs, 0, sizeof(WParserInfo));
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
nsp=get_namespace(TSNSP_FunctionOid);
|
nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
sprintf(buf, "select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from %s.pg_ts_parser where oid = $1", nsp);
|
sprintf(buf, "select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from %s.pg_ts_parser where oid = $1", nsp);
|
||||||
pfree(nsp);
|
pfree(nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -140,8 +141,9 @@ name2id_prs(text *name)
|
|||||||
Datum pars[1];
|
Datum pars[1];
|
||||||
int stat;
|
int stat;
|
||||||
Oid id = findSNMap_t(&(PList.name2id_map), name);
|
Oid id = findSNMap_t(&(PList.name2id_map), name);
|
||||||
char buf[1024], *nsp;
|
char buf[1024],
|
||||||
void *plan;
|
*nsp;
|
||||||
|
void *plan;
|
||||||
|
|
||||||
arg[0] = TEXTOID;
|
arg[0] = TEXTOID;
|
||||||
pars[0] = PointerGetDatum(name);
|
pars[0] = PointerGetDatum(name);
|
||||||
@ -153,7 +155,7 @@ name2id_prs(text *name)
|
|||||||
nsp = get_namespace(TSNSP_FunctionOid);
|
nsp = get_namespace(TSNSP_FunctionOid);
|
||||||
sprintf(buf, "select oid from %s.pg_ts_parser where prs_name = $1", nsp);
|
sprintf(buf, "select oid from %s.pg_ts_parser where prs_name = $1", nsp);
|
||||||
pfree(nsp);
|
pfree(nsp);
|
||||||
plan= SPI_prepare(buf, 1, arg);
|
plan = SPI_prepare(buf, 1, arg);
|
||||||
if (!plan)
|
if (!plan)
|
||||||
ts_error(ERROR, "SPI_prepare() failed");
|
ts_error(ERROR, "SPI_prepare() failed");
|
||||||
|
|
||||||
@ -242,7 +244,8 @@ token_type(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
@ -263,7 +266,8 @@ token_type_byname(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
text *name = PG_GETARG_TEXT_P(0);
|
text *name = PG_GETARG_TEXT_P(0);
|
||||||
@ -287,7 +291,8 @@ token_type_current(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
@ -309,7 +314,7 @@ Datum set_curprs(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
set_curprs(PG_FUNCTION_ARGS)
|
set_curprs(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
findprs(PG_GETARG_OID(0));
|
findprs(PG_GETARG_OID(0));
|
||||||
current_parser_id = PG_GETARG_OID(0);
|
current_parser_id = PG_GETARG_OID(0);
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
@ -321,7 +326,8 @@ Datum
|
|||||||
set_curprs_byname(PG_FUNCTION_ARGS)
|
set_curprs_byname(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *name = PG_GETARG_TEXT_P(0);
|
text *name = PG_GETARG_TEXT_P(0);
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
DirectFunctionCall1(
|
DirectFunctionCall1(
|
||||||
set_curprs,
|
set_curprs,
|
||||||
ObjectIdGetDatum(name2id_prs(name))
|
ObjectIdGetDatum(name2id_prs(name))
|
||||||
@ -444,7 +450,8 @@ parse(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
text *txt = PG_GETARG_TEXT_P(1);
|
text *txt = PG_GETARG_TEXT_P(1);
|
||||||
@ -468,7 +475,8 @@ parse_byname(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
text *name = PG_GETARG_TEXT_P(0);
|
text *name = PG_GETARG_TEXT_P(0);
|
||||||
@ -495,7 +503,8 @@ parse_current(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
FuncCallContext *funcctx;
|
FuncCallContext *funcctx;
|
||||||
Datum result;
|
Datum result;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
text *txt = PG_GETARG_TEXT_P(0);
|
text *txt = PG_GETARG_TEXT_P(0);
|
||||||
@ -527,7 +536,7 @@ headline(PG_FUNCTION_ARGS)
|
|||||||
TSCfgInfo *cfg;
|
TSCfgInfo *cfg;
|
||||||
WParserInfo *prsobj;
|
WParserInfo *prsobj;
|
||||||
|
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
cfg = findcfg(PG_GETARG_OID(0));
|
cfg = findcfg(PG_GETARG_OID(0));
|
||||||
prsobj = findprs(cfg->prs_id);
|
prsobj = findprs(cfg->prs_id);
|
||||||
|
|
||||||
@ -566,14 +575,15 @@ headline_byname(PG_FUNCTION_ARGS)
|
|||||||
text *cfg = PG_GETARG_TEXT_P(0);
|
text *cfg = PG_GETARG_TEXT_P(0);
|
||||||
|
|
||||||
Datum out;
|
Datum out;
|
||||||
SET_FUNCOID();
|
|
||||||
|
SET_FUNCOID();
|
||||||
out = DirectFunctionCall4(
|
out = DirectFunctionCall4(
|
||||||
headline,
|
headline,
|
||||||
ObjectIdGetDatum(name2id_cfg(cfg)),
|
ObjectIdGetDatum(name2id_cfg(cfg)),
|
||||||
PG_GETARG_DATUM(1),
|
PG_GETARG_DATUM(1),
|
||||||
PG_GETARG_DATUM(2),
|
PG_GETARG_DATUM(2),
|
||||||
(PG_NARGS() > 3) ? PG_GETARG_DATUM(3) : PointerGetDatum(NULL)
|
(PG_NARGS() > 3) ? PG_GETARG_DATUM(3) : PointerGetDatum(NULL)
|
||||||
);
|
);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(cfg, 0);
|
PG_FREE_IF_COPY(cfg, 0);
|
||||||
PG_RETURN_DATUM(out);
|
PG_RETURN_DATUM(out);
|
||||||
@ -584,7 +594,7 @@ Datum headline_current(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
headline_current(PG_FUNCTION_ARGS)
|
headline_current(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SET_FUNCOID();
|
SET_FUNCOID();
|
||||||
PG_RETURN_DATUM(DirectFunctionCall4(
|
PG_RETURN_DATUM(DirectFunctionCall4(
|
||||||
headline,
|
headline,
|
||||||
ObjectIdGetDatum(get_currcfg()),
|
ObjectIdGetDatum(get_currcfg()),
|
||||||
|
@ -192,12 +192,13 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
int bestb = -1,
|
int bestb = -1,
|
||||||
beste = -1;
|
beste = -1;
|
||||||
int bestlen = -1;
|
int bestlen = -1;
|
||||||
int pose = 0, posb,
|
int pose = 0,
|
||||||
|
posb,
|
||||||
poslen,
|
poslen,
|
||||||
curlen;
|
curlen;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int highlight=0;
|
int highlight = 0;
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
prs->startsel = NULL;
|
prs->startsel = NULL;
|
||||||
@ -224,13 +225,13 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
prs->stopsel = pstrdup(mptr->value);
|
prs->stopsel = pstrdup(mptr->value);
|
||||||
else if (pg_strcasecmp(mptr->key, "HighlightAll") == 0)
|
else if (pg_strcasecmp(mptr->key, "HighlightAll") == 0)
|
||||||
highlight = (
|
highlight = (
|
||||||
pg_strcasecmp(mptr->value, "1")==0 ||
|
pg_strcasecmp(mptr->value, "1") == 0 ||
|
||||||
pg_strcasecmp(mptr->value, "on")==0 ||
|
pg_strcasecmp(mptr->value, "on") == 0 ||
|
||||||
pg_strcasecmp(mptr->value, "true")==0 ||
|
pg_strcasecmp(mptr->value, "true") == 0 ||
|
||||||
pg_strcasecmp(mptr->value, "t")==0 ||
|
pg_strcasecmp(mptr->value, "t") == 0 ||
|
||||||
pg_strcasecmp(mptr->value, "y")==0 ||
|
pg_strcasecmp(mptr->value, "y") == 0 ||
|
||||||
pg_strcasecmp(mptr->value, "yes")==0 ) ?
|
pg_strcasecmp(mptr->value, "yes") == 0) ?
|
||||||
1 : 0;
|
1 : 0;
|
||||||
|
|
||||||
pfree(mptr->key);
|
pfree(mptr->key);
|
||||||
pfree(mptr->value);
|
pfree(mptr->value);
|
||||||
@ -239,23 +240,25 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
pfree(map);
|
pfree(map);
|
||||||
|
|
||||||
if (highlight==0) {
|
if (highlight == 0)
|
||||||
|
{
|
||||||
if (min_words >= max_words)
|
if (min_words >= max_words)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("MinWords should be less than MaxWords")));
|
errmsg("MinWords should be less than MaxWords")));
|
||||||
if (min_words <= 0)
|
if (min_words <= 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("MinWords should be positive")));
|
errmsg("MinWords should be positive")));
|
||||||
if (shortword < 0)
|
if (shortword < 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("ShortWord should be >= 0")));
|
errmsg("ShortWord should be >= 0")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highlight==0) {
|
if (highlight == 0)
|
||||||
|
{
|
||||||
while (hlCover(prs, query, &p, &q))
|
while (hlCover(prs, query, &p, &q))
|
||||||
{
|
{
|
||||||
/* find cover len in words */
|
/* find cover len in words */
|
||||||
@ -277,9 +280,9 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
posb=p;
|
posb = p;
|
||||||
if (curlen < max_words)
|
if (curlen < max_words)
|
||||||
{ /* find good end */
|
{ /* find good end */
|
||||||
for (i = i - 1; i < prs->curwords && curlen < max_words; i++)
|
for (i = i - 1; i < prs->curwords && curlen < max_words; i++)
|
||||||
{
|
{
|
||||||
if (i != q)
|
if (i != q)
|
||||||
@ -295,8 +298,11 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
if (curlen >= min_words)
|
if (curlen >= min_words)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( curlen < min_words && i>=prs->curwords ) { /* got end of text and our cover is shoter than min_words */
|
if (curlen < min_words && i >= prs->curwords)
|
||||||
for(i=p; i>= 0; i--) {
|
{ /* got end of text and our cover is shoter
|
||||||
|
* than min_words */
|
||||||
|
for (i = p; i >= 0; i--)
|
||||||
|
{
|
||||||
if (!NONWORDTOKEN(prs->words[i].type))
|
if (!NONWORDTOKEN(prs->words[i].type))
|
||||||
curlen++;
|
curlen++;
|
||||||
if (prs->words[i].item && !prs->words[i].repeated)
|
if (prs->words[i].item && !prs->words[i].repeated)
|
||||||
@ -306,11 +312,11 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
if (curlen >= min_words)
|
if (curlen >= min_words)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
posb=(i>=0) ? i : 0;
|
posb = (i >= 0) ? i : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* shorter cover :((( */
|
{ /* shorter cover :((( */
|
||||||
for (; curlen > min_words; i--)
|
for (; curlen > min_words; i--)
|
||||||
{
|
{
|
||||||
if (!NONWORDTOKEN(prs->words[i].type))
|
if (!NONWORDTOKEN(prs->words[i].type))
|
||||||
@ -348,19 +354,24 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||||||
bestb = 0;
|
bestb = 0;
|
||||||
beste = pose;
|
beste = pose;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
bestb=0;
|
else
|
||||||
beste=prs->curwords-1;
|
{
|
||||||
|
bestb = 0;
|
||||||
|
beste = prs->curwords - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = bestb; i <= beste; i++)
|
for (i = bestb; i <= beste; i++)
|
||||||
{
|
{
|
||||||
if (prs->words[i].item)
|
if (prs->words[i].item)
|
||||||
prs->words[i].selected = 1;
|
prs->words[i].selected = 1;
|
||||||
if ( highlight==0 ) {
|
if (highlight == 0)
|
||||||
|
{
|
||||||
if (HLIDIGNORE(prs->words[i].type))
|
if (HLIDIGNORE(prs->words[i].type))
|
||||||
prs->words[i].replace = 1;
|
prs->words[i].replace = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (HTMLHLIDIGNORE(prs->words[i].type))
|
if (HTMLHLIDIGNORE(prs->words[i].type))
|
||||||
prs->words[i].replace = 1;
|
prs->words[i].replace = 1;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -32,153 +32,150 @@ extern xmlChar *pgxml_texttoxmlchar(text *textstring);
|
|||||||
/* local defs */
|
/* local defs */
|
||||||
static void parse_params(const char **params, text *paramstr);
|
static void parse_params(const char **params, text *paramstr);
|
||||||
|
|
||||||
Datum xslt_process(PG_FUNCTION_ARGS);
|
Datum xslt_process(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
#define MAXPARAMS 20
|
#define MAXPARAMS 20
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(xslt_process);
|
PG_FUNCTION_INFO_V1(xslt_process);
|
||||||
|
|
||||||
Datum xslt_process(PG_FUNCTION_ARGS) {
|
Datum
|
||||||
|
xslt_process(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
const char *params[MAXPARAMS + 1]; /* +1 for the terminator */
|
const char *params[MAXPARAMS + 1]; /* +1 for the terminator */
|
||||||
xsltStylesheetPtr stylesheet = NULL;
|
xsltStylesheetPtr stylesheet = NULL;
|
||||||
xmlDocPtr doctree;
|
xmlDocPtr doctree;
|
||||||
xmlDocPtr restree;
|
xmlDocPtr restree;
|
||||||
xmlDocPtr ssdoc = NULL;
|
xmlDocPtr ssdoc = NULL;
|
||||||
xmlChar *resstr;
|
xmlChar *resstr;
|
||||||
int resstat;
|
int resstat;
|
||||||
int reslen;
|
int reslen;
|
||||||
|
|
||||||
text *doct = PG_GETARG_TEXT_P(0);
|
text *doct = PG_GETARG_TEXT_P(0);
|
||||||
text *ssheet = PG_GETARG_TEXT_P(1);
|
text *ssheet = PG_GETARG_TEXT_P(1);
|
||||||
text *paramstr;
|
text *paramstr;
|
||||||
text *tres;
|
text *tres;
|
||||||
|
|
||||||
|
|
||||||
if (fcinfo->nargs == 3)
|
if (fcinfo->nargs == 3)
|
||||||
{
|
|
||||||
paramstr = PG_GETARG_TEXT_P(2);
|
|
||||||
parse_params(params,paramstr);
|
|
||||||
}
|
|
||||||
else /* No parameters */
|
|
||||||
{
|
|
||||||
params[0] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup parser */
|
|
||||||
pgxml_parser_init();
|
|
||||||
|
|
||||||
/* Check to see if document is a file or a literal */
|
|
||||||
|
|
||||||
if (VARDATA(doct)[0] == '<')
|
|
||||||
{
|
|
||||||
doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct)-VARHDRSZ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
doctree = xmlParseFile(GET_STR(doct));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doctree == NULL)
|
|
||||||
{
|
|
||||||
xmlCleanupParser();
|
|
||||||
elog_error(ERROR,"Error parsing XML document",0);
|
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Same for stylesheet */
|
|
||||||
if (VARDATA(ssheet)[0] == '<')
|
|
||||||
{
|
|
||||||
ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
|
|
||||||
VARSIZE(ssheet)-VARHDRSZ);
|
|
||||||
if (ssdoc == NULL)
|
|
||||||
{
|
{
|
||||||
xmlFreeDoc(doctree);
|
paramstr = PG_GETARG_TEXT_P(2);
|
||||||
xmlCleanupParser();
|
parse_params(params, paramstr);
|
||||||
elog_error(ERROR,"Error parsing stylesheet as XML document",0);
|
}
|
||||||
PG_RETURN_NULL();
|
else
|
||||||
|
/* No parameters */
|
||||||
|
params[0] = NULL;
|
||||||
|
|
||||||
|
/* Setup parser */
|
||||||
|
pgxml_parser_init();
|
||||||
|
|
||||||
|
/* Check to see if document is a file or a literal */
|
||||||
|
|
||||||
|
if (VARDATA(doct)[0] == '<')
|
||||||
|
doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
|
||||||
|
else
|
||||||
|
doctree = xmlParseFile(GET_STR(doct));
|
||||||
|
|
||||||
|
if (doctree == NULL)
|
||||||
|
{
|
||||||
|
xmlCleanupParser();
|
||||||
|
elog_error(ERROR, "Error parsing XML document", 0);
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
stylesheet = xsltParseStylesheetDoc(ssdoc);
|
/* Same for stylesheet */
|
||||||
}
|
if (VARDATA(ssheet)[0] == '<')
|
||||||
else
|
{
|
||||||
{
|
ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
|
||||||
stylesheet = xsltParseStylesheetFile(GET_STR(ssheet));
|
VARSIZE(ssheet) - VARHDRSZ);
|
||||||
}
|
if (ssdoc == NULL)
|
||||||
|
{
|
||||||
|
xmlFreeDoc(doctree);
|
||||||
|
xmlCleanupParser();
|
||||||
|
elog_error(ERROR, "Error parsing stylesheet as XML document", 0);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
stylesheet = xsltParseStylesheetDoc(ssdoc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stylesheet = xsltParseStylesheetFile(GET_STR(ssheet));
|
||||||
|
|
||||||
|
|
||||||
if (stylesheet == NULL)
|
if (stylesheet == NULL)
|
||||||
{
|
{
|
||||||
xmlFreeDoc(doctree);
|
xmlFreeDoc(doctree);
|
||||||
xsltCleanupGlobals();
|
xsltCleanupGlobals();
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
elog_error(ERROR,"Failed to parse stylesheet",0);
|
elog_error(ERROR, "Failed to parse stylesheet", 0);
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
restree = xsltApplyStylesheet(stylesheet, doctree, params);
|
restree = xsltApplyStylesheet(stylesheet, doctree, params);
|
||||||
resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet);
|
resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet);
|
||||||
|
|
||||||
xsltFreeStylesheet(stylesheet);
|
xsltFreeStylesheet(stylesheet);
|
||||||
xmlFreeDoc(restree);
|
xmlFreeDoc(restree);
|
||||||
xmlFreeDoc(doctree);
|
xmlFreeDoc(doctree);
|
||||||
|
|
||||||
xsltCleanupGlobals();
|
xsltCleanupGlobals();
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
|
|
||||||
if (resstat < 0) {
|
if (resstat < 0)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
|
||||||
|
|
||||||
tres = palloc(reslen + VARHDRSZ);
|
tres = palloc(reslen + VARHDRSZ);
|
||||||
memcpy(VARDATA(tres),resstr,reslen);
|
memcpy(VARDATA(tres), resstr, reslen);
|
||||||
VARATT_SIZEP(tres) = reslen + VARHDRSZ;
|
VARATT_SIZEP(tres) = reslen + VARHDRSZ;
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(tres);
|
PG_RETURN_TEXT_P(tres);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_params(const char **params, text *paramstr)
|
void
|
||||||
|
parse_params(const char **params, text *paramstr)
|
||||||
{
|
{
|
||||||
char *pos;
|
char *pos;
|
||||||
char *pstr;
|
char *pstr;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char *nvsep="=";
|
char *nvsep = "=";
|
||||||
char *itsep=",";
|
char *itsep = ",";
|
||||||
|
|
||||||
pstr = GET_STR(paramstr);
|
pstr = GET_STR(paramstr);
|
||||||
|
|
||||||
pos=pstr;
|
pos = pstr;
|
||||||
|
|
||||||
for (i=0; i < MAXPARAMS; i++)
|
for (i = 0; i < MAXPARAMS; i++)
|
||||||
{
|
{
|
||||||
params[i] = pos;
|
params[i] = pos;
|
||||||
pos = strstr(pos,nvsep);
|
pos = strstr(pos, nvsep);
|
||||||
if (pos != NULL) {
|
if (pos != NULL)
|
||||||
*pos = '\0';
|
{
|
||||||
pos++;
|
*pos = '\0';
|
||||||
} else {
|
pos++;
|
||||||
params[i]=NULL;
|
}
|
||||||
break;
|
else
|
||||||
}
|
{
|
||||||
/* Value */
|
params[i] = NULL;
|
||||||
i++;
|
break;
|
||||||
params[i]=pos;
|
}
|
||||||
pos = strstr(pos,itsep);
|
/* Value */
|
||||||
if (pos != NULL) {
|
i++;
|
||||||
*pos = '\0';
|
params[i] = pos;
|
||||||
pos++;
|
pos = strstr(pos, itsep);
|
||||||
} else {
|
if (pos != NULL)
|
||||||
break;
|
{
|
||||||
}
|
*pos = '\0';
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (i < MAXPARAMS)
|
if (i < MAXPARAMS)
|
||||||
{
|
params[i + 1] = NULL;
|
||||||
params[i+1]=NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.93 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.94 2004/08/29 05:06:39 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The old interface functions have been converted to macros
|
* The old interface functions have been converted to macros
|
||||||
@ -468,17 +468,19 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the attribute number is 0, then we are supposed to return
|
* If the attribute number is 0, then we are supposed to
|
||||||
* the entire tuple as a row-type Datum. (Using zero for this
|
* return the entire tuple as a row-type Datum. (Using zero
|
||||||
* purpose is unclean since it risks confusion with "invalid attr"
|
* for this purpose is unclean since it risks confusion with
|
||||||
* result codes, but it's not worth changing now.)
|
* "invalid attr" result codes, but it's not worth changing
|
||||||
|
* now.)
|
||||||
*
|
*
|
||||||
* We have to make a copy of the tuple so we can safely insert the
|
* We have to make a copy of the tuple so we can safely insert
|
||||||
* Datum overhead fields, which are not set in on-disk tuples.
|
* the Datum overhead fields, which are not set in on-disk
|
||||||
|
* tuples.
|
||||||
*/
|
*/
|
||||||
case InvalidAttrNumber:
|
case InvalidAttrNumber:
|
||||||
{
|
{
|
||||||
HeapTupleHeader dtup;
|
HeapTupleHeader dtup;
|
||||||
|
|
||||||
dtup = (HeapTupleHeader) palloc(tup->t_len);
|
dtup = (HeapTupleHeader) palloc(tup->t_len);
|
||||||
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
|
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
|
||||||
@ -555,7 +557,7 @@ heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
|
|||||||
* construct a tuple from the given values[] and nulls[] arrays
|
* construct a tuple from the given values[] and nulls[] arrays
|
||||||
*
|
*
|
||||||
* Null attributes are indicated by a 'n' in the appropriate byte
|
* Null attributes are indicated by a 'n' in the appropriate byte
|
||||||
* of nulls[]. Non-null attributes are indicated by a ' ' (space).
|
* of nulls[]. Non-null attributes are indicated by a ' ' (space).
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
HeapTuple
|
HeapTuple
|
||||||
@ -580,7 +582,7 @@ heap_formtuple(TupleDesc tupleDescriptor,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for nulls and embedded tuples; expand any toasted attributes
|
* Check for nulls and embedded tuples; expand any toasted attributes
|
||||||
* in embedded tuples. This preserves the invariant that toasting can
|
* in embedded tuples. This preserves the invariant that toasting can
|
||||||
* only go one level deep.
|
* only go one level deep.
|
||||||
*
|
*
|
||||||
* We can skip calling toast_flatten_tuple_attribute() if the attribute
|
* We can skip calling toast_flatten_tuple_attribute() if the attribute
|
||||||
@ -620,7 +622,7 @@ heap_formtuple(TupleDesc tupleDescriptor,
|
|||||||
len += ComputeDataSize(tupleDescriptor, values, nulls);
|
len += ComputeDataSize(tupleDescriptor, values, nulls);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and zero the space needed. Note that the tuple body and
|
* Allocate and zero the space needed. Note that the tuple body and
|
||||||
* HeapTupleData management structure are allocated in one chunk.
|
* HeapTupleData management structure are allocated in one chunk.
|
||||||
*/
|
*/
|
||||||
tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
|
tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
|
||||||
@ -683,9 +685,9 @@ heap_modifytuple(HeapTuple tuple,
|
|||||||
* allocate and fill values and nulls arrays from either the tuple or
|
* allocate and fill values and nulls arrays from either the tuple or
|
||||||
* the repl information, as appropriate.
|
* the repl information, as appropriate.
|
||||||
*
|
*
|
||||||
* NOTE: it's debatable whether to use heap_deformtuple() here or
|
* NOTE: it's debatable whether to use heap_deformtuple() here or just
|
||||||
* just heap_getattr() only the non-replaced colums. The latter could
|
* heap_getattr() only the non-replaced colums. The latter could win
|
||||||
* win if there are many replaced columns and few non-replaced ones.
|
* if there are many replaced columns and few non-replaced ones.
|
||||||
* However, heap_deformtuple costs only O(N) while the heap_getattr
|
* However, heap_deformtuple costs only O(N) while the heap_getattr
|
||||||
* way would cost O(N^2) if there are many non-replaced columns, so it
|
* way would cost O(N^2) if there are many non-replaced columns, so it
|
||||||
* seems better to err on the side of linear cost.
|
* seems better to err on the side of linear cost.
|
||||||
@ -763,10 +765,11 @@ heap_deformtuple(HeapTuple tuple,
|
|||||||
bool slow = false; /* can we use/set attcacheoff? */
|
bool slow = false; /* can we use/set attcacheoff? */
|
||||||
|
|
||||||
natts = tup->t_natts;
|
natts = tup->t_natts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In inheritance situations, it is possible that the given tuple actually
|
* In inheritance situations, it is possible that the given tuple
|
||||||
* has more fields than the caller is expecting. Don't run off the end
|
* actually has more fields than the caller is expecting. Don't run
|
||||||
* of the caller's arrays.
|
* off the end of the caller's arrays.
|
||||||
*/
|
*/
|
||||||
natts = Min(natts, tdesc_natts);
|
natts = Min(natts, tdesc_natts);
|
||||||
|
|
||||||
@ -787,9 +790,7 @@ heap_deformtuple(HeapTuple tuple,
|
|||||||
nulls[attnum] = ' ';
|
nulls[attnum] = ' ';
|
||||||
|
|
||||||
if (!slow && att[attnum]->attcacheoff >= 0)
|
if (!slow && att[attnum]->attcacheoff >= 0)
|
||||||
{
|
|
||||||
off = att[attnum]->attcacheoff;
|
off = att[attnum]->attcacheoff;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
off = att_align(off, att[attnum]->attalign);
|
off = att_align(off, att[attnum]->attalign);
|
||||||
@ -807,8 +808,8 @@ heap_deformtuple(HeapTuple tuple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If tuple doesn't have all the atts indicated by tupleDesc, read
|
* If tuple doesn't have all the atts indicated by tupleDesc, read the
|
||||||
* the rest as null
|
* rest as null
|
||||||
*/
|
*/
|
||||||
for (; attnum < tdesc_natts; attnum++)
|
for (; attnum < tdesc_natts; attnum++)
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.70 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.71 2004/08/29 05:06:39 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -162,9 +162,9 @@ index_formtuple(TupleDesc tupleDescriptor,
|
|||||||
if ((size & INDEX_SIZE_MASK) != size)
|
if ((size & INDEX_SIZE_MASK) != size)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("index row requires %lu bytes, maximum size is %lu",
|
errmsg("index row requires %lu bytes, maximum size is %lu",
|
||||||
(unsigned long) size,
|
(unsigned long) size,
|
||||||
(unsigned long) INDEX_SIZE_MASK)));
|
(unsigned long) INDEX_SIZE_MASK)));
|
||||||
|
|
||||||
infomask |= size;
|
infomask |= size;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.84 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.85 2004/08/29 05:06:39 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -356,7 +356,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
|||||||
|
|
||||||
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
|
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
|
||||||
attr,
|
attr,
|
||||||
ObjectIdGetDatum(thisState->typioparam),
|
ObjectIdGetDatum(thisState->typioparam),
|
||||||
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
||||||
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
|
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
|
||||||
pfree(outputstr);
|
pfree(outputstr);
|
||||||
@ -368,7 +368,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
|||||||
|
|
||||||
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
||||||
attr,
|
attr,
|
||||||
ObjectIdGetDatum(thisState->typioparam)));
|
ObjectIdGetDatum(thisState->typioparam)));
|
||||||
/* We assume the result will not have been toasted */
|
/* We assume the result will not have been toasted */
|
||||||
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
||||||
pq_sendbytes(&buf, VARDATA(outputbytes),
|
pq_sendbytes(&buf, VARDATA(outputbytes),
|
||||||
@ -458,7 +458,7 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
|||||||
|
|
||||||
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
|
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
|
||||||
attr,
|
attr,
|
||||||
ObjectIdGetDatum(thisState->typioparam),
|
ObjectIdGetDatum(thisState->typioparam),
|
||||||
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
||||||
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
|
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
|
||||||
pfree(outputstr);
|
pfree(outputstr);
|
||||||
@ -579,7 +579,7 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
|||||||
|
|
||||||
value = DatumGetCString(OidFunctionCall3(typoutput,
|
value = DatumGetCString(OidFunctionCall3(typoutput,
|
||||||
attr,
|
attr,
|
||||||
ObjectIdGetDatum(typioparam),
|
ObjectIdGetDatum(typioparam),
|
||||||
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
||||||
|
|
||||||
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
|
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
|
||||||
@ -672,7 +672,7 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
|||||||
|
|
||||||
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
||||||
attr,
|
attr,
|
||||||
ObjectIdGetDatum(thisState->typioparam)));
|
ObjectIdGetDatum(thisState->typioparam)));
|
||||||
/* We assume the result will not have been toasted */
|
/* We assume the result will not have been toasted */
|
||||||
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
||||||
pq_sendbytes(&buf, VARDATA(outputbytes),
|
pq_sendbytes(&buf, VARDATA(outputbytes),
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.105 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.106 2004/08/29 05:06:39 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* some of the executor utility code such as "ExecTypeFromTL" should be
|
* some of the executor utility code such as "ExecTypeFromTL" should be
|
||||||
@ -52,8 +52,8 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate enough memory for the tuple descriptor, and zero the
|
* Allocate enough memory for the tuple descriptor, and zero the
|
||||||
* attrs[] array since TupleDescInitEntry assumes that the array
|
* attrs[] array since TupleDescInitEntry assumes that the array is
|
||||||
* is filled with NULL pointers.
|
* filled with NULL pointers.
|
||||||
*/
|
*/
|
||||||
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
|
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
|
||||||
|
|
||||||
@ -420,8 +420,8 @@ TupleDescInitEntry(TupleDesc desc,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: attributeName can be NULL, because the planner doesn't always
|
* Note: attributeName can be NULL, because the planner doesn't always
|
||||||
* fill in valid resname values in targetlists, particularly for resjunk
|
* fill in valid resname values in targetlists, particularly for
|
||||||
* attributes.
|
* resjunk attributes.
|
||||||
*/
|
*/
|
||||||
if (attributeName != NULL)
|
if (attributeName != NULL)
|
||||||
namestrcpy(&(att->attname), attributeName);
|
namestrcpy(&(att->attname), attributeName);
|
||||||
@ -464,7 +464,7 @@ TupleDescInitEntry(TupleDesc desc,
|
|||||||
* Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
|
* Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
|
||||||
*
|
*
|
||||||
* Note: the default assumption is no OIDs; caller may modify the returned
|
* Note: the default assumption is no OIDs; caller may modify the returned
|
||||||
* TupleDesc if it wants OIDs. Also, tdtypeid will need to be filled in
|
* TupleDesc if it wants OIDs. Also, tdtypeid will need to be filled in
|
||||||
* later on.
|
* later on.
|
||||||
*/
|
*/
|
||||||
TupleDesc
|
TupleDesc
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.110 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.111 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -667,7 +667,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
|||||||
Datum attr[INDEX_MAX_KEYS];
|
Datum attr[INDEX_MAX_KEYS];
|
||||||
bool whatfree[INDEX_MAX_KEYS];
|
bool whatfree[INDEX_MAX_KEYS];
|
||||||
char isnull[INDEX_MAX_KEYS];
|
char isnull[INDEX_MAX_KEYS];
|
||||||
GistEntryVector *evec;
|
GistEntryVector *evec;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
int datumsize,
|
int datumsize,
|
||||||
i,
|
i,
|
||||||
@ -715,8 +715,8 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
|||||||
{
|
{
|
||||||
evec->n = 2;
|
evec->n = 2;
|
||||||
gistentryinit(evec->vector[1],
|
gistentryinit(evec->vector[1],
|
||||||
evec->vector[0].key, r, NULL,
|
evec->vector[0].key, r, NULL,
|
||||||
(OffsetNumber) 0, evec->vector[0].bytes, FALSE);
|
(OffsetNumber) 0, evec->vector[0].bytes, FALSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -763,7 +763,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
|||||||
static IndexTuple
|
static IndexTuple
|
||||||
gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
|
gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
|
||||||
{
|
{
|
||||||
GistEntryVector *evec;
|
GistEntryVector *evec;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
int datumsize;
|
int datumsize;
|
||||||
bool result,
|
bool result,
|
||||||
@ -879,7 +879,7 @@ gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITV
|
|||||||
int len,
|
int len,
|
||||||
*attrsize;
|
*attrsize;
|
||||||
OffsetNumber *entries;
|
OffsetNumber *entries;
|
||||||
GistEntryVector *evec;
|
GistEntryVector *evec;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
int datumsize;
|
int datumsize;
|
||||||
int reallen;
|
int reallen;
|
||||||
@ -940,8 +940,8 @@ gistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITV
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* evec->vector[0].bytes may be not
|
* evec->vector[0].bytes may be not defined, so form union
|
||||||
* defined, so form union with itself
|
* with itself
|
||||||
*/
|
*/
|
||||||
if (reallen == 1)
|
if (reallen == 1)
|
||||||
{
|
{
|
||||||
@ -1056,7 +1056,7 @@ gistadjsubkey(Relation r,
|
|||||||
*ev1p;
|
*ev1p;
|
||||||
float lpenalty,
|
float lpenalty,
|
||||||
rpenalty;
|
rpenalty;
|
||||||
GistEntryVector *evec;
|
GistEntryVector *evec;
|
||||||
int datumsize;
|
int datumsize;
|
||||||
bool isnull[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
int i,
|
int i,
|
||||||
@ -1222,7 +1222,7 @@ gistSplit(Relation r,
|
|||||||
rbknum;
|
rbknum;
|
||||||
GISTPageOpaque opaque;
|
GISTPageOpaque opaque;
|
||||||
GIST_SPLITVEC v;
|
GIST_SPLITVEC v;
|
||||||
GistEntryVector *entryvec;
|
GistEntryVector *entryvec;
|
||||||
bool *decompvec;
|
bool *decompvec;
|
||||||
int i,
|
int i,
|
||||||
j,
|
j,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.41 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.42 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -250,9 +250,10 @@ gistindex_keytest(IndexTuple tuple,
|
|||||||
FALSE, isNull);
|
FALSE, isNull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the Consistent function to evaluate the test. The arguments
|
* Call the Consistent function to evaluate the test. The
|
||||||
* are the index datum (as a GISTENTRY*), the comparison datum, and
|
* arguments are the index datum (as a GISTENTRY*), the comparison
|
||||||
* the comparison operator's strategy number and subtype from pg_amop.
|
* datum, and the comparison operator's strategy number and
|
||||||
|
* subtype from pg_amop.
|
||||||
*
|
*
|
||||||
* (Presently there's no need to pass the subtype since it'll always
|
* (Presently there's no need to pass the subtype since it'll always
|
||||||
* be zero, but might as well pass it for possible future use.)
|
* be zero, but might as well pass it for possible future use.)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.54 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.55 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -115,9 +115,7 @@ gistrescan(PG_FUNCTION_ARGS)
|
|||||||
* the sk_subtype field.
|
* the sk_subtype field.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < s->numberOfKeys; i++)
|
for (i = 0; i < s->numberOfKeys; i++)
|
||||||
{
|
|
||||||
s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
|
s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
@ -266,9 +264,9 @@ ReleaseResources_gist(void)
|
|||||||
GISTScanList next;
|
GISTScanList next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: this should be a no-op during normal query shutdown.
|
* Note: this should be a no-op during normal query shutdown. However,
|
||||||
* However, in an abort situation ExecutorEnd is not called and so
|
* in an abort situation ExecutorEnd is not called and so there may be
|
||||||
* there may be open index scans to clean up.
|
* open index scans to clean up.
|
||||||
*/
|
*/
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.72 2004/08/29 04:12:17 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.73 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -210,8 +210,8 @@ hashgettuple(PG_FUNCTION_ARGS)
|
|||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We hold pin but not lock on current buffer while outside the hash AM.
|
* We hold pin but not lock on current buffer while outside the hash
|
||||||
* Reacquire the read lock here.
|
* AM. Reacquire the read lock here.
|
||||||
*/
|
*/
|
||||||
if (BufferIsValid(so->hashso_curbuf))
|
if (BufferIsValid(so->hashso_curbuf))
|
||||||
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
|
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
|
||||||
@ -470,7 +470,7 @@ hashbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
/*
|
/*
|
||||||
* Read the metapage to fetch original bucket and tuple counts. Also,
|
* Read the metapage to fetch original bucket and tuple counts. Also,
|
||||||
* we keep a copy of the last-seen metapage so that we can use its
|
* we keep a copy of the last-seen metapage so that we can use its
|
||||||
* hashm_spares[] values to compute bucket page addresses. This is a
|
* hashm_spares[] values to compute bucket page addresses. This is a
|
||||||
* bit hokey but perfectly safe, since the interesting entries in the
|
* bit hokey but perfectly safe, since the interesting entries in the
|
||||||
* spares array cannot change under us; and it beats rereading the
|
* spares array cannot change under us; and it beats rereading the
|
||||||
* metapage for each bucket.
|
* metapage for each bucket.
|
||||||
@ -532,7 +532,7 @@ loop_top:
|
|||||||
ItemPointer htup;
|
ItemPointer htup;
|
||||||
|
|
||||||
hitem = (HashItem) PageGetItem(page,
|
hitem = (HashItem) PageGetItem(page,
|
||||||
PageGetItemId(page, offno));
|
PageGetItemId(page, offno));
|
||||||
htup = &(hitem->hash_itup.t_tid);
|
htup = &(hitem->hash_itup.t_tid);
|
||||||
if (callback(htup, callback_state))
|
if (callback(htup, callback_state))
|
||||||
{
|
{
|
||||||
@ -595,8 +595,8 @@ loop_top:
|
|||||||
orig_ntuples == metap->hashm_ntuples)
|
orig_ntuples == metap->hashm_ntuples)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* No one has split or inserted anything since start of scan,
|
* No one has split or inserted anything since start of scan, so
|
||||||
* so believe our count as gospel.
|
* believe our count as gospel.
|
||||||
*/
|
*/
|
||||||
metap->hashm_ntuples = num_index_tuples;
|
metap->hashm_ntuples = num_index_tuples;
|
||||||
}
|
}
|
||||||
@ -604,7 +604,7 @@ loop_top:
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Otherwise, our count is untrustworthy since we may have
|
* Otherwise, our count is untrustworthy since we may have
|
||||||
* double-scanned tuples in split buckets. Proceed by
|
* double-scanned tuples in split buckets. Proceed by
|
||||||
* dead-reckoning.
|
* dead-reckoning.
|
||||||
*/
|
*/
|
||||||
if (metap->hashm_ntuples > tuples_removed)
|
if (metap->hashm_ntuples > tuples_removed)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.33 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.34 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf,
|
static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf,
|
||||||
Size itemsize, HashItem hitem);
|
Size itemsize, HashItem hitem);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -81,7 +81,7 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether the item can fit on a hash page at all. (Eventually,
|
* Check whether the item can fit on a hash page at all. (Eventually,
|
||||||
* we ought to try to apply TOAST methods if not.) Note that at this
|
* we ought to try to apply TOAST methods if not.) Note that at this
|
||||||
* point, itemsz doesn't include the ItemId.
|
* point, itemsz doesn't include the ItemId.
|
||||||
*/
|
*/
|
||||||
if (itemsz > HashMaxItemSize((Page) metap))
|
if (itemsz > HashMaxItemSize((Page) metap))
|
||||||
@ -105,7 +105,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
|
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquire share lock on target bucket; then we can release split lock.
|
* Acquire share lock on target bucket; then we can release split
|
||||||
|
* lock.
|
||||||
*/
|
*/
|
||||||
_hash_getlock(rel, blkno, HASH_SHARE);
|
_hash_getlock(rel, blkno, HASH_SHARE);
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
/*
|
/*
|
||||||
* no space on this page; check for an overflow page
|
* no space on this page; check for an overflow page
|
||||||
*/
|
*/
|
||||||
BlockNumber nextblkno = pageopaque->hasho_nextblkno;
|
BlockNumber nextblkno = pageopaque->hasho_nextblkno;
|
||||||
|
|
||||||
if (BlockNumberIsValid(nextblkno))
|
if (BlockNumberIsValid(nextblkno))
|
||||||
{
|
{
|
||||||
@ -169,8 +170,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
_hash_droplock(rel, blkno, HASH_SHARE);
|
_hash_droplock(rel, blkno, HASH_SHARE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write-lock the metapage so we can increment the tuple count.
|
* Write-lock the metapage so we can increment the tuple count. After
|
||||||
* After incrementing it, check to see if it's time for a split.
|
* incrementing it, check to see if it's time for a split.
|
||||||
*/
|
*/
|
||||||
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.43 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.44 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Overflow pages look like ordinary relation pages.
|
* Overflow pages look like ordinary relation pages.
|
||||||
@ -41,11 +41,11 @@ bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
|
|||||||
for (i = 1;
|
for (i = 1;
|
||||||
i < splitnum && ovflbitnum > metap->hashm_spares[i];
|
i < splitnum && ovflbitnum > metap->hashm_spares[i];
|
||||||
i++)
|
i++)
|
||||||
/* loop */ ;
|
/* loop */ ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert to absolute page number by adding the number of bucket pages
|
* Convert to absolute page number by adding the number of bucket
|
||||||
* that exist before this split point.
|
* pages that exist before this split point.
|
||||||
*/
|
*/
|
||||||
return (BlockNumber) ((1 << i) + ovflbitnum);
|
return (BlockNumber) ((1 << i) + ovflbitnum);
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
|
|||||||
*
|
*
|
||||||
* Add an overflow page to the bucket whose last page is pointed to by 'buf'.
|
* Add an overflow page to the bucket whose last page is pointed to by 'buf'.
|
||||||
*
|
*
|
||||||
* On entry, the caller must hold a pin but no lock on 'buf'. The pin is
|
* On entry, the caller must hold a pin but no lock on 'buf'. The pin is
|
||||||
* dropped before exiting (we assume the caller is not interested in 'buf'
|
* dropped before exiting (we assume the caller is not interested in 'buf'
|
||||||
* anymore). The returned overflow page will be pinned and write-locked;
|
* anymore). The returned overflow page will be pinned and write-locked;
|
||||||
* it is guaranteed to be empty.
|
* it is guaranteed to be empty.
|
||||||
@ -88,12 +88,12 @@ blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
|
|||||||
* That buffer is returned in the same state.
|
* That buffer is returned in the same state.
|
||||||
*
|
*
|
||||||
* The caller must hold at least share lock on the bucket, to ensure that
|
* The caller must hold at least share lock on the bucket, to ensure that
|
||||||
* no one else tries to compact the bucket meanwhile. This guarantees that
|
* no one else tries to compact the bucket meanwhile. This guarantees that
|
||||||
* 'buf' won't stop being part of the bucket while it's unlocked.
|
* 'buf' won't stop being part of the bucket while it's unlocked.
|
||||||
*
|
*
|
||||||
* NB: since this could be executed concurrently by multiple processes,
|
* NB: since this could be executed concurrently by multiple processes,
|
||||||
* one should not assume that the returned overflow page will be the
|
* one should not assume that the returned overflow page will be the
|
||||||
* immediate successor of the originally passed 'buf'. Additional overflow
|
* immediate successor of the originally passed 'buf'. Additional overflow
|
||||||
* pages might have been added to the bucket chain in between.
|
* pages might have been added to the bucket chain in between.
|
||||||
*/
|
*/
|
||||||
Buffer
|
Buffer
|
||||||
@ -197,7 +197,7 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
|
|||||||
/* outer loop iterates once per bitmap page */
|
/* outer loop iterates once per bitmap page */
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
BlockNumber mapblkno;
|
BlockNumber mapblkno;
|
||||||
Page mappage;
|
Page mappage;
|
||||||
uint32 last_inpage;
|
uint32 last_inpage;
|
||||||
|
|
||||||
@ -274,9 +274,9 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
|
|||||||
blkno = bitno_to_blkno(metap, bit);
|
blkno = bitno_to_blkno(metap, bit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust hashm_firstfree to avoid redundant searches. But don't
|
* Adjust hashm_firstfree to avoid redundant searches. But don't risk
|
||||||
* risk changing it if someone moved it while we were searching
|
* changing it if someone moved it while we were searching bitmap
|
||||||
* bitmap pages.
|
* pages.
|
||||||
*/
|
*/
|
||||||
if (metap->hashm_firstfree == orig_firstfree)
|
if (metap->hashm_firstfree == orig_firstfree)
|
||||||
metap->hashm_firstfree = bit + 1;
|
metap->hashm_firstfree = bit + 1;
|
||||||
@ -304,9 +304,9 @@ found:
|
|||||||
blkno = bitno_to_blkno(metap, bit);
|
blkno = bitno_to_blkno(metap, bit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust hashm_firstfree to avoid redundant searches. But don't
|
* Adjust hashm_firstfree to avoid redundant searches. But don't risk
|
||||||
* risk changing it if someone moved it while we were searching
|
* changing it if someone moved it while we were searching bitmap
|
||||||
* bitmap pages.
|
* pages.
|
||||||
*/
|
*/
|
||||||
if (metap->hashm_firstfree == orig_firstfree)
|
if (metap->hashm_firstfree == orig_firstfree)
|
||||||
{
|
{
|
||||||
@ -396,7 +396,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
/*
|
/*
|
||||||
* Fix up the bucket chain. this is a doubly-linked list, so we must
|
* Fix up the bucket chain. this is a doubly-linked list, so we must
|
||||||
* fix up the bucket chain members behind and ahead of the overflow
|
* fix up the bucket chain members behind and ahead of the overflow
|
||||||
* page being deleted. No concurrency issues since we hold exclusive
|
* page being deleted. No concurrency issues since we hold exclusive
|
||||||
* lock on the entire bucket.
|
* lock on the entire bucket.
|
||||||
*/
|
*/
|
||||||
if (BlockNumberIsValid(prevblkno))
|
if (BlockNumberIsValid(prevblkno))
|
||||||
@ -488,7 +488,8 @@ _hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* It is okay to write-lock the new bitmap page while holding metapage
|
* It is okay to write-lock the new bitmap page while holding metapage
|
||||||
* write lock, because no one else could be contending for the new page.
|
* write lock, because no one else could be contending for the new
|
||||||
|
* page.
|
||||||
*
|
*
|
||||||
* There is some loss of concurrency in possibly doing I/O for the new
|
* There is some loss of concurrency in possibly doing I/O for the new
|
||||||
* page while holding the metapage lock, but this path is taken so
|
* page while holding the metapage lock, but this path is taken so
|
||||||
@ -654,8 +655,8 @@ _hash_squeezebucket(Relation rel,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* delete the tuple from the "read" page. PageIndexTupleDelete
|
* delete the tuple from the "read" page. PageIndexTupleDelete
|
||||||
* repacks the ItemId array, so 'roffnum' will be "advanced" to
|
* repacks the ItemId array, so 'roffnum' will be "advanced"
|
||||||
* the "next" ItemId.
|
* to the "next" ItemId.
|
||||||
*/
|
*/
|
||||||
PageIndexTupleDelete(rpage, roffnum);
|
PageIndexTupleDelete(rpage, roffnum);
|
||||||
}
|
}
|
||||||
@ -667,8 +668,9 @@ _hash_squeezebucket(Relation rel,
|
|||||||
* Tricky point here: if our read and write pages are adjacent in the
|
* Tricky point here: if our read and write pages are adjacent in the
|
||||||
* bucket chain, our write lock on wbuf will conflict with
|
* bucket chain, our write lock on wbuf will conflict with
|
||||||
* _hash_freeovflpage's attempt to update the sibling links of the
|
* _hash_freeovflpage's attempt to update the sibling links of the
|
||||||
* removed page. However, in that case we are done anyway, so we can
|
* removed page. However, in that case we are done anyway, so we
|
||||||
* simply drop the write lock before calling _hash_freeovflpage.
|
* can simply drop the write lock before calling
|
||||||
|
* _hash_freeovflpage.
|
||||||
*/
|
*/
|
||||||
if (PageIsEmpty(rpage))
|
if (PageIsEmpty(rpage))
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.45 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.46 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Postgres hash pages look like ordinary relation pages. The opaque
|
* Postgres hash pages look like ordinary relation pages. The opaque
|
||||||
@ -35,11 +35,11 @@
|
|||||||
|
|
||||||
|
|
||||||
static void _hash_splitbucket(Relation rel, Buffer metabuf,
|
static void _hash_splitbucket(Relation rel, Buffer metabuf,
|
||||||
Bucket obucket, Bucket nbucket,
|
Bucket obucket, Bucket nbucket,
|
||||||
BlockNumber start_oblkno,
|
BlockNumber start_oblkno,
|
||||||
BlockNumber start_nblkno,
|
BlockNumber start_nblkno,
|
||||||
uint32 maxbucket,
|
uint32 maxbucket,
|
||||||
uint32 highmask, uint32 lowmask);
|
uint32 highmask, uint32 lowmask);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -47,7 +47,7 @@ static void _hash_splitbucket(Relation rel, Buffer metabuf,
|
|||||||
* of the locking rules). However, we can skip taking lmgr locks when the
|
* of the locking rules). However, we can skip taking lmgr locks when the
|
||||||
* index is local to the current backend (ie, either temp or new in the
|
* index is local to the current backend (ie, either temp or new in the
|
||||||
* current transaction). No one else can see it, so there's no reason to
|
* current transaction). No one else can see it, so there's no reason to
|
||||||
* take locks. We still take buffer-level locks, but not lmgr locks.
|
* take locks. We still take buffer-level locks, but not lmgr locks.
|
||||||
*/
|
*/
|
||||||
#define USELOCKING(rel) (!RELATION_IS_LOCAL(rel))
|
#define USELOCKING(rel) (!RELATION_IS_LOCAL(rel))
|
||||||
|
|
||||||
@ -239,13 +239,13 @@ _hash_metapinit(Relation rel)
|
|||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the target fill factor (tuples per bucket) for this index.
|
* Determine the target fill factor (tuples per bucket) for this
|
||||||
* The idea is to make the fill factor correspond to pages about 3/4ths
|
* index. The idea is to make the fill factor correspond to pages
|
||||||
* full. We can compute it exactly if the index datatype is fixed-width,
|
* about 3/4ths full. We can compute it exactly if the index datatype
|
||||||
* but for var-width there's some guessing involved.
|
* is fixed-width, but for var-width there's some guessing involved.
|
||||||
*/
|
*/
|
||||||
data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid,
|
data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid,
|
||||||
RelationGetDescr(rel)->attrs[0]->atttypmod);
|
RelationGetDescr(rel)->attrs[0]->atttypmod);
|
||||||
item_width = MAXALIGN(sizeof(HashItemData)) + MAXALIGN(data_width) +
|
item_width = MAXALIGN(sizeof(HashItemData)) + MAXALIGN(data_width) +
|
||||||
sizeof(ItemIdData); /* include the line pointer */
|
sizeof(ItemIdData); /* include the line pointer */
|
||||||
ffactor = (BLCKSZ * 3 / 4) / item_width;
|
ffactor = (BLCKSZ * 3 / 4) / item_width;
|
||||||
@ -288,8 +288,9 @@ _hash_metapinit(Relation rel)
|
|||||||
metap->hashm_procid = index_getprocid(rel, 1, HASHPROC);
|
metap->hashm_procid = index_getprocid(rel, 1, HASHPROC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We initialize the index with two buckets, 0 and 1, occupying physical
|
* We initialize the index with two buckets, 0 and 1, occupying
|
||||||
* blocks 1 and 2. The first freespace bitmap page is in block 3.
|
* physical blocks 1 and 2. The first freespace bitmap page is in
|
||||||
|
* block 3.
|
||||||
*/
|
*/
|
||||||
metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */
|
metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */
|
||||||
metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */
|
metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */
|
||||||
@ -297,7 +298,7 @@ _hash_metapinit(Relation rel)
|
|||||||
MemSet((char *) metap->hashm_spares, 0, sizeof(metap->hashm_spares));
|
MemSet((char *) metap->hashm_spares, 0, sizeof(metap->hashm_spares));
|
||||||
MemSet((char *) metap->hashm_mapp, 0, sizeof(metap->hashm_mapp));
|
MemSet((char *) metap->hashm_mapp, 0, sizeof(metap->hashm_mapp));
|
||||||
|
|
||||||
metap->hashm_spares[1] = 1; /* the first bitmap page is only spare */
|
metap->hashm_spares[1] = 1; /* the first bitmap page is only spare */
|
||||||
metap->hashm_ovflpoint = 1;
|
metap->hashm_ovflpoint = 1;
|
||||||
metap->hashm_firstfree = 0;
|
metap->hashm_firstfree = 0;
|
||||||
|
|
||||||
@ -319,8 +320,8 @@ _hash_metapinit(Relation rel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize first bitmap page. Can't do this until we
|
* Initialize first bitmap page. Can't do this until we create the
|
||||||
* create the first two buckets, else smgr will complain.
|
* first two buckets, else smgr will complain.
|
||||||
*/
|
*/
|
||||||
_hash_initbitmap(rel, metap, 3);
|
_hash_initbitmap(rel, metap, 3);
|
||||||
|
|
||||||
@ -362,17 +363,18 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
uint32 lowmask;
|
uint32 lowmask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain the page-zero lock to assert the right to begin a split
|
* Obtain the page-zero lock to assert the right to begin a split (see
|
||||||
* (see README).
|
* README).
|
||||||
*
|
*
|
||||||
* Note: deadlock should be impossible here. Our own backend could only
|
* Note: deadlock should be impossible here. Our own backend could only
|
||||||
* be holding bucket sharelocks due to stopped indexscans; those will not
|
* be holding bucket sharelocks due to stopped indexscans; those will
|
||||||
* block other holders of the page-zero lock, who are only interested in
|
* not block other holders of the page-zero lock, who are only
|
||||||
* acquiring bucket sharelocks themselves. Exclusive bucket locks are
|
* interested in acquiring bucket sharelocks themselves. Exclusive
|
||||||
* only taken here and in hashbulkdelete, and neither of these operations
|
* bucket locks are only taken here and in hashbulkdelete, and neither
|
||||||
* needs any additional locks to complete. (If, due to some flaw in this
|
* of these operations needs any additional locks to complete. (If,
|
||||||
* reasoning, we manage to deadlock anyway, it's okay to error out; the
|
* due to some flaw in this reasoning, we manage to deadlock anyway,
|
||||||
* index will be left in a consistent state.)
|
* it's okay to error out; the index will be left in a consistent
|
||||||
|
* state.)
|
||||||
*/
|
*/
|
||||||
_hash_getlock(rel, 0, HASH_EXCLUSIVE);
|
_hash_getlock(rel, 0, HASH_EXCLUSIVE);
|
||||||
|
|
||||||
@ -383,8 +385,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if split is still needed; someone else might have already
|
* Check to see if split is still needed; someone else might have
|
||||||
* done one while we waited for the lock.
|
* already done one while we waited for the lock.
|
||||||
*
|
*
|
||||||
* Make sure this stays in sync with_hash_doinsert()
|
* Make sure this stays in sync with_hash_doinsert()
|
||||||
*/
|
*/
|
||||||
@ -394,16 +396,16 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine which bucket is to be split, and attempt to lock the old
|
* Determine which bucket is to be split, and attempt to lock the old
|
||||||
* bucket. If we can't get the lock, give up.
|
* bucket. If we can't get the lock, give up.
|
||||||
*
|
*
|
||||||
* The lock protects us against other backends, but not against our own
|
* The lock protects us against other backends, but not against our own
|
||||||
* backend. Must check for active scans separately.
|
* backend. Must check for active scans separately.
|
||||||
*
|
*
|
||||||
* Ideally we would lock the new bucket too before proceeding, but if
|
* Ideally we would lock the new bucket too before proceeding, but if we
|
||||||
* we are about to cross a splitpoint then the BUCKET_TO_BLKNO mapping
|
* are about to cross a splitpoint then the BUCKET_TO_BLKNO mapping
|
||||||
* isn't correct yet. For simplicity we update the metapage first and
|
* isn't correct yet. For simplicity we update the metapage first and
|
||||||
* then lock. This should be okay because no one else should be trying
|
* then lock. This should be okay because no one else should be
|
||||||
* to lock the new bucket yet...
|
* trying to lock the new bucket yet...
|
||||||
*/
|
*/
|
||||||
new_bucket = metap->hashm_maxbucket + 1;
|
new_bucket = metap->hashm_maxbucket + 1;
|
||||||
old_bucket = (new_bucket & metap->hashm_lowmask);
|
old_bucket = (new_bucket & metap->hashm_lowmask);
|
||||||
@ -417,7 +419,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay to proceed with split. Update the metapage bucket mapping info.
|
* Okay to proceed with split. Update the metapage bucket mapping
|
||||||
|
* info.
|
||||||
*/
|
*/
|
||||||
metap->hashm_maxbucket = new_bucket;
|
metap->hashm_maxbucket = new_bucket;
|
||||||
|
|
||||||
@ -431,11 +434,11 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
/*
|
/*
|
||||||
* If the split point is increasing (hashm_maxbucket's log base 2
|
* If the split point is increasing (hashm_maxbucket's log base 2
|
||||||
* increases), we need to adjust the hashm_spares[] array and
|
* increases), we need to adjust the hashm_spares[] array and
|
||||||
* hashm_ovflpoint so that future overflow pages will be created beyond
|
* hashm_ovflpoint so that future overflow pages will be created
|
||||||
* this new batch of bucket pages.
|
* beyond this new batch of bucket pages.
|
||||||
*
|
*
|
||||||
* XXX should initialize new bucket pages to prevent out-of-order
|
* XXX should initialize new bucket pages to prevent out-of-order page
|
||||||
* page creation? Don't wanna do it right here though.
|
* creation? Don't wanna do it right here though.
|
||||||
*/
|
*/
|
||||||
spare_ndx = _hash_log2(metap->hashm_maxbucket + 1);
|
spare_ndx = _hash_log2(metap->hashm_maxbucket + 1);
|
||||||
if (spare_ndx > metap->hashm_ovflpoint)
|
if (spare_ndx > metap->hashm_ovflpoint)
|
||||||
@ -456,9 +459,10 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
/*
|
/*
|
||||||
* Copy bucket mapping info now; this saves re-accessing the meta page
|
* Copy bucket mapping info now; this saves re-accessing the meta page
|
||||||
* inside _hash_splitbucket's inner loop. Note that once we drop the
|
* inside _hash_splitbucket's inner loop. Note that once we drop the
|
||||||
* split lock, other splits could begin, so these values might be out of
|
* split lock, other splits could begin, so these values might be out
|
||||||
* date before _hash_splitbucket finishes. That's okay, since all it
|
* of date before _hash_splitbucket finishes. That's okay, since all
|
||||||
* needs is to tell which of these two buckets to map hashkeys into.
|
* it needs is to tell which of these two buckets to map hashkeys
|
||||||
|
* into.
|
||||||
*/
|
*/
|
||||||
maxbucket = metap->hashm_maxbucket;
|
maxbucket = metap->hashm_maxbucket;
|
||||||
highmask = metap->hashm_highmask;
|
highmask = metap->hashm_highmask;
|
||||||
@ -539,8 +543,8 @@ _hash_splitbucket(Relation rel,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* It should be okay to simultaneously write-lock pages from each
|
* It should be okay to simultaneously write-lock pages from each
|
||||||
* bucket, since no one else can be trying to acquire buffer lock
|
* bucket, since no one else can be trying to acquire buffer lock on
|
||||||
* on pages of either bucket.
|
* pages of either bucket.
|
||||||
*/
|
*/
|
||||||
oblkno = start_oblkno;
|
oblkno = start_oblkno;
|
||||||
nblkno = start_nblkno;
|
nblkno = start_nblkno;
|
||||||
@ -562,9 +566,9 @@ _hash_splitbucket(Relation rel,
|
|||||||
nopaque->hasho_filler = HASHO_FILL;
|
nopaque->hasho_filler = HASHO_FILL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Partition the tuples in the old bucket between the old bucket and the
|
* Partition the tuples in the old bucket between the old bucket and
|
||||||
* new bucket, advancing along the old bucket's overflow bucket chain
|
* the new bucket, advancing along the old bucket's overflow bucket
|
||||||
* and adding overflow pages to the new bucket as needed.
|
* chain and adding overflow pages to the new bucket as needed.
|
||||||
*/
|
*/
|
||||||
ooffnum = FirstOffsetNumber;
|
ooffnum = FirstOffsetNumber;
|
||||||
omaxoffnum = PageGetMaxOffsetNumber(opage);
|
omaxoffnum = PageGetMaxOffsetNumber(opage);
|
||||||
@ -582,9 +586,10 @@ _hash_splitbucket(Relation rel,
|
|||||||
oblkno = oopaque->hasho_nextblkno;
|
oblkno = oopaque->hasho_nextblkno;
|
||||||
if (!BlockNumberIsValid(oblkno))
|
if (!BlockNumberIsValid(oblkno))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we ran out of tuples on this particular page, but we
|
* we ran out of tuples on this particular page, but we have
|
||||||
* have more overflow pages; advance to next page.
|
* more overflow pages; advance to next page.
|
||||||
*/
|
*/
|
||||||
_hash_wrtbuf(rel, obuf);
|
_hash_wrtbuf(rel, obuf);
|
||||||
|
|
||||||
@ -600,8 +605,8 @@ _hash_splitbucket(Relation rel,
|
|||||||
/*
|
/*
|
||||||
* Re-hash the tuple to determine which bucket it now belongs in.
|
* Re-hash the tuple to determine which bucket it now belongs in.
|
||||||
*
|
*
|
||||||
* It is annoying to call the hash function while holding locks,
|
* It is annoying to call the hash function while holding locks, but
|
||||||
* but releasing and relocking the page for each tuple is unappealing
|
* releasing and relocking the page for each tuple is unappealing
|
||||||
* too.
|
* too.
|
||||||
*/
|
*/
|
||||||
hitem = (HashItem) PageGetItem(opage, PageGetItemId(opage, ooffnum));
|
hitem = (HashItem) PageGetItem(opage, PageGetItemId(opage, ooffnum));
|
||||||
@ -666,10 +671,11 @@ _hash_splitbucket(Relation rel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're at the end of the old bucket chain, so we're done partitioning
|
* We're at the end of the old bucket chain, so we're done
|
||||||
* the tuples. Before quitting, call _hash_squeezebucket to ensure the
|
* partitioning the tuples. Before quitting, call _hash_squeezebucket
|
||||||
* tuples remaining in the old bucket (including the overflow pages) are
|
* to ensure the tuples remaining in the old bucket (including the
|
||||||
* packed as tightly as possible. The new bucket is already tight.
|
* overflow pages) are packed as tightly as possible. The new bucket
|
||||||
|
* is already tight.
|
||||||
*/
|
*/
|
||||||
_hash_wrtbuf(rel, obuf);
|
_hash_wrtbuf(rel, obuf);
|
||||||
_hash_wrtbuf(rel, nbuf);
|
_hash_wrtbuf(rel, nbuf);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashscan.c,v 1.36 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashscan.c,v 1.37 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,9 +44,9 @@ ReleaseResources_hash(void)
|
|||||||
HashScanList next;
|
HashScanList next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: this should be a no-op during normal query shutdown.
|
* Note: this should be a no-op during normal query shutdown. However,
|
||||||
* However, in an abort situation ExecutorEnd is not called and so
|
* in an abort situation ExecutorEnd is not called and so there may be
|
||||||
* there may be open index scans to clean up.
|
* open index scans to clean up.
|
||||||
*/
|
*/
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.36 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.37 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -137,12 +137,13 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
* We do not support hash scans with no index qualification, because
|
* We do not support hash scans with no index qualification, because
|
||||||
* we would have to read the whole index rather than just one bucket.
|
* we would have to read the whole index rather than just one bucket.
|
||||||
* That creates a whole raft of problems, since we haven't got a
|
* That creates a whole raft of problems, since we haven't got a
|
||||||
* practical way to lock all the buckets against splits or compactions.
|
* practical way to lock all the buckets against splits or
|
||||||
|
* compactions.
|
||||||
*/
|
*/
|
||||||
if (scan->numberOfKeys < 1)
|
if (scan->numberOfKeys < 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("hash indexes do not support whole-index scans")));
|
errmsg("hash indexes do not support whole-index scans")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the constant in the index qual is NULL, assume it cannot match
|
* If the constant in the index qual is NULL, assume it cannot match
|
||||||
@ -182,7 +183,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
_hash_relbuf(rel, metabuf);
|
_hash_relbuf(rel, metabuf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquire share lock on target bucket; then we can release split lock.
|
* Acquire share lock on target bucket; then we can release split
|
||||||
|
* lock.
|
||||||
*/
|
*/
|
||||||
_hash_getlock(rel, blkno, HASH_SHARE);
|
_hash_getlock(rel, blkno, HASH_SHARE);
|
||||||
|
|
||||||
@ -287,9 +289,8 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
|||||||
while (offnum > maxoff)
|
while (offnum > maxoff)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* either this page is empty
|
* either this page is empty (maxoff ==
|
||||||
* (maxoff == InvalidOffsetNumber)
|
* InvalidOffsetNumber) or we ran off the end.
|
||||||
* or we ran off the end.
|
|
||||||
*/
|
*/
|
||||||
_hash_readnext(rel, &buf, &page, &opaque);
|
_hash_readnext(rel, &buf, &page, &opaque);
|
||||||
if (BufferIsValid(buf))
|
if (BufferIsValid(buf))
|
||||||
@ -315,15 +316,12 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
|||||||
while (offnum < FirstOffsetNumber)
|
while (offnum < FirstOffsetNumber)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* either this page is empty
|
* either this page is empty (offnum ==
|
||||||
* (offnum == InvalidOffsetNumber)
|
* InvalidOffsetNumber) or we ran off the end.
|
||||||
* or we ran off the end.
|
|
||||||
*/
|
*/
|
||||||
_hash_readprev(rel, &buf, &page, &opaque);
|
_hash_readprev(rel, &buf, &page, &opaque);
|
||||||
if (BufferIsValid(buf))
|
if (BufferIsValid(buf))
|
||||||
{
|
|
||||||
maxoff = offnum = PageGetMaxOffsetNumber(page);
|
maxoff = offnum = PageGetMaxOffsetNumber(page);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* end of bucket */
|
/* end of bucket */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.39 2004/08/29 04:12:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.40 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -113,6 +113,7 @@ void
|
|||||||
_hash_checkpage(Relation rel, Page page, int flags)
|
_hash_checkpage(Relation rel, Page page, int flags)
|
||||||
{
|
{
|
||||||
Assert(page);
|
Assert(page);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When checking the metapage, always verify magic number and version.
|
* When checking the metapage, always verify magic number and version.
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.172 2004/08/29 04:12:20 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.173 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -75,9 +75,9 @@ initscan(HeapScanDesc scan, ScanKey key)
|
|||||||
/*
|
/*
|
||||||
* Determine the number of blocks we have to scan.
|
* Determine the number of blocks we have to scan.
|
||||||
*
|
*
|
||||||
* It is sufficient to do this once at scan start, since any tuples
|
* It is sufficient to do this once at scan start, since any tuples added
|
||||||
* added while the scan is in progress will be invisible to my
|
* while the scan is in progress will be invisible to my transaction
|
||||||
* transaction anyway...
|
* anyway...
|
||||||
*/
|
*/
|
||||||
scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
|
scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
|
||||||
|
|
||||||
@ -1141,12 +1141,13 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
|
|||||||
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId());
|
HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId());
|
||||||
HeapTupleHeaderSetCmin(tup->t_data, cid);
|
HeapTupleHeaderSetCmin(tup->t_data, cid);
|
||||||
HeapTupleHeaderSetCmax(tup->t_data, 0); /* zero out Datum fields */
|
HeapTupleHeaderSetCmax(tup->t_data, 0); /* zero out Datum fields */
|
||||||
tup->t_tableOid = relation->rd_id;
|
tup->t_tableOid = relation->rd_id;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the new tuple is too big for storage or contains already toasted
|
* If the new tuple is too big for storage or contains already toasted
|
||||||
* out-of-line attributes from some other relation, invoke the toaster.
|
* out-of-line attributes from some other relation, invoke the
|
||||||
|
* toaster.
|
||||||
*/
|
*/
|
||||||
if (HeapTupleHasExternal(tup) ||
|
if (HeapTupleHasExternal(tup) ||
|
||||||
(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
|
(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
|
||||||
@ -1273,7 +1274,7 @@ simple_heap_insert(Relation relation, HeapTuple tup)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
heap_delete(Relation relation, ItemPointer tid,
|
heap_delete(Relation relation, ItemPointer tid,
|
||||||
ItemPointer ctid, CommandId cid, Snapshot crosscheck, bool wait)
|
ItemPointer ctid, CommandId cid, Snapshot crosscheck, bool wait)
|
||||||
{
|
{
|
||||||
ItemId lp;
|
ItemId lp;
|
||||||
HeapTupleData tp;
|
HeapTupleData tp;
|
||||||
@ -1404,9 +1405,9 @@ l1:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If the tuple has toasted out-of-line attributes, we need to delete
|
* If the tuple has toasted out-of-line attributes, we need to delete
|
||||||
* those items too. We have to do this before WriteBuffer because we need
|
* those items too. We have to do this before WriteBuffer because we
|
||||||
* to look at the contents of the tuple, but it's OK to release the
|
* need to look at the contents of the tuple, but it's OK to release
|
||||||
* context lock on the buffer first.
|
* the context lock on the buffer first.
|
||||||
*/
|
*/
|
||||||
if (HeapTupleHasExternal(&tp))
|
if (HeapTupleHasExternal(&tp))
|
||||||
heap_tuple_toast_attrs(relation, NULL, &tp);
|
heap_tuple_toast_attrs(relation, NULL, &tp);
|
||||||
@ -1443,7 +1444,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
|
|||||||
result = heap_delete(relation, tid,
|
result = heap_delete(relation, tid,
|
||||||
&ctid,
|
&ctid,
|
||||||
GetCurrentCommandId(), SnapshotAny,
|
GetCurrentCommandId(), SnapshotAny,
|
||||||
true /* wait for commit */);
|
true /* wait for commit */ );
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case HeapTupleSelfUpdated:
|
case HeapTupleSelfUpdated:
|
||||||
@ -1490,7 +1491,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
|
heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
|
||||||
ItemPointer ctid, CommandId cid, Snapshot crosscheck, bool wait)
|
ItemPointer ctid, CommandId cid, Snapshot crosscheck, bool wait)
|
||||||
{
|
{
|
||||||
ItemId lp;
|
ItemId lp;
|
||||||
HeapTupleData oldtup;
|
HeapTupleData oldtup;
|
||||||
@ -1804,7 +1805,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
|
|||||||
result = heap_update(relation, otid, tup,
|
result = heap_update(relation, otid, tup,
|
||||||
&ctid,
|
&ctid,
|
||||||
GetCurrentCommandId(), SnapshotAny,
|
GetCurrentCommandId(), SnapshotAny,
|
||||||
true /* wait for commit */);
|
true /* wait for commit */ );
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case HeapTupleSelfUpdated:
|
case HeapTupleSelfUpdated:
|
||||||
@ -2198,8 +2199,8 @@ heap_xlog_newpage(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
|||||||
Page page;
|
Page page;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: the NEWPAGE log record is used for both heaps and indexes,
|
* Note: the NEWPAGE log record is used for both heaps and indexes, so
|
||||||
* so do not do anything that assumes we are touching a heap.
|
* do not do anything that assumes we are touching a heap.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
|
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
|
||||||
@ -2668,7 +2669,7 @@ static void
|
|||||||
out_target(char *buf, xl_heaptid *target)
|
out_target(char *buf, xl_heaptid *target)
|
||||||
{
|
{
|
||||||
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u",
|
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u",
|
||||||
target->node.spcNode, target->node.dbNode, target->node.relNode,
|
target->node.spcNode, target->node.dbNode, target->node.relNode,
|
||||||
ItemPointerGetBlockNumber(&(target->tid)),
|
ItemPointerGetBlockNumber(&(target->tid)),
|
||||||
ItemPointerGetOffsetNumber(&(target->tid)));
|
ItemPointerGetOffsetNumber(&(target->tid)));
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.44 2004/08/29 04:12:20 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.45 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -288,13 +288,13 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
|||||||
/*
|
/*
|
||||||
* Get the tuple descriptor and break down the tuple into fields.
|
* Get the tuple descriptor and break down the tuple into fields.
|
||||||
*
|
*
|
||||||
* NOTE: it's debatable whether to use heap_deformtuple() here or
|
* NOTE: it's debatable whether to use heap_deformtuple() here or just
|
||||||
* just heap_getattr() only the varlena columns. The latter could
|
* heap_getattr() only the varlena columns. The latter could win if
|
||||||
* win if there are few varlena columns and many non-varlena ones.
|
* there are few varlena columns and many non-varlena ones. However,
|
||||||
* However, heap_deformtuple costs only O(N) while the heap_getattr
|
* heap_deformtuple costs only O(N) while the heap_getattr way would
|
||||||
* way would cost O(N^2) if there are many varlena columns, so it
|
* cost O(N^2) if there are many varlena columns, so it seems better
|
||||||
* seems better to err on the side of linear cost. (We won't even
|
* to err on the side of linear cost. (We won't even be here unless
|
||||||
* be here unless there's at least one varlena column, by the way.)
|
* there's at least one varlena column, by the way.)
|
||||||
*/
|
*/
|
||||||
tupleDesc = rel->rd_att;
|
tupleDesc = rel->rd_att;
|
||||||
att = tupleDesc->attrs;
|
att = tupleDesc->attrs;
|
||||||
@ -311,7 +311,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
|||||||
{
|
{
|
||||||
if (att[i]->attlen == -1)
|
if (att[i]->attlen == -1)
|
||||||
{
|
{
|
||||||
Datum value = toast_values[i];
|
Datum value = toast_values[i];
|
||||||
|
|
||||||
if (toast_nulls[i] != 'n' && VARATT_IS_EXTERNAL(value))
|
if (toast_nulls[i] != 'n' && VARATT_IS_EXTERNAL(value))
|
||||||
toast_delete_datum(rel, value);
|
toast_delete_datum(rel, value);
|
||||||
@ -791,7 +791,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
|||||||
*
|
*
|
||||||
* If a Datum is of composite type, "flatten" it to contain no toasted fields.
|
* If a Datum is of composite type, "flatten" it to contain no toasted fields.
|
||||||
* This must be invoked on any potentially-composite field that is to be
|
* This must be invoked on any potentially-composite field that is to be
|
||||||
* inserted into a tuple. Doing this preserves the invariant that toasting
|
* inserted into a tuple. Doing this preserves the invariant that toasting
|
||||||
* goes only one level deep in a tuple.
|
* goes only one level deep in a tuple.
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -1105,7 +1105,7 @@ toast_delete_datum(Relation rel, Datum value)
|
|||||||
ScanKeyInit(&toastkey,
|
ScanKeyInit(&toastkey,
|
||||||
(AttrNumber) 1,
|
(AttrNumber) 1,
|
||||||
BTEqualStrategyNumber, F_OIDEQ,
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the chunks by index
|
* Find the chunks by index
|
||||||
@ -1176,7 +1176,7 @@ toast_fetch_datum(varattrib *attr)
|
|||||||
ScanKeyInit(&toastkey,
|
ScanKeyInit(&toastkey,
|
||||||
(AttrNumber) 1,
|
(AttrNumber) 1,
|
||||||
BTEqualStrategyNumber, F_OIDEQ,
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the chunks by index
|
* Read the chunks by index
|
||||||
@ -1330,7 +1330,7 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
|
|||||||
ScanKeyInit(&toastkey[0],
|
ScanKeyInit(&toastkey[0],
|
||||||
(AttrNumber) 1,
|
(AttrNumber) 1,
|
||||||
BTEqualStrategyNumber, F_OIDEQ,
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use equality condition for one chunk, a range condition otherwise:
|
* Use equality condition for one chunk, a range condition otherwise:
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.115 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.116 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -200,26 +200,26 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
|||||||
* We can skip items that are marked killed.
|
* We can skip items that are marked killed.
|
||||||
*
|
*
|
||||||
* Formerly, we applied _bt_isequal() before checking the kill
|
* Formerly, we applied _bt_isequal() before checking the kill
|
||||||
* flag, so as to fall out of the item loop as soon as possible.
|
* flag, so as to fall out of the item loop as soon as
|
||||||
* However, in the presence of heavy update activity an index
|
* possible. However, in the presence of heavy update activity
|
||||||
* may contain many killed items with the same key; running
|
* an index may contain many killed items with the same key;
|
||||||
* _bt_isequal() on each killed item gets expensive. Furthermore
|
* running _bt_isequal() on each killed item gets expensive.
|
||||||
* it is likely that the non-killed version of each key appears
|
* Furthermore it is likely that the non-killed version of
|
||||||
* first, so that we didn't actually get to exit any sooner anyway.
|
* each key appears first, so that we didn't actually get to
|
||||||
* So now we just advance over killed items as quickly as we can.
|
* exit any sooner anyway. So now we just advance over killed
|
||||||
* We only apply _bt_isequal() when we get to a non-killed item or
|
* items as quickly as we can. We only apply _bt_isequal()
|
||||||
* the end of the page.
|
* when we get to a non-killed item or the end of the page.
|
||||||
*/
|
*/
|
||||||
if (!ItemIdDeleted(curitemid))
|
if (!ItemIdDeleted(curitemid))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's
|
* _bt_compare returns 0 for (1,NULL) and (1,NULL) -
|
||||||
* how we handling NULLs - and so we must not use _bt_compare
|
* this's how we handling NULLs - and so we must not use
|
||||||
* in real comparison, but only for ordering/finding items on
|
* _bt_compare in real comparison, but only for
|
||||||
* pages. - vadim 03/24/97
|
* ordering/finding items on pages. - vadim 03/24/97
|
||||||
*/
|
*/
|
||||||
if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey))
|
if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey))
|
||||||
break; /* we're past all the equal tuples */
|
break; /* we're past all the equal tuples */
|
||||||
|
|
||||||
/* okay, we gotta fetch the heap tuple ... */
|
/* okay, we gotta fetch the heap tuple ... */
|
||||||
cbti = (BTItem) PageGetItem(page, curitemid);
|
cbti = (BTItem) PageGetItem(page, curitemid);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.79 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.80 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||||
@ -276,8 +276,8 @@ _bt_getroot(Relation rel, int access)
|
|||||||
rootlevel = metad->btm_fastlevel;
|
rootlevel = metad->btm_fastlevel;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are done with the metapage; arrange to release it via
|
* We are done with the metapage; arrange to release it via first
|
||||||
* first _bt_relandgetbuf call
|
* _bt_relandgetbuf call
|
||||||
*/
|
*/
|
||||||
rootbuf = metabuf;
|
rootbuf = metabuf;
|
||||||
|
|
||||||
@ -368,8 +368,8 @@ _bt_gettrueroot(Relation rel)
|
|||||||
rootlevel = metad->btm_level;
|
rootlevel = metad->btm_level;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are done with the metapage; arrange to release it via
|
* We are done with the metapage; arrange to release it via first
|
||||||
* first _bt_relandgetbuf call
|
* _bt_relandgetbuf call
|
||||||
*/
|
*/
|
||||||
rootbuf = metabuf;
|
rootbuf = metabuf;
|
||||||
|
|
||||||
@ -433,21 +433,22 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
|||||||
* page could have been re-used between the time the last VACUUM
|
* page could have been re-used between the time the last VACUUM
|
||||||
* scanned it and the time the VACUUM made its FSM updates.)
|
* scanned it and the time the VACUUM made its FSM updates.)
|
||||||
*
|
*
|
||||||
* In fact, it's worse than that: we can't even assume that it's
|
* In fact, it's worse than that: we can't even assume that it's safe
|
||||||
* safe to take a lock on the reported page. If somebody else
|
* to take a lock on the reported page. If somebody else has a
|
||||||
* has a lock on it, or even worse our own caller does, we could
|
* lock on it, or even worse our own caller does, we could
|
||||||
* deadlock. (The own-caller scenario is actually not improbable.
|
* deadlock. (The own-caller scenario is actually not improbable.
|
||||||
* Consider an index on a serial or timestamp column. Nearly all
|
* Consider an index on a serial or timestamp column. Nearly all
|
||||||
* splits will be at the rightmost page, so it's entirely likely
|
* splits will be at the rightmost page, so it's entirely likely
|
||||||
* that _bt_split will call us while holding a lock on the page most
|
* that _bt_split will call us while holding a lock on the page
|
||||||
* recently acquired from FSM. A VACUUM running concurrently with
|
* most recently acquired from FSM. A VACUUM running concurrently
|
||||||
* the previous split could well have placed that page back in FSM.)
|
* with the previous split could well have placed that page back
|
||||||
|
* in FSM.)
|
||||||
*
|
*
|
||||||
* To get around that, we ask for only a conditional lock on the
|
* To get around that, we ask for only a conditional lock on the
|
||||||
* reported page. If we fail, then someone else is using the page,
|
* reported page. If we fail, then someone else is using the
|
||||||
* and we may reasonably assume it's not free. (If we happen to be
|
* page, and we may reasonably assume it's not free. (If we
|
||||||
* wrong, the worst consequence is the page will be lost to use till
|
* happen to be wrong, the worst consequence is the page will be
|
||||||
* the next VACUUM, which is no big problem.)
|
* lost to use till the next VACUUM, which is no big problem.)
|
||||||
*/
|
*/
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.88 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.89 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -155,15 +155,16 @@ _bt_moveright(Relation rel,
|
|||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When nextkey = false (normal case): if the scan key that brought us to
|
* When nextkey = false (normal case): if the scan key that brought us
|
||||||
* this page is > the high key stored on the page, then the page has split
|
* to this page is > the high key stored on the page, then the page
|
||||||
* and we need to move right. (If the scan key is equal to the high key,
|
* has split and we need to move right. (If the scan key is equal to
|
||||||
* we might or might not need to move right; have to scan the page first
|
* the high key, we might or might not need to move right; have to
|
||||||
* anyway.)
|
* scan the page first anyway.)
|
||||||
*
|
*
|
||||||
* When nextkey = true: move right if the scan key is >= page's high key.
|
* When nextkey = true: move right if the scan key is >= page's high key.
|
||||||
*
|
*
|
||||||
* The page could even have split more than once, so scan as far as needed.
|
* The page could even have split more than once, so scan as far as
|
||||||
|
* needed.
|
||||||
*
|
*
|
||||||
* We also have to move right if we followed a link that brought us to a
|
* We also have to move right if we followed a link that brought us to a
|
||||||
* dead page.
|
* dead page.
|
||||||
@ -253,13 +254,11 @@ _bt_binsrch(Relation rel,
|
|||||||
* Binary search to find the first key on the page >= scan key, or
|
* Binary search to find the first key on the page >= scan key, or
|
||||||
* first key > scankey when nextkey is true.
|
* first key > scankey when nextkey is true.
|
||||||
*
|
*
|
||||||
* For nextkey=false (cmpval=1), the loop invariant is: all slots
|
* For nextkey=false (cmpval=1), the loop invariant is: all slots before
|
||||||
* before 'low' are < scan key, all slots at or after 'high'
|
* 'low' are < scan key, all slots at or after 'high' are >= scan key.
|
||||||
* are >= scan key.
|
|
||||||
*
|
*
|
||||||
* For nextkey=true (cmpval=0), the loop invariant is: all slots
|
* For nextkey=true (cmpval=0), the loop invariant is: all slots before
|
||||||
* before 'low' are <= scan key, all slots at or after 'high'
|
* 'low' are <= scan key, all slots at or after 'high' are > scan key.
|
||||||
* are > scan key.
|
|
||||||
*
|
*
|
||||||
* We can fall out when high == low.
|
* We can fall out when high == low.
|
||||||
*/
|
*/
|
||||||
@ -285,15 +284,15 @@ _bt_binsrch(Relation rel,
|
|||||||
* At this point we have high == low, but be careful: they could point
|
* At this point we have high == low, but be careful: they could point
|
||||||
* past the last slot on the page.
|
* past the last slot on the page.
|
||||||
*
|
*
|
||||||
* On a leaf page, we always return the first key >= scan key (resp.
|
* On a leaf page, we always return the first key >= scan key (resp. >
|
||||||
* > scan key), which could be the last slot + 1.
|
* scan key), which could be the last slot + 1.
|
||||||
*/
|
*/
|
||||||
if (P_ISLEAF(opaque))
|
if (P_ISLEAF(opaque))
|
||||||
return low;
|
return low;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On a non-leaf page, return the last key < scan key (resp. <= scan key).
|
* On a non-leaf page, return the last key < scan key (resp. <= scan
|
||||||
* There must be one if _bt_compare() is playing by the rules.
|
* key). There must be one if _bt_compare() is playing by the rules.
|
||||||
*/
|
*/
|
||||||
Assert(low > P_FIRSTDATAKEY(opaque));
|
Assert(low > P_FIRSTDATAKEY(opaque));
|
||||||
|
|
||||||
@ -382,10 +381,10 @@ _bt_compare(Relation rel,
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The sk_func needs to be passed the index value as left arg
|
* The sk_func needs to be passed the index value as left arg
|
||||||
* and the sk_argument as right arg (they might be of different
|
* and the sk_argument as right arg (they might be of
|
||||||
* types). Since it is convenient for callers to think of
|
* different types). Since it is convenient for callers to
|
||||||
* _bt_compare as comparing the scankey to the index item,
|
* think of _bt_compare as comparing the scankey to the index
|
||||||
* we have to flip the sign of the comparison result.
|
* item, we have to flip the sign of the comparison result.
|
||||||
*
|
*
|
||||||
* Note: curious-looking coding is to avoid overflow if
|
* Note: curious-looking coding is to avoid overflow if
|
||||||
* comparison function returns INT_MIN. There is no risk of
|
* comparison function returns INT_MIN. There is no risk of
|
||||||
@ -497,7 +496,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
bool goback;
|
bool goback;
|
||||||
bool continuescan;
|
bool continuescan;
|
||||||
ScanKey scankeys;
|
ScanKey scankeys;
|
||||||
ScanKey *startKeys = NULL;
|
ScanKey *startKeys = NULL;
|
||||||
int keysCount = 0;
|
int keysCount = 0;
|
||||||
int i;
|
int i;
|
||||||
StrategyNumber strat_total;
|
StrategyNumber strat_total;
|
||||||
@ -521,7 +520,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
* We want to identify the keys that can be used as starting boundaries;
|
* We want to identify the keys that can be used as starting boundaries;
|
||||||
* these are =, >, or >= keys for a forward scan or =, <, <= keys for
|
* these are =, >, or >= keys for a forward scan or =, <, <= keys for
|
||||||
* a backwards scan. We can use keys for multiple attributes so long as
|
* a backwards scan. We can use keys for multiple attributes so long as
|
||||||
* the prior attributes had only =, >= (resp. =, <=) keys. Once we accept
|
* the prior attributes had only =, >= (resp. =, <=) keys. Once we accept
|
||||||
* a > or < boundary or find an attribute with no boundary (which can be
|
* a > or < boundary or find an attribute with no boundary (which can be
|
||||||
* thought of as the same as "> -infinity"), we can't use keys for any
|
* thought of as the same as "> -infinity"), we can't use keys for any
|
||||||
* attributes to its right, because it would break our simplistic notion
|
* attributes to its right, because it would break our simplistic notion
|
||||||
@ -554,13 +553,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
ScanKey cur;
|
ScanKey cur;
|
||||||
|
|
||||||
startKeys = (ScanKey *) palloc(so->numberOfKeys * sizeof(ScanKey));
|
startKeys = (ScanKey *) palloc(so->numberOfKeys * sizeof(ScanKey));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* chosen is the so-far-chosen key for the current attribute, if any.
|
* chosen is the so-far-chosen key for the current attribute, if
|
||||||
* We don't cast the decision in stone until we reach keys for the
|
* any. We don't cast the decision in stone until we reach keys
|
||||||
* next attribute.
|
* for the next attribute.
|
||||||
*/
|
*/
|
||||||
curattr = 1;
|
curattr = 1;
|
||||||
chosen = NULL;
|
chosen = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop iterates from 0 to numberOfKeys inclusive; we use the last
|
* Loop iterates from 0 to numberOfKeys inclusive; we use the last
|
||||||
* pass to handle after-last-key processing. Actual exit from the
|
* pass to handle after-last-key processing. Actual exit from the
|
||||||
@ -578,8 +579,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
if (chosen == NULL)
|
if (chosen == NULL)
|
||||||
break;
|
break;
|
||||||
startKeys[keysCount++] = chosen;
|
startKeys[keysCount++] = chosen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust strat_total, and quit if we have stored a > or < key.
|
* Adjust strat_total, and quit if we have stored a > or <
|
||||||
|
* key.
|
||||||
*/
|
*/
|
||||||
strat = chosen->sk_strategy;
|
strat = chosen->sk_strategy;
|
||||||
if (strat != BTEqualStrategyNumber)
|
if (strat != BTEqualStrategyNumber)
|
||||||
@ -589,11 +592,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
strat == BTLessStrategyNumber)
|
strat == BTLessStrategyNumber)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Done if that was the last attribute.
|
* Done if that was the last attribute.
|
||||||
*/
|
*/
|
||||||
if (i >= so->numberOfKeys)
|
if (i >= so->numberOfKeys)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset for next attr, which should be in sequence.
|
* Reset for next attr, which should be in sequence.
|
||||||
*/
|
*/
|
||||||
@ -646,8 +651,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
ScanKey cur = startKeys[i];
|
ScanKey cur = startKeys[i];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _bt_preprocess_keys disallows it, but it's place to add some code
|
* _bt_preprocess_keys disallows it, but it's place to add some
|
||||||
* later
|
* code later
|
||||||
*/
|
*/
|
||||||
if (cur->sk_flags & SK_ISNULL)
|
if (cur->sk_flags & SK_ISNULL)
|
||||||
{
|
{
|
||||||
@ -656,10 +661,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
elog(ERROR, "btree doesn't support is(not)null, yet");
|
elog(ERROR, "btree doesn't support is(not)null, yet");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If scankey operator is of default subtype, we can use the
|
* If scankey operator is of default subtype, we can use the
|
||||||
* cached comparison procedure; otherwise gotta look it up in
|
* cached comparison procedure; otherwise gotta look it up in the
|
||||||
* the catalogs.
|
* catalogs.
|
||||||
*/
|
*/
|
||||||
if (cur->sk_subtype == InvalidOid)
|
if (cur->sk_subtype == InvalidOid)
|
||||||
{
|
{
|
||||||
@ -695,43 +701,46 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Examine the selected initial-positioning strategy to determine
|
* Examine the selected initial-positioning strategy to determine
|
||||||
* exactly where we need to start the scan, and set flag variables
|
* exactly where we need to start the scan, and set flag variables to
|
||||||
* to control the code below.
|
* control the code below.
|
||||||
*
|
*
|
||||||
* If nextkey = false, _bt_search and _bt_binsrch will locate the
|
* If nextkey = false, _bt_search and _bt_binsrch will locate the first
|
||||||
* first item >= scan key. If nextkey = true, they will locate the
|
* item >= scan key. If nextkey = true, they will locate the first
|
||||||
* first item > scan key.
|
* item > scan key.
|
||||||
*
|
*
|
||||||
* If goback = true, we will then step back one item, while if
|
* If goback = true, we will then step back one item, while if goback =
|
||||||
* goback = false, we will start the scan on the located item.
|
* false, we will start the scan on the located item.
|
||||||
*
|
*
|
||||||
* it's yet other place to add some code later for is(not)null ...
|
* it's yet other place to add some code later for is(not)null ...
|
||||||
*/
|
*/
|
||||||
switch (strat_total)
|
switch (strat_total)
|
||||||
{
|
{
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find first item >= scankey, then back up one to arrive at last
|
* Find first item >= scankey, then back up one to arrive at
|
||||||
* item < scankey. (Note: this positioning strategy is only used
|
* last item < scankey. (Note: this positioning strategy is
|
||||||
* for a backward scan, so that is always the correct starting
|
* only used for a backward scan, so that is always the
|
||||||
* position.)
|
* correct starting position.)
|
||||||
*/
|
*/
|
||||||
nextkey = false;
|
nextkey = false;
|
||||||
goback = true;
|
goback = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTLessEqualStrategyNumber:
|
case BTLessEqualStrategyNumber:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find first item > scankey, then back up one to arrive at last
|
* Find first item > scankey, then back up one to arrive at
|
||||||
* item <= scankey. (Note: this positioning strategy is only used
|
* last item <= scankey. (Note: this positioning strategy is
|
||||||
* for a backward scan, so that is always the correct starting
|
* only used for a backward scan, so that is always the
|
||||||
* position.)
|
* correct starting position.)
|
||||||
*/
|
*/
|
||||||
nextkey = true;
|
nextkey = true;
|
||||||
goback = true;
|
goback = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTEqualStrategyNumber:
|
case BTEqualStrategyNumber:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a backward scan was specified, need to start with last
|
* If a backward scan was specified, need to start with last
|
||||||
* equal item not first one.
|
* equal item not first one.
|
||||||
@ -739,8 +748,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
if (ScanDirectionIsBackward(dir))
|
if (ScanDirectionIsBackward(dir))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is the same as the <= strategy. We will check
|
* This is the same as the <= strategy. We will check at
|
||||||
* at the end whether the found item is actually =.
|
* the end whether the found item is actually =.
|
||||||
*/
|
*/
|
||||||
nextkey = true;
|
nextkey = true;
|
||||||
goback = true;
|
goback = true;
|
||||||
@ -748,8 +757,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is the same as the >= strategy. We will check
|
* This is the same as the >= strategy. We will check at
|
||||||
* at the end whether the found item is actually =.
|
* the end whether the found item is actually =.
|
||||||
*/
|
*/
|
||||||
nextkey = false;
|
nextkey = false;
|
||||||
goback = false;
|
goback = false;
|
||||||
@ -757,18 +766,20 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BTGreaterEqualStrategyNumber:
|
case BTGreaterEqualStrategyNumber:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find first item >= scankey. (This is only used for
|
* Find first item >= scankey. (This is only used for forward
|
||||||
* forward scans.)
|
* scans.)
|
||||||
*/
|
*/
|
||||||
nextkey = false;
|
nextkey = false;
|
||||||
goback = false;
|
goback = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTGreaterStrategyNumber:
|
case BTGreaterStrategyNumber:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find first item > scankey. (This is only used for
|
* Find first item > scankey. (This is only used for forward
|
||||||
* forward scans.)
|
* scans.)
|
||||||
*/
|
*/
|
||||||
nextkey = true;
|
nextkey = true;
|
||||||
goback = false;
|
goback = false;
|
||||||
@ -814,23 +825,23 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
pfree(scankeys);
|
pfree(scankeys);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If nextkey = false, we are positioned at the first item >= scan key,
|
* If nextkey = false, we are positioned at the first item >= scan
|
||||||
* or possibly at the end of a page on which all the existing items are
|
* key, or possibly at the end of a page on which all the existing
|
||||||
* less than the scan key and we know that everything on later pages
|
* items are less than the scan key and we know that everything on
|
||||||
* is greater than or equal to scan key.
|
* later pages is greater than or equal to scan key.
|
||||||
*
|
*
|
||||||
* If nextkey = true, we are positioned at the first item > scan key,
|
* If nextkey = true, we are positioned at the first item > scan key, or
|
||||||
* or possibly at the end of a page on which all the existing items are
|
* possibly at the end of a page on which all the existing items are
|
||||||
* less than or equal to the scan key and we know that everything on
|
* less than or equal to the scan key and we know that everything on
|
||||||
* later pages is greater than scan key.
|
* later pages is greater than scan key.
|
||||||
*
|
*
|
||||||
* The actually desired starting point is either this item or the prior
|
* The actually desired starting point is either this item or the prior
|
||||||
* one, or in the end-of-page case it's the first item on the next page
|
* one, or in the end-of-page case it's the first item on the next
|
||||||
* or the last item on this page. We apply _bt_step if needed to get to
|
* page or the last item on this page. We apply _bt_step if needed to
|
||||||
* the right place.
|
* get to the right place.
|
||||||
*
|
*
|
||||||
* If _bt_step fails (meaning we fell off the end of the index in
|
* If _bt_step fails (meaning we fell off the end of the index in one
|
||||||
* one direction or the other), then there are no matches so we just
|
* direction or the other), then there are no matches so we just
|
||||||
* return false.
|
* return false.
|
||||||
*/
|
*/
|
||||||
if (goback)
|
if (goback)
|
||||||
@ -1292,7 +1303,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
|
|||||||
itup = &(btitem->bti_itup);
|
itup = &(btitem->bti_itup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay, we are on the first or last tuple. Does it pass all the quals?
|
* Okay, we are on the first or last tuple. Does it pass all the
|
||||||
|
* quals?
|
||||||
*/
|
*/
|
||||||
if (_bt_checkkeys(scan, itup, dir, &continuescan))
|
if (_bt_checkkeys(scan, itup, dir, &continuescan))
|
||||||
{
|
{
|
||||||
|
@ -41,11 +41,11 @@
|
|||||||
*
|
*
|
||||||
* Since the index will never be used unless it is completely built,
|
* Since the index will never be used unless it is completely built,
|
||||||
* from a crash-recovery point of view there is no need to WAL-log the
|
* from a crash-recovery point of view there is no need to WAL-log the
|
||||||
* steps of the build. After completing the index build, we can just sync
|
* steps of the build. After completing the index build, we can just sync
|
||||||
* the whole file to disk using smgrimmedsync() before exiting this module.
|
* the whole file to disk using smgrimmedsync() before exiting this module.
|
||||||
* This can be seen to be sufficient for crash recovery by considering that
|
* This can be seen to be sufficient for crash recovery by considering that
|
||||||
* it's effectively equivalent to what would happen if a CHECKPOINT occurred
|
* it's effectively equivalent to what would happen if a CHECKPOINT occurred
|
||||||
* just after the index build. However, it is clearly not sufficient if the
|
* just after the index build. However, it is clearly not sufficient if the
|
||||||
* DBA is using the WAL log for PITR or replication purposes, since another
|
* DBA is using the WAL log for PITR or replication purposes, since another
|
||||||
* machine would not be able to reconstruct the index from WAL. Therefore,
|
* machine would not be able to reconstruct the index from WAL. Therefore,
|
||||||
* we log the completed index pages to WAL if and only if WAL archiving is
|
* we log the completed index pages to WAL if and only if WAL archiving is
|
||||||
@ -56,7 +56,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.87 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.88 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -98,7 +98,7 @@ struct BTSpool
|
|||||||
typedef struct BTPageState
|
typedef struct BTPageState
|
||||||
{
|
{
|
||||||
Page btps_page; /* workspace for page building */
|
Page btps_page; /* workspace for page building */
|
||||||
BlockNumber btps_blkno; /* block # to write this page at */
|
BlockNumber btps_blkno; /* block # to write this page at */
|
||||||
BTItem btps_minkey; /* copy of minimum key (first item) on
|
BTItem btps_minkey; /* copy of minimum key (first item) on
|
||||||
* page */
|
* page */
|
||||||
OffsetNumber btps_lastoff; /* last item offset loaded */
|
OffsetNumber btps_lastoff; /* last item offset loaded */
|
||||||
@ -114,10 +114,10 @@ typedef struct BTPageState
|
|||||||
typedef struct BTWriteState
|
typedef struct BTWriteState
|
||||||
{
|
{
|
||||||
Relation index;
|
Relation index;
|
||||||
bool btws_use_wal; /* dump pages to WAL? */
|
bool btws_use_wal; /* dump pages to WAL? */
|
||||||
BlockNumber btws_pages_alloced; /* # pages allocated */
|
BlockNumber btws_pages_alloced; /* # pages allocated */
|
||||||
BlockNumber btws_pages_written; /* # pages written out */
|
BlockNumber btws_pages_written; /* # pages written out */
|
||||||
Page btws_zeropage; /* workspace for filling zeroes */
|
Page btws_zeropage; /* workspace for filling zeroes */
|
||||||
} BTWriteState;
|
} BTWriteState;
|
||||||
|
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ static void _bt_sortaddtup(Page page, Size itemsize,
|
|||||||
static void _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti);
|
static void _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti);
|
||||||
static void _bt_uppershutdown(BTWriteState *wstate, BTPageState *state);
|
static void _bt_uppershutdown(BTWriteState *wstate, BTPageState *state);
|
||||||
static void _bt_load(BTWriteState *wstate,
|
static void _bt_load(BTWriteState *wstate,
|
||||||
BTSpool *btspool, BTSpool *btspool2);
|
BTSpool *btspool, BTSpool *btspool2);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -157,12 +157,12 @@ _bt_spoolinit(Relation index, bool isunique, bool isdead)
|
|||||||
btspool->isunique = isunique;
|
btspool->isunique = isunique;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We size the sort area as maintenance_work_mem rather than work_mem to
|
* We size the sort area as maintenance_work_mem rather than work_mem
|
||||||
* speed index creation. This should be OK since a single backend can't
|
* to speed index creation. This should be OK since a single backend
|
||||||
* run multiple index creations in parallel. Note that creation of a
|
* can't run multiple index creations in parallel. Note that creation
|
||||||
* unique index actually requires two BTSpool objects. We expect that the
|
* of a unique index actually requires two BTSpool objects. We expect
|
||||||
* second one (for dead tuples) won't get very full, so we give it only
|
* that the second one (for dead tuples) won't get very full, so we
|
||||||
* work_mem.
|
* give it only work_mem.
|
||||||
*/
|
*/
|
||||||
btKbytes = isdead ? work_mem : maintenance_work_mem;
|
btKbytes = isdead ? work_mem : maintenance_work_mem;
|
||||||
btspool->sortstate = tuplesort_begin_index(index, isunique,
|
btspool->sortstate = tuplesort_begin_index(index, isunique,
|
||||||
@ -205,7 +205,7 @@ _bt_spool(BTItem btitem, BTSpool *btspool)
|
|||||||
void
|
void
|
||||||
_bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
_bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
||||||
{
|
{
|
||||||
BTWriteState wstate;
|
BTWriteState wstate;
|
||||||
|
|
||||||
#ifdef BTREE_BUILD_STATS
|
#ifdef BTREE_BUILD_STATS
|
||||||
if (log_btree_build_stats)
|
if (log_btree_build_stats)
|
||||||
@ -220,6 +220,7 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
|||||||
tuplesort_performsort(btspool2->sortstate);
|
tuplesort_performsort(btspool2->sortstate);
|
||||||
|
|
||||||
wstate.index = btspool->index;
|
wstate.index = btspool->index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to log index creation in WAL iff WAL archiving is enabled
|
* We need to log index creation in WAL iff WAL archiving is enabled
|
||||||
* AND it's not a temp index.
|
* AND it's not a temp index.
|
||||||
@ -229,7 +230,7 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
|||||||
/* reserve the metapage */
|
/* reserve the metapage */
|
||||||
wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
|
wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
|
||||||
wstate.btws_pages_written = 0;
|
wstate.btws_pages_written = 0;
|
||||||
wstate.btws_zeropage = NULL; /* until needed */
|
wstate.btws_zeropage = NULL; /* until needed */
|
||||||
|
|
||||||
_bt_load(&wstate, btspool, btspool2);
|
_bt_load(&wstate, btspool, btspool2);
|
||||||
}
|
}
|
||||||
@ -246,7 +247,7 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
|||||||
static Page
|
static Page
|
||||||
_bt_blnewpage(uint32 level)
|
_bt_blnewpage(uint32 level)
|
||||||
{
|
{
|
||||||
Page page;
|
Page page;
|
||||||
BTPageOpaque opaque;
|
BTPageOpaque opaque;
|
||||||
|
|
||||||
page = (Page) palloc(BLCKSZ);
|
page = (Page) palloc(BLCKSZ);
|
||||||
@ -313,8 +314,8 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
|
|||||||
* If we have to write pages nonsequentially, fill in the space with
|
* If we have to write pages nonsequentially, fill in the space with
|
||||||
* zeroes until we come back and overwrite. This is not logically
|
* zeroes until we come back and overwrite. This is not logically
|
||||||
* necessary on standard Unix filesystems (unwritten space will read
|
* necessary on standard Unix filesystems (unwritten space will read
|
||||||
* as zeroes anyway), but it should help to avoid fragmentation.
|
* as zeroes anyway), but it should help to avoid fragmentation. The
|
||||||
* The dummy pages aren't WAL-logged though.
|
* dummy pages aren't WAL-logged though.
|
||||||
*/
|
*/
|
||||||
while (blkno > wstate->btws_pages_written)
|
while (blkno > wstate->btws_pages_written)
|
||||||
{
|
{
|
||||||
@ -326,9 +327,9 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now write the page. We say isTemp = true even if it's not a
|
* Now write the page. We say isTemp = true even if it's not a temp
|
||||||
* temp index, because there's no need for smgr to schedule an fsync
|
* index, because there's no need for smgr to schedule an fsync for
|
||||||
* for this write; we'll do it ourselves before ending the build.
|
* this write; we'll do it ourselves before ending the build.
|
||||||
*/
|
*/
|
||||||
smgrwrite(wstate->index->rd_smgr, blkno, (char *) page, true);
|
smgrwrite(wstate->index->rd_smgr, blkno, (char *) page, true);
|
||||||
|
|
||||||
@ -468,7 +469,7 @@ static void
|
|||||||
_bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
|
_bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
|
||||||
{
|
{
|
||||||
Page npage;
|
Page npage;
|
||||||
BlockNumber nblkno;
|
BlockNumber nblkno;
|
||||||
OffsetNumber last_off;
|
OffsetNumber last_off;
|
||||||
Size pgspc;
|
Size pgspc;
|
||||||
Size btisz;
|
Size btisz;
|
||||||
@ -506,7 +507,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
|
|||||||
* already. Finish off the page and write it out.
|
* already. Finish off the page and write it out.
|
||||||
*/
|
*/
|
||||||
Page opage = npage;
|
Page opage = npage;
|
||||||
BlockNumber oblkno = nblkno;
|
BlockNumber oblkno = nblkno;
|
||||||
ItemId ii;
|
ItemId ii;
|
||||||
ItemId hii;
|
ItemId hii;
|
||||||
BTItem obti;
|
BTItem obti;
|
||||||
@ -539,8 +540,8 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
|
|||||||
((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
|
((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Link the old page into its parent, using its minimum key. If
|
* Link the old page into its parent, using its minimum key. If we
|
||||||
* we don't have a parent, we have to create one; this adds a new
|
* don't have a parent, we have to create one; this adds a new
|
||||||
* btree level.
|
* btree level.
|
||||||
*/
|
*/
|
||||||
if (state->btps_next == NULL)
|
if (state->btps_next == NULL)
|
||||||
@ -572,8 +573,8 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write out the old page. We never need to touch it again,
|
* Write out the old page. We never need to touch it again, so we
|
||||||
* so we can free the opage workspace too.
|
* can free the opage workspace too.
|
||||||
*/
|
*/
|
||||||
_bt_blwritepage(wstate, opage, oblkno);
|
_bt_blwritepage(wstate, opage, oblkno);
|
||||||
|
|
||||||
@ -613,7 +614,7 @@ static void
|
|||||||
_bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
|
_bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
|
||||||
{
|
{
|
||||||
BTPageState *s;
|
BTPageState *s;
|
||||||
BlockNumber rootblkno = P_NONE;
|
BlockNumber rootblkno = P_NONE;
|
||||||
uint32 rootlevel = 0;
|
uint32 rootlevel = 0;
|
||||||
Page metapage;
|
Page metapage;
|
||||||
|
|
||||||
@ -663,9 +664,9 @@ _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* As the last step in the process, construct the metapage and make it
|
* As the last step in the process, construct the metapage and make it
|
||||||
* point to the new root (unless we had no data at all, in which case it's
|
* point to the new root (unless we had no data at all, in which case
|
||||||
* set to point to "P_NONE"). This changes the index to the "valid"
|
* it's set to point to "P_NONE"). This changes the index to the
|
||||||
* state by filling in a valid magic number in the metapage.
|
* "valid" state by filling in a valid magic number in the metapage.
|
||||||
*/
|
*/
|
||||||
metapage = (Page) palloc(BLCKSZ);
|
metapage = (Page) palloc(BLCKSZ);
|
||||||
_bt_initmetapage(metapage, rootblkno, rootlevel);
|
_bt_initmetapage(metapage, rootblkno, rootlevel);
|
||||||
@ -744,7 +745,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
|
|
||||||
compare = DatumGetInt32(FunctionCall2(&entry->sk_func,
|
compare = DatumGetInt32(FunctionCall2(&entry->sk_func,
|
||||||
attrDatum1,
|
attrDatum1,
|
||||||
attrDatum2));
|
attrDatum2));
|
||||||
if (compare > 0)
|
if (compare > 0)
|
||||||
{
|
{
|
||||||
load1 = false;
|
load1 = false;
|
||||||
@ -768,7 +769,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
if (should_free)
|
if (should_free)
|
||||||
pfree((void *) bti);
|
pfree((void *) bti);
|
||||||
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
|
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
|
||||||
true, &should_free);
|
true, &should_free);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -776,7 +777,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
if (should_free2)
|
if (should_free2)
|
||||||
pfree((void *) bti2);
|
pfree((void *) bti2);
|
||||||
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate,
|
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate,
|
||||||
true, &should_free2);
|
true, &should_free2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_bt_freeskey(indexScanKey);
|
_bt_freeskey(indexScanKey);
|
||||||
@ -785,7 +786,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
{
|
{
|
||||||
/* merge is unnecessary */
|
/* merge is unnecessary */
|
||||||
while ((bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
|
while ((bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
|
||||||
true, &should_free)) != NULL)
|
true, &should_free)) != NULL)
|
||||||
{
|
{
|
||||||
/* When we see first tuple, create first index page */
|
/* When we see first tuple, create first index page */
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
@ -802,18 +803,18 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If the index isn't temp, we must fsync it down to disk before it's
|
* If the index isn't temp, we must fsync it down to disk before it's
|
||||||
* safe to commit the transaction. (For a temp index we don't care
|
* safe to commit the transaction. (For a temp index we don't care
|
||||||
* since the index will be uninteresting after a crash anyway.)
|
* since the index will be uninteresting after a crash anyway.)
|
||||||
*
|
*
|
||||||
* It's obvious that we must do this when not WAL-logging the build.
|
* It's obvious that we must do this when not WAL-logging the build. It's
|
||||||
* It's less obvious that we have to do it even if we did WAL-log the
|
* less obvious that we have to do it even if we did WAL-log the index
|
||||||
* index pages. The reason is that since we're building outside
|
* pages. The reason is that since we're building outside shared
|
||||||
* shared buffers, a CHECKPOINT occurring during the build has no way
|
* buffers, a CHECKPOINT occurring during the build has no way to
|
||||||
* to flush the previously written data to disk (indeed it won't know
|
* flush the previously written data to disk (indeed it won't know the
|
||||||
* the index even exists). A crash later on would replay WAL from the
|
* index even exists). A crash later on would replay WAL from the
|
||||||
* checkpoint, therefore it wouldn't replay our earlier WAL entries.
|
* checkpoint, therefore it wouldn't replay our earlier WAL entries.
|
||||||
* If we do not fsync those pages here, they might still not be on disk
|
* If we do not fsync those pages here, they might still not be on
|
||||||
* when the crash occurs.
|
* disk when the crash occurs.
|
||||||
*/
|
*/
|
||||||
if (!wstate->index->rd_istemp)
|
if (!wstate->index->rd_istemp)
|
||||||
smgrimmedsync(wstate->index->rd_smgr);
|
smgrimmedsync(wstate->index->rd_smgr);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.59 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.60 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,8 +48,8 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
|
|||||||
bool null;
|
bool null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can use the cached (default) support procs since no cross-type
|
* We can use the cached (default) support procs since no
|
||||||
* comparison can be needed.
|
* cross-type comparison can be needed.
|
||||||
*/
|
*/
|
||||||
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
|
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
|
||||||
arg = index_getattr(itup, i + 1, itupdesc, &null);
|
arg = index_getattr(itup, i + 1, itupdesc, &null);
|
||||||
@ -68,7 +68,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
|
|||||||
/*
|
/*
|
||||||
* _bt_mkscankey_nodata
|
* _bt_mkscankey_nodata
|
||||||
* Build a scan key that contains comparator routines appropriate to
|
* Build a scan key that contains comparator routines appropriate to
|
||||||
* the key datatypes, but no comparison data. The comparison data
|
* the key datatypes, but no comparison data. The comparison data
|
||||||
* ultimately used must match the key datatypes.
|
* ultimately used must match the key datatypes.
|
||||||
*
|
*
|
||||||
* The result cannot be used with _bt_compare(). Currently this
|
* The result cannot be used with _bt_compare(). Currently this
|
||||||
@ -93,8 +93,8 @@ _bt_mkscankey_nodata(Relation rel)
|
|||||||
FmgrInfo *procinfo;
|
FmgrInfo *procinfo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can use the cached (default) support procs since no cross-type
|
* We can use the cached (default) support procs since no
|
||||||
* comparison can be needed.
|
* cross-type comparison can be needed.
|
||||||
*/
|
*/
|
||||||
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
|
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
|
||||||
ScanKeyEntryInitializeWithInfo(&skey[i],
|
ScanKeyEntryInitializeWithInfo(&skey[i],
|
||||||
@ -163,12 +163,12 @@ _bt_formitem(IndexTuple itup)
|
|||||||
* _bt_preprocess_keys() -- Preprocess scan keys
|
* _bt_preprocess_keys() -- Preprocess scan keys
|
||||||
*
|
*
|
||||||
* The caller-supplied keys (in scan->keyData[]) are copied to
|
* The caller-supplied keys (in scan->keyData[]) are copied to
|
||||||
* so->keyData[] with possible transformation. scan->numberOfKeys is
|
* so->keyData[] with possible transformation. scan->numberOfKeys is
|
||||||
* the number of input keys, so->numberOfKeys gets the number of output
|
* the number of input keys, so->numberOfKeys gets the number of output
|
||||||
* keys (possibly less, never greater).
|
* keys (possibly less, never greater).
|
||||||
*
|
*
|
||||||
* The primary purpose of this routine is to discover how many scan keys
|
* The primary purpose of this routine is to discover how many scan keys
|
||||||
* must be satisfied to continue the scan. It also attempts to eliminate
|
* must be satisfied to continue the scan. It also attempts to eliminate
|
||||||
* redundant keys and detect contradictory keys. At present, redundant and
|
* redundant keys and detect contradictory keys. At present, redundant and
|
||||||
* contradictory keys can only be detected for same-data-type comparisons,
|
* contradictory keys can only be detected for same-data-type comparisons,
|
||||||
* but that's the usual case so it seems worth doing.
|
* but that's the usual case so it seems worth doing.
|
||||||
@ -198,7 +198,7 @@ _bt_formitem(IndexTuple itup)
|
|||||||
* or one or two boundary-condition keys for each attr.) However, we can
|
* or one or two boundary-condition keys for each attr.) However, we can
|
||||||
* only detect redundant keys when the right-hand datatypes are all equal
|
* only detect redundant keys when the right-hand datatypes are all equal
|
||||||
* to the index datatype, because we do not know suitable operators for
|
* to the index datatype, because we do not know suitable operators for
|
||||||
* comparing right-hand values of two different datatypes. (In theory
|
* comparing right-hand values of two different datatypes. (In theory
|
||||||
* we could handle comparison of a RHS of the index datatype with a RHS of
|
* we could handle comparison of a RHS of the index datatype with a RHS of
|
||||||
* another type, but that seems too much pain for too little gain.) So,
|
* another type, but that seems too much pain for too little gain.) So,
|
||||||
* keys whose operator has a nondefault subtype (ie, its RHS is not of the
|
* keys whose operator has a nondefault subtype (ie, its RHS is not of the
|
||||||
@ -285,9 +285,9 @@ _bt_preprocess_keys(IndexScanDesc scan)
|
|||||||
*
|
*
|
||||||
* xform[i] points to the currently best scan key of strategy type i+1,
|
* xform[i] points to the currently best scan key of strategy type i+1,
|
||||||
* if any is found with a default operator subtype; it is NULL if we
|
* if any is found with a default operator subtype; it is NULL if we
|
||||||
* haven't yet found such a key for this attr. Scan keys of nondefault
|
* haven't yet found such a key for this attr. Scan keys of
|
||||||
* subtypes are transferred to the output with no processing except for
|
* nondefault subtypes are transferred to the output with no
|
||||||
* noting if they are of "=" type.
|
* processing except for noting if they are of "=" type.
|
||||||
*/
|
*/
|
||||||
attno = 1;
|
attno = 1;
|
||||||
memset(xform, 0, sizeof(xform));
|
memset(xform, 0, sizeof(xform));
|
||||||
@ -361,7 +361,7 @@ _bt_preprocess_keys(IndexScanDesc scan)
|
|||||||
/*
|
/*
|
||||||
* If no "=" for this key, we're done with required keys
|
* If no "=" for this key, we're done with required keys
|
||||||
*/
|
*/
|
||||||
if (! hasOtherTypeEqual)
|
if (!hasOtherTypeEqual)
|
||||||
allEqualSoFar = false;
|
allEqualSoFar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,8 +369,8 @@ _bt_preprocess_keys(IndexScanDesc scan)
|
|||||||
if (xform[BTLessStrategyNumber - 1]
|
if (xform[BTLessStrategyNumber - 1]
|
||||||
&& xform[BTLessEqualStrategyNumber - 1])
|
&& xform[BTLessEqualStrategyNumber - 1])
|
||||||
{
|
{
|
||||||
ScanKey lt = xform[BTLessStrategyNumber - 1];
|
ScanKey lt = xform[BTLessStrategyNumber - 1];
|
||||||
ScanKey le = xform[BTLessEqualStrategyNumber - 1];
|
ScanKey le = xform[BTLessEqualStrategyNumber - 1];
|
||||||
|
|
||||||
test = FunctionCall2(&le->sk_func,
|
test = FunctionCall2(&le->sk_func,
|
||||||
lt->sk_argument,
|
lt->sk_argument,
|
||||||
@ -385,8 +385,8 @@ _bt_preprocess_keys(IndexScanDesc scan)
|
|||||||
if (xform[BTGreaterStrategyNumber - 1]
|
if (xform[BTGreaterStrategyNumber - 1]
|
||||||
&& xform[BTGreaterEqualStrategyNumber - 1])
|
&& xform[BTGreaterEqualStrategyNumber - 1])
|
||||||
{
|
{
|
||||||
ScanKey gt = xform[BTGreaterStrategyNumber - 1];
|
ScanKey gt = xform[BTGreaterStrategyNumber - 1];
|
||||||
ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1];
|
ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1];
|
||||||
|
|
||||||
test = FunctionCall2(&ge->sk_func,
|
test = FunctionCall2(&ge->sk_func,
|
||||||
gt->sk_argument,
|
gt->sk_argument,
|
||||||
@ -545,21 +545,23 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Tuple fails this qual. If it's a required qual, then we
|
* Tuple fails this qual. If it's a required qual, then we
|
||||||
* may be able to conclude no further tuples will pass, either.
|
* may be able to conclude no further tuples will pass,
|
||||||
* We have to look at the scan direction and the qual type.
|
* either. We have to look at the scan direction and the qual
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* Note: the only case in which we would keep going after failing
|
* Note: the only case in which we would keep going after failing
|
||||||
* a required qual is if there are partially-redundant quals that
|
* a required qual is if there are partially-redundant quals
|
||||||
* _bt_preprocess_keys() was unable to eliminate. For example,
|
* that _bt_preprocess_keys() was unable to eliminate. For
|
||||||
* given "x > 4 AND x > 10" where both are cross-type comparisons
|
* example, given "x > 4 AND x > 10" where both are cross-type
|
||||||
* and so not removable, we might start the scan at the x = 4
|
* comparisons and so not removable, we might start the scan
|
||||||
* boundary point. The "x > 10" condition will fail until we
|
* at the x = 4 boundary point. The "x > 10" condition will
|
||||||
* pass x = 10, but we must not stop the scan on its account.
|
* fail until we pass x = 10, but we must not stop the scan on
|
||||||
|
* its account.
|
||||||
*
|
*
|
||||||
* Note: because we stop the scan as soon as any required equality
|
* Note: because we stop the scan as soon as any required
|
||||||
* qual fails, it is critical that equality quals be used for the
|
* equality qual fails, it is critical that equality quals be
|
||||||
* initial positioning in _bt_first() when they are available.
|
* used for the initial positioning in _bt_first() when they
|
||||||
* See comments in _bt_first().
|
* are available. See comments in _bt_first().
|
||||||
*/
|
*/
|
||||||
if (ikey < so->numberOfRequiredKeys)
|
if (ikey < so->numberOfRequiredKeys)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.17 2004/08/29 04:12:21 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.18 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -770,7 +770,7 @@ static void
|
|||||||
out_target(char *buf, xl_btreetid *target)
|
out_target(char *buf, xl_btreetid *target)
|
||||||
{
|
{
|
||||||
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u",
|
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u",
|
||||||
target->node.spcNode, target->node.dbNode, target->node.relNode,
|
target->node.spcNode, target->node.dbNode, target->node.relNode,
|
||||||
ItemPointerGetBlockNumber(&(target->tid)),
|
ItemPointerGetBlockNumber(&(target->tid)),
|
||||||
ItemPointerGetOffsetNumber(&(target->tid)));
|
ItemPointerGetOffsetNumber(&(target->tid)));
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.54 2004/08/29 04:12:22 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.55 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -123,7 +123,7 @@ rtrescan(PG_FUNCTION_ARGS)
|
|||||||
Oid int_oper;
|
Oid int_oper;
|
||||||
RegProcedure int_proc;
|
RegProcedure int_proc;
|
||||||
|
|
||||||
opclass = s->indexRelation->rd_index->indclass[attno-1];
|
opclass = s->indexRelation->rd_index->indclass[attno - 1];
|
||||||
int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
|
int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
|
||||||
int_oper = get_opclass_member(opclass,
|
int_oper = get_opclass_member(opclass,
|
||||||
s->keyData[i].sk_subtype,
|
s->keyData[i].sk_subtype,
|
||||||
@ -280,14 +280,14 @@ rtdropscan(IndexScanDesc s)
|
|||||||
void
|
void
|
||||||
ReleaseResources_rtree(void)
|
ReleaseResources_rtree(void)
|
||||||
{
|
{
|
||||||
RTScanList l;
|
RTScanList l;
|
||||||
RTScanList prev;
|
RTScanList prev;
|
||||||
RTScanList next;
|
RTScanList next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: this should be a no-op during normal query shutdown.
|
* Note: this should be a no-op during normal query shutdown. However,
|
||||||
* However, in an abort situation ExecutorEnd is not called and so
|
* in an abort situation ExecutorEnd is not called and so there may be
|
||||||
* there may be open index scans to clean up.
|
* open index scans to clean up.
|
||||||
*/
|
*/
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.24 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.25 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -62,6 +62,7 @@
|
|||||||
* Link to shared-memory data structures for CLOG control
|
* Link to shared-memory data structures for CLOG control
|
||||||
*/
|
*/
|
||||||
static SlruCtlData ClogCtlData;
|
static SlruCtlData ClogCtlData;
|
||||||
|
|
||||||
#define ClogCtl (&ClogCtlData)
|
#define ClogCtl (&ClogCtlData)
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.20 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.21 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -79,7 +79,7 @@
|
|||||||
* segment and page numbers in SimpleLruTruncate (see PagePrecedes()).
|
* segment and page numbers in SimpleLruTruncate (see PagePrecedes()).
|
||||||
*
|
*
|
||||||
* Note: this file currently assumes that segment file names will be four
|
* Note: this file currently assumes that segment file names will be four
|
||||||
* hex digits. This sets a lower bound on the segment size (64K transactions
|
* hex digits. This sets a lower bound on the segment size (64K transactions
|
||||||
* for 32-bit TransactionIds).
|
* for 32-bit TransactionIds).
|
||||||
*/
|
*/
|
||||||
#define SLRU_PAGES_PER_SEGMENT 32
|
#define SLRU_PAGES_PER_SEGMENT 32
|
||||||
@ -96,9 +96,9 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct SlruFlushData
|
typedef struct SlruFlushData
|
||||||
{
|
{
|
||||||
int num_files; /* # files actually open */
|
int num_files; /* # files actually open */
|
||||||
int fd[NUM_SLRU_BUFFERS]; /* their FD's */
|
int fd[NUM_SLRU_BUFFERS]; /* their FD's */
|
||||||
int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */
|
int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */
|
||||||
} SlruFlushData;
|
} SlruFlushData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,7 +132,7 @@ static int slru_errno;
|
|||||||
|
|
||||||
static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno);
|
static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno);
|
||||||
static bool SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno,
|
static bool SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno,
|
||||||
SlruFlush fdata);
|
SlruFlush fdata);
|
||||||
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid);
|
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid);
|
||||||
static int SlruSelectLRUPage(SlruCtl ctl, int pageno);
|
static int SlruSelectLRUPage(SlruCtl ctl, int pageno);
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ SimpleLruWritePage(SlruCtl ctl, int slotno, SlruFlush fdata)
|
|||||||
/* If we failed, and we're in a flush, better close the files */
|
/* If we failed, and we're in a flush, better close the files */
|
||||||
if (!ok && fdata)
|
if (!ok && fdata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < fdata->num_files; i++)
|
for (i = 0; i < fdata->num_files; i++)
|
||||||
close(fdata->fd[i]);
|
close(fdata->fd[i]);
|
||||||
@ -511,7 +511,7 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
|
|||||||
*/
|
*/
|
||||||
if (fdata)
|
if (fdata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < fdata->num_files; i++)
|
for (i = 0; i < fdata->num_files; i++)
|
||||||
{
|
{
|
||||||
@ -527,16 +527,17 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If the file doesn't already exist, we should create it. It is
|
* If the file doesn't already exist, we should create it. It is
|
||||||
* possible for this to need to happen when writing a page that's not
|
* possible for this to need to happen when writing a page that's
|
||||||
* first in its segment; we assume the OS can cope with that.
|
* not first in its segment; we assume the OS can cope with that.
|
||||||
* (Note: it might seem that it'd be okay to create files only when
|
* (Note: it might seem that it'd be okay to create files only
|
||||||
* SimpleLruZeroPage is called for the first page of a segment.
|
* when SimpleLruZeroPage is called for the first page of a
|
||||||
* However, if after a crash and restart the REDO logic elects to
|
* segment. However, if after a crash and restart the REDO logic
|
||||||
* replay the log from a checkpoint before the latest one, then it's
|
* elects to replay the log from a checkpoint before the latest
|
||||||
* possible that we will get commands to set transaction status of
|
* one, then it's possible that we will get commands to set
|
||||||
* transactions that have already been truncated from the commit log.
|
* transaction status of transactions that have already been
|
||||||
* Easiest way to deal with that is to accept references to
|
* truncated from the commit log. Easiest way to deal with that is
|
||||||
* nonexistent files here and in SlruPhysicalReadPage.)
|
* to accept references to nonexistent files here and in
|
||||||
|
* SlruPhysicalReadPage.)
|
||||||
*/
|
*/
|
||||||
SlruFileName(ctl, path, segno);
|
SlruFileName(ctl, path, segno);
|
||||||
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
||||||
@ -648,36 +649,36 @@ SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not access status of transaction %u", xid),
|
errmsg("could not access status of transaction %u", xid),
|
||||||
errdetail("could not seek in file \"%s\" to offset %u: %m",
|
errdetail("could not seek in file \"%s\" to offset %u: %m",
|
||||||
path, offset)));
|
path, offset)));
|
||||||
break;
|
break;
|
||||||
case SLRU_READ_FAILED:
|
case SLRU_READ_FAILED:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not access status of transaction %u", xid),
|
errmsg("could not access status of transaction %u", xid),
|
||||||
errdetail("could not read from file \"%s\" at offset %u: %m",
|
errdetail("could not read from file \"%s\" at offset %u: %m",
|
||||||
path, offset)));
|
path, offset)));
|
||||||
break;
|
break;
|
||||||
case SLRU_WRITE_FAILED:
|
case SLRU_WRITE_FAILED:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not access status of transaction %u", xid),
|
errmsg("could not access status of transaction %u", xid),
|
||||||
errdetail("could not write to file \"%s\" at offset %u: %m",
|
errdetail("could not write to file \"%s\" at offset %u: %m",
|
||||||
path, offset)));
|
path, offset)));
|
||||||
break;
|
break;
|
||||||
case SLRU_FSYNC_FAILED:
|
case SLRU_FSYNC_FAILED:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not access status of transaction %u", xid),
|
errmsg("could not access status of transaction %u", xid),
|
||||||
errdetail("could not fsync file \"%s\": %m",
|
errdetail("could not fsync file \"%s\": %m",
|
||||||
path)));
|
path)));
|
||||||
break;
|
break;
|
||||||
case SLRU_CLOSE_FAILED:
|
case SLRU_CLOSE_FAILED:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not access status of transaction %u", xid),
|
errmsg("could not access status of transaction %u", xid),
|
||||||
errdetail("could not close file \"%s\": %m",
|
errdetail("could not close file \"%s\": %m",
|
||||||
path)));
|
path)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* can't get here, we trust */
|
/* can't get here, we trust */
|
||||||
@ -841,8 +842,8 @@ SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
|
|||||||
/*
|
/*
|
||||||
* Scan shared memory and remove any pages preceding the cutoff page,
|
* Scan shared memory and remove any pages preceding the cutoff page,
|
||||||
* to ensure we won't rewrite them later. (Since this is normally
|
* to ensure we won't rewrite them later. (Since this is normally
|
||||||
* called in or just after a checkpoint, any dirty pages should
|
* called in or just after a checkpoint, any dirty pages should have
|
||||||
* have been flushed already ... we're just being extra careful here.)
|
* been flushed already ... we're just being extra careful here.)
|
||||||
*/
|
*/
|
||||||
LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);
|
LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
@ -952,8 +953,11 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
|
|
||||||
not in released version */
|
/*
|
||||||
|
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
|
||||||
|
* not in released version
|
||||||
|
*/
|
||||||
if (GetLastError() == ERROR_NO_MORE_FILES)
|
if (GetLastError() == ERROR_NO_MORE_FILES)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* The pg_subtrans manager is a pg_clog-like manager that stores the parent
|
* The pg_subtrans manager is a pg_clog-like manager that stores the parent
|
||||||
* transaction Id for each transaction. It is a fundamental part of the
|
* transaction Id for each transaction. It is a fundamental part of the
|
||||||
* nested transactions implementation. A main transaction has a parent
|
* nested transactions implementation. A main transaction has a parent
|
||||||
* of InvalidTransactionId, and each subtransaction has its immediate parent.
|
* of InvalidTransactionId, and each subtransaction has its immediate parent.
|
||||||
* The tree can easily be walked from child to parent, but not in the
|
* The tree can easily be walked from child to parent, but not in the
|
||||||
* opposite direction.
|
* opposite direction.
|
||||||
@ -22,7 +22,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.4 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.5 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -57,6 +57,7 @@
|
|||||||
* Link to shared-memory data structures for SUBTRANS control
|
* Link to shared-memory data structures for SUBTRANS control
|
||||||
*/
|
*/
|
||||||
static SlruCtlData SubTransCtlData;
|
static SlruCtlData SubTransCtlData;
|
||||||
|
|
||||||
#define SubTransCtl (&SubTransCtlData)
|
#define SubTransCtl (&SubTransCtlData)
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ SubTransGetParent(TransactionId xid)
|
|||||||
int entryno = TransactionIdToEntry(xid);
|
int entryno = TransactionIdToEntry(xid);
|
||||||
int slotno;
|
int slotno;
|
||||||
TransactionId *ptr;
|
TransactionId *ptr;
|
||||||
TransactionId parent;
|
TransactionId parent;
|
||||||
|
|
||||||
/* Can't ask about stuff that might not be around anymore */
|
/* Can't ask about stuff that might not be around anymore */
|
||||||
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
|
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
|
||||||
@ -139,7 +140,7 @@ TransactionId
|
|||||||
SubTransGetTopmostTransaction(TransactionId xid)
|
SubTransGetTopmostTransaction(TransactionId xid)
|
||||||
{
|
{
|
||||||
TransactionId parentXid = xid,
|
TransactionId parentXid = xid,
|
||||||
previousXid = xid;
|
previousXid = xid;
|
||||||
|
|
||||||
/* Can't ask about stuff that might not be around anymore */
|
/* Can't ask about stuff that might not be around anymore */
|
||||||
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
|
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
|
||||||
@ -185,7 +186,7 @@ SUBTRANSShmemInit(void)
|
|||||||
* must have been called already.)
|
* must have been called already.)
|
||||||
*
|
*
|
||||||
* Note: it's not really necessary to create the initial segment now,
|
* Note: it's not really necessary to create the initial segment now,
|
||||||
* since slru.c would create it on first write anyway. But we may as well
|
* since slru.c would create it on first write anyway. But we may as well
|
||||||
* do it to be sure the directory is set up correctly.
|
* do it to be sure the directory is set up correctly.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -229,10 +230,11 @@ StartupSUBTRANS(void)
|
|||||||
int startPage;
|
int startPage;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we don't expect pg_subtrans to be valid across crashes,
|
* Since we don't expect pg_subtrans to be valid across crashes, we
|
||||||
* we initialize the currently-active page to zeroes during startup.
|
* initialize the currently-active page to zeroes during startup.
|
||||||
* Whenever we advance into a new page, ExtendSUBTRANS will likewise
|
* Whenever we advance into a new page, ExtendSUBTRANS will likewise
|
||||||
* zero the new page without regard to whatever was previously on disk.
|
* zero the new page without regard to whatever was previously on
|
||||||
|
* disk.
|
||||||
*/
|
*/
|
||||||
LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE);
|
LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
@ -251,8 +253,8 @@ ShutdownSUBTRANS(void)
|
|||||||
/*
|
/*
|
||||||
* Flush dirty SUBTRANS pages to disk
|
* Flush dirty SUBTRANS pages to disk
|
||||||
*
|
*
|
||||||
* This is not actually necessary from a correctness point of view.
|
* This is not actually necessary from a correctness point of view. We do
|
||||||
* We do it merely as a debugging aid.
|
* it merely as a debugging aid.
|
||||||
*/
|
*/
|
||||||
SimpleLruFlush(SubTransCtl, false);
|
SimpleLruFlush(SubTransCtl, false);
|
||||||
}
|
}
|
||||||
@ -266,8 +268,8 @@ CheckPointSUBTRANS(void)
|
|||||||
/*
|
/*
|
||||||
* Flush dirty SUBTRANS pages to disk
|
* Flush dirty SUBTRANS pages to disk
|
||||||
*
|
*
|
||||||
* This is not actually necessary from a correctness point of view.
|
* This is not actually necessary from a correctness point of view. We do
|
||||||
* We do it merely to improve the odds that writing of dirty pages is done
|
* it merely to improve the odds that writing of dirty pages is done
|
||||||
* by the checkpoint process and not by backends.
|
* by the checkpoint process and not by backends.
|
||||||
*/
|
*/
|
||||||
SimpleLruFlush(SubTransCtl, true);
|
SimpleLruFlush(SubTransCtl, true);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.60 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.61 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains the high level access-method interface to the
|
* This file contains the high level access-method interface to the
|
||||||
@ -126,7 +126,7 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
|
|||||||
static void
|
static void
|
||||||
TransactionLogMultiUpdate(int nxids, TransactionId *xids, XidStatus status)
|
TransactionLogMultiUpdate(int nxids, TransactionId *xids, XidStatus status)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
Assert(nxids != 0);
|
Assert(nxids != 0);
|
||||||
|
|
||||||
@ -199,9 +199,10 @@ TransactionIdDidCommit(TransactionId transactionId)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's marked subcommitted, we have to check the parent recursively.
|
* If it's marked subcommitted, we have to check the parent
|
||||||
* However, if it's older than RecentXmin, we can't look at pg_subtrans;
|
* recursively. However, if it's older than RecentXmin, we can't look
|
||||||
* instead assume that the parent crashed without cleaning up its children.
|
* at pg_subtrans; instead assume that the parent crashed without
|
||||||
|
* cleaning up its children.
|
||||||
*/
|
*/
|
||||||
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
|
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
|
||||||
{
|
{
|
||||||
@ -247,9 +248,10 @@ TransactionIdDidAbort(TransactionId transactionId)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's marked subcommitted, we have to check the parent recursively.
|
* If it's marked subcommitted, we have to check the parent
|
||||||
* However, if it's older than RecentXmin, we can't look at pg_subtrans;
|
* recursively. However, if it's older than RecentXmin, we can't look
|
||||||
* instead assume that the parent crashed without cleaning up its children.
|
* at pg_subtrans; instead assume that the parent crashed without
|
||||||
|
* cleaning up its children.
|
||||||
*/
|
*/
|
||||||
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
|
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 2000-2004, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2004, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.58 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.59 2004/08/29 05:06:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -47,9 +47,9 @@ GetNewTransactionId(bool isSubXact)
|
|||||||
xid = ShmemVariableCache->nextXid;
|
xid = ShmemVariableCache->nextXid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are allocating the first XID of a new page of the commit
|
* If we are allocating the first XID of a new page of the commit log,
|
||||||
* log, zero out that commit-log page before returning. We must do
|
* zero out that commit-log page before returning. We must do this
|
||||||
* this while holding XidGenLock, else another xact could acquire and
|
* while holding XidGenLock, else another xact could acquire and
|
||||||
* commit a later XID before we zero the page. Fortunately, a page of
|
* commit a later XID before we zero the page. Fortunately, a page of
|
||||||
* the commit log holds 32K or more transactions, so we don't have to
|
* the commit log holds 32K or more transactions, so we don't have to
|
||||||
* do this very often.
|
* do this very often.
|
||||||
@ -61,17 +61,18 @@ GetNewTransactionId(bool isSubXact)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Now advance the nextXid counter. This must not happen until after
|
* Now advance the nextXid counter. This must not happen until after
|
||||||
* we have successfully completed ExtendCLOG() --- if that routine fails,
|
* we have successfully completed ExtendCLOG() --- if that routine
|
||||||
* we want the next incoming transaction to try it again. We cannot
|
* fails, we want the next incoming transaction to try it again. We
|
||||||
* assign more XIDs until there is CLOG space for them.
|
* cannot assign more XIDs until there is CLOG space for them.
|
||||||
*/
|
*/
|
||||||
TransactionIdAdvance(ShmemVariableCache->nextXid);
|
TransactionIdAdvance(ShmemVariableCache->nextXid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must store the new XID into the shared PGPROC array before releasing
|
* We must store the new XID into the shared PGPROC array before
|
||||||
* XidGenLock. This ensures that when GetSnapshotData calls
|
* releasing XidGenLock. This ensures that when GetSnapshotData calls
|
||||||
* ReadNewTransactionId, all active XIDs before the returned value of
|
* ReadNewTransactionId, all active XIDs before the returned value of
|
||||||
* nextXid are already present in PGPROC. Else we have a race condition.
|
* nextXid are already present in PGPROC. Else we have a race
|
||||||
|
* condition.
|
||||||
*
|
*
|
||||||
* XXX by storing xid into MyProc without acquiring SInvalLock, we are
|
* XXX by storing xid into MyProc without acquiring SInvalLock, we are
|
||||||
* relying on fetch/store of an xid to be atomic, else other backends
|
* relying on fetch/store of an xid to be atomic, else other backends
|
||||||
@ -86,19 +87,19 @@ GetNewTransactionId(bool isSubXact)
|
|||||||
*
|
*
|
||||||
* A solution to the atomic-store problem would be to give each PGPROC
|
* A solution to the atomic-store problem would be to give each PGPROC
|
||||||
* its own spinlock used only for fetching/storing that PGPROC's xid
|
* its own spinlock used only for fetching/storing that PGPROC's xid
|
||||||
* and related fields. (SInvalLock would then mean primarily that
|
* and related fields. (SInvalLock would then mean primarily that
|
||||||
* PGPROCs couldn't be added/removed while holding the lock.)
|
* PGPROCs couldn't be added/removed while holding the lock.)
|
||||||
*
|
*
|
||||||
* If there's no room to fit a subtransaction XID into PGPROC, set the
|
* If there's no room to fit a subtransaction XID into PGPROC, set the
|
||||||
* cache-overflowed flag instead. This forces readers to look in
|
* cache-overflowed flag instead. This forces readers to look in
|
||||||
* pg_subtrans to map subtransaction XIDs up to top-level XIDs.
|
* pg_subtrans to map subtransaction XIDs up to top-level XIDs. There
|
||||||
* There is a race-condition window, in that the new XID will not
|
* is a race-condition window, in that the new XID will not appear as
|
||||||
* appear as running until its parent link has been placed into
|
* running until its parent link has been placed into pg_subtrans.
|
||||||
* pg_subtrans. However, that will happen before anyone could possibly
|
* However, that will happen before anyone could possibly have a
|
||||||
* have a reason to inquire about the status of the XID, so it seems
|
* reason to inquire about the status of the XID, so it seems OK.
|
||||||
* OK. (Snapshots taken during this window *will* include the parent
|
* (Snapshots taken during this window *will* include the parent XID,
|
||||||
* XID, so they will deliver the correct answer later on when someone
|
* so they will deliver the correct answer later on when someone does
|
||||||
* does have a reason to inquire.)
|
* have a reason to inquire.)
|
||||||
*/
|
*/
|
||||||
if (MyProc != NULL)
|
if (MyProc != NULL)
|
||||||
{
|
{
|
||||||
@ -112,9 +113,7 @@ GetNewTransactionId(bool isSubXact)
|
|||||||
MyProc->subxids.nxids++;
|
MyProc->subxids.nxids++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
MyProc->subxids.overflowed = true;
|
MyProc->subxids.overflowed = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.33 2004/08/29 04:12:23 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.34 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -212,11 +212,11 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
|
|||||||
res->reldata.rd_node = rnode;
|
res->reldata.rd_node = rnode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We set up the lockRelId in case anything tries to lock the dummy
|
* We set up the lockRelId in case anything tries to lock the
|
||||||
* relation. Note that this is fairly bogus since relNode may be
|
* dummy relation. Note that this is fairly bogus since relNode
|
||||||
* different from the relation's OID. It shouldn't really matter
|
* may be different from the relation's OID. It shouldn't really
|
||||||
* though, since we are presumably running by ourselves and can't
|
* matter though, since we are presumably running by ourselves and
|
||||||
* have any lock conflicts ...
|
* can't have any lock conflicts ...
|
||||||
*/
|
*/
|
||||||
res->reldata.rd_lockInfo.lockRelId.dbId = rnode.dbNode;
|
res->reldata.rd_lockInfo.lockRelId.dbId = rnode.dbNode;
|
||||||
res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode;
|
res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode;
|
||||||
@ -234,14 +234,15 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
|
|||||||
|
|
||||||
res->reldata.rd_targblock = InvalidBlockNumber;
|
res->reldata.rd_targblock = InvalidBlockNumber;
|
||||||
res->reldata.rd_smgr = smgropen(res->reldata.rd_node);
|
res->reldata.rd_smgr = smgropen(res->reldata.rd_node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the target file if it doesn't already exist. This lets
|
* Create the target file if it doesn't already exist. This lets
|
||||||
* us cope if the replay sequence contains writes to a relation
|
* us cope if the replay sequence contains writes to a relation
|
||||||
* that is later deleted. (The original coding of this routine
|
* that is later deleted. (The original coding of this routine
|
||||||
* would instead return NULL, causing the writes to be suppressed.
|
* would instead return NULL, causing the writes to be suppressed.
|
||||||
* But that seems like it risks losing valuable data if the filesystem
|
* But that seems like it risks losing valuable data if the
|
||||||
* loses an inode during a crash. Better to write the data until we
|
* filesystem loses an inode during a crash. Better to write the
|
||||||
* are actually told to delete the file.)
|
* data until we are actually told to delete the file.)
|
||||||
*/
|
*/
|
||||||
smgrcreate(res->reldata.rd_smgr, res->reldata.rd_istemp, true);
|
smgrcreate(res->reldata.rd_smgr, res->reldata.rd_istemp, true);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.192 2004/08/29 04:12:25 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.193 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -111,46 +111,46 @@ struct typinfo
|
|||||||
|
|
||||||
static const struct typinfo TypInfo[] = {
|
static const struct typinfo TypInfo[] = {
|
||||||
{"bool", BOOLOID, 0, 1, true, 'c', 'p',
|
{"bool", BOOLOID, 0, 1, true, 'c', 'p',
|
||||||
F_BOOLIN, F_BOOLOUT},
|
F_BOOLIN, F_BOOLOUT},
|
||||||
{"bytea", BYTEAOID, 0, -1, false, 'i', 'x',
|
{"bytea", BYTEAOID, 0, -1, false, 'i', 'x',
|
||||||
F_BYTEAIN, F_BYTEAOUT},
|
F_BYTEAIN, F_BYTEAOUT},
|
||||||
{"char", CHAROID, 0, 1, true, 'c', 'p',
|
{"char", CHAROID, 0, 1, true, 'c', 'p',
|
||||||
F_CHARIN, F_CHAROUT},
|
F_CHARIN, F_CHAROUT},
|
||||||
{"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'i', 'p',
|
{"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'i', 'p',
|
||||||
F_NAMEIN, F_NAMEOUT},
|
F_NAMEIN, F_NAMEOUT},
|
||||||
{"int2", INT2OID, 0, 2, true, 's', 'p',
|
{"int2", INT2OID, 0, 2, true, 's', 'p',
|
||||||
F_INT2IN, F_INT2OUT},
|
F_INT2IN, F_INT2OUT},
|
||||||
{"int4", INT4OID, 0, 4, true, 'i', 'p',
|
{"int4", INT4OID, 0, 4, true, 'i', 'p',
|
||||||
F_INT4IN, F_INT4OUT},
|
F_INT4IN, F_INT4OUT},
|
||||||
{"regproc", REGPROCOID, 0, 4, true, 'i', 'p',
|
{"regproc", REGPROCOID, 0, 4, true, 'i', 'p',
|
||||||
F_REGPROCIN, F_REGPROCOUT},
|
F_REGPROCIN, F_REGPROCOUT},
|
||||||
{"regclass", REGCLASSOID, 0, 4, true, 'i', 'p',
|
{"regclass", REGCLASSOID, 0, 4, true, 'i', 'p',
|
||||||
F_REGCLASSIN, F_REGCLASSOUT},
|
F_REGCLASSIN, F_REGCLASSOUT},
|
||||||
{"regtype", REGTYPEOID, 0, 4, true, 'i', 'p',
|
{"regtype", REGTYPEOID, 0, 4, true, 'i', 'p',
|
||||||
F_REGTYPEIN, F_REGTYPEOUT},
|
F_REGTYPEIN, F_REGTYPEOUT},
|
||||||
{"text", TEXTOID, 0, -1, false, 'i', 'x',
|
{"text", TEXTOID, 0, -1, false, 'i', 'x',
|
||||||
F_TEXTIN, F_TEXTOUT},
|
F_TEXTIN, F_TEXTOUT},
|
||||||
{"oid", OIDOID, 0, 4, true, 'i', 'p',
|
{"oid", OIDOID, 0, 4, true, 'i', 'p',
|
||||||
F_OIDIN, F_OIDOUT},
|
F_OIDIN, F_OIDOUT},
|
||||||
{"tid", TIDOID, 0, 6, false, 's', 'p',
|
{"tid", TIDOID, 0, 6, false, 's', 'p',
|
||||||
F_TIDIN, F_TIDOUT},
|
F_TIDIN, F_TIDOUT},
|
||||||
{"xid", XIDOID, 0, 4, true, 'i', 'p',
|
{"xid", XIDOID, 0, 4, true, 'i', 'p',
|
||||||
F_XIDIN, F_XIDOUT},
|
F_XIDIN, F_XIDOUT},
|
||||||
{"cid", CIDOID, 0, 4, true, 'i', 'p',
|
{"cid", CIDOID, 0, 4, true, 'i', 'p',
|
||||||
F_CIDIN, F_CIDOUT},
|
F_CIDIN, F_CIDOUT},
|
||||||
{"int2vector", INT2VECTOROID, INT2OID, INDEX_MAX_KEYS * 2, false, 's', 'p',
|
{"int2vector", INT2VECTOROID, INT2OID, INDEX_MAX_KEYS * 2, false, 's', 'p',
|
||||||
F_INT2VECTORIN, F_INT2VECTOROUT},
|
F_INT2VECTORIN, F_INT2VECTOROUT},
|
||||||
{"oidvector", OIDVECTOROID, OIDOID, INDEX_MAX_KEYS * 4, false, 'i', 'p',
|
{"oidvector", OIDVECTOROID, OIDOID, INDEX_MAX_KEYS * 4, false, 'i', 'p',
|
||||||
F_OIDVECTORIN, F_OIDVECTOROUT},
|
F_OIDVECTORIN, F_OIDVECTOROUT},
|
||||||
{"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x',
|
{"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x',
|
||||||
F_ARRAY_IN, F_ARRAY_OUT},
|
F_ARRAY_IN, F_ARRAY_OUT},
|
||||||
{"_text", 1009, TEXTOID, -1, false, 'i', 'x',
|
{"_text", 1009, TEXTOID, -1, false, 'i', 'x',
|
||||||
F_ARRAY_IN, F_ARRAY_OUT},
|
F_ARRAY_IN, F_ARRAY_OUT},
|
||||||
{"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x',
|
{"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x',
|
||||||
F_ARRAY_IN, F_ARRAY_OUT}
|
F_ARRAY_IN, F_ARRAY_OUT}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
|
static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
|
||||||
|
|
||||||
struct typmap
|
struct typmap
|
||||||
{ /* a hack */
|
{ /* a hack */
|
||||||
@ -498,13 +498,13 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
write_stderr("Usage:\n"
|
write_stderr("Usage:\n"
|
||||||
" postgres -boot [OPTION]... DBNAME\n"
|
" postgres -boot [OPTION]... DBNAME\n"
|
||||||
" -c NAME=VALUE set run-time parameter\n"
|
" -c NAME=VALUE set run-time parameter\n"
|
||||||
" -d 1-5 debug level\n"
|
" -d 1-5 debug level\n"
|
||||||
" -D datadir data directory\n"
|
" -D datadir data directory\n"
|
||||||
" -F turn off fsync\n"
|
" -F turn off fsync\n"
|
||||||
" -o file send debug output to file\n"
|
" -o file send debug output to file\n"
|
||||||
" -x num internal use\n");
|
" -x num internal use\n");
|
||||||
|
|
||||||
proc_exit(1);
|
proc_exit(1);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.106 2004/08/29 04:12:26 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.107 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* See acl.h.
|
* See acl.h.
|
||||||
@ -73,7 +73,7 @@ dumpacl(Acl *acl)
|
|||||||
* Determine the effective grantor ID for a GRANT or REVOKE operation.
|
* Determine the effective grantor ID for a GRANT or REVOKE operation.
|
||||||
*
|
*
|
||||||
* Ordinarily this is just the current user, but when a superuser does
|
* Ordinarily this is just the current user, but when a superuser does
|
||||||
* GRANT or REVOKE, we pretend he is the object owner. This ensures that
|
* GRANT or REVOKE, we pretend he is the object owner. This ensures that
|
||||||
* all granted privileges appear to flow from the object owner, and there
|
* all granted privileges appear to flow from the object owner, and there
|
||||||
* are never multiple "original sources" of a privilege.
|
* are never multiple "original sources" of a privilege.
|
||||||
*/
|
*/
|
||||||
@ -122,25 +122,25 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant,
|
|||||||
foreach(j, grantees)
|
foreach(j, grantees)
|
||||||
{
|
{
|
||||||
PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
|
PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
|
||||||
AclItem aclitem;
|
AclItem aclitem;
|
||||||
uint32 idtype;
|
uint32 idtype;
|
||||||
Acl *newer_acl;
|
Acl *newer_acl;
|
||||||
|
|
||||||
if (grantee->username)
|
if (grantee->username)
|
||||||
{
|
{
|
||||||
aclitem.ai_grantee = get_usesysid(grantee->username);
|
aclitem. ai_grantee = get_usesysid(grantee->username);
|
||||||
|
|
||||||
idtype = ACL_IDTYPE_UID;
|
idtype = ACL_IDTYPE_UID;
|
||||||
}
|
}
|
||||||
else if (grantee->groupname)
|
else if (grantee->groupname)
|
||||||
{
|
{
|
||||||
aclitem.ai_grantee = get_grosysid(grantee->groupname);
|
aclitem. ai_grantee = get_grosysid(grantee->groupname);
|
||||||
|
|
||||||
idtype = ACL_IDTYPE_GID;
|
idtype = ACL_IDTYPE_GID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aclitem.ai_grantee = ACL_ID_WORLD;
|
aclitem. ai_grantee = ACL_ID_WORLD;
|
||||||
|
|
||||||
idtype = ACL_IDTYPE_WORLD;
|
idtype = ACL_IDTYPE_WORLD;
|
||||||
}
|
}
|
||||||
@ -157,18 +157,19 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant,
|
|||||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
||||||
errmsg("grant options can only be granted to individual users")));
|
errmsg("grant options can only be granted to individual users")));
|
||||||
|
|
||||||
aclitem.ai_grantor = grantor_uid;
|
aclitem. ai_grantor = grantor_uid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The asymmetry in the conditions here comes from the spec. In
|
* The asymmetry in the conditions here comes from the spec. In
|
||||||
* GRANT, the grant_option flag signals WITH GRANT OPTION, which means
|
* GRANT, the grant_option flag signals WITH GRANT OPTION, which
|
||||||
* to grant both the basic privilege and its grant option. But in
|
* means to grant both the basic privilege and its grant option.
|
||||||
* REVOKE, plain revoke revokes both the basic privilege and its
|
* But in REVOKE, plain revoke revokes both the basic privilege
|
||||||
* grant option, while REVOKE GRANT OPTION revokes only the option.
|
* and its grant option, while REVOKE GRANT OPTION revokes only
|
||||||
|
* the option.
|
||||||
*/
|
*/
|
||||||
ACLITEM_SET_PRIVS_IDTYPE(aclitem,
|
ACLITEM_SET_PRIVS_IDTYPE(aclitem,
|
||||||
(is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
|
(is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
|
||||||
(!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS,
|
(!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS,
|
||||||
idtype);
|
idtype);
|
||||||
|
|
||||||
newer_acl = aclupdate(new_acl, &aclitem, modechg, owner_uid, behavior);
|
newer_acl = aclupdate(new_acl, &aclitem, modechg, owner_uid, behavior);
|
||||||
@ -318,11 +319,11 @@ ExecuteGrantStmt_Relation(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -476,11 +477,11 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -630,11 +631,11 @@ ExecuteGrantStmt_Function(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -761,7 +762,7 @@ ExecuteGrantStmt_Language(GrantStmt *stmt)
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("language \"%s\" is not trusted", langname),
|
errmsg("language \"%s\" is not trusted", langname),
|
||||||
errhint("Only superusers may use untrusted languages.")));
|
errhint("Only superusers may use untrusted languages.")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: for now, languages are treated as owned by the bootstrap
|
* Note: for now, languages are treated as owned by the bootstrap
|
||||||
@ -793,11 +794,11 @@ ExecuteGrantStmt_Language(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -946,11 +947,11 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -1039,8 +1040,8 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
|||||||
if (priv & ~((AclMode) ACL_ALL_RIGHTS_TABLESPACE))
|
if (priv & ~((AclMode) ACL_ALL_RIGHTS_TABLESPACE))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
||||||
errmsg("invalid privilege type %s for tablespace",
|
errmsg("invalid privilege type %s for tablespace",
|
||||||
privilege_to_string(priv))));
|
privilege_to_string(priv))));
|
||||||
privileges |= priv;
|
privileges |= priv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1076,7 +1077,7 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
|||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("tablespace \"%s\" does not exist", spcname)));
|
errmsg("tablespace \"%s\" does not exist", spcname)));
|
||||||
pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
|
pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
|
||||||
|
|
||||||
ownerId = pg_tablespace_tuple->spcowner;
|
ownerId = pg_tablespace_tuple->spcowner;
|
||||||
@ -1105,11 +1106,11 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrict the operation to what we can actually grant or revoke,
|
* Restrict the operation to what we can actually grant or revoke,
|
||||||
* and issue a warning if appropriate. (For REVOKE this isn't quite
|
* and issue a warning if appropriate. (For REVOKE this isn't
|
||||||
* what the spec says to do: the spec seems to want a warning only
|
* quite what the spec says to do: the spec seems to want a
|
||||||
* if no privilege bits actually change in the ACL. In practice
|
* warning only if no privilege bits actually change in the ACL.
|
||||||
* that behavior seems much too noisy, as well as inconsistent with
|
* In practice that behavior seems much too noisy, as well as
|
||||||
* the GRANT case.)
|
* inconsistent with the GRANT case.)
|
||||||
*/
|
*/
|
||||||
this_privileges = privileges & my_goptions;
|
this_privileges = privileges & my_goptions;
|
||||||
if (stmt->is_grant)
|
if (stmt->is_grant)
|
||||||
@ -1389,11 +1390,12 @@ pg_class_aclmask(Oid table_oid, AclId userid,
|
|||||||
/*
|
/*
|
||||||
* Deny anyone permission to update a system catalog unless
|
* Deny anyone permission to update a system catalog unless
|
||||||
* pg_shadow.usecatupd is set. (This is to let superusers protect
|
* pg_shadow.usecatupd is set. (This is to let superusers protect
|
||||||
* themselves from themselves.) Also allow it if allowSystemTableMods.
|
* themselves from themselves.) Also allow it if
|
||||||
|
* allowSystemTableMods.
|
||||||
*
|
*
|
||||||
* As of 7.4 we have some updatable system views; those shouldn't
|
* As of 7.4 we have some updatable system views; those shouldn't be
|
||||||
* be protected in this way. Assume the view rules can take care
|
* protected in this way. Assume the view rules can take care of
|
||||||
* of themselves.
|
* themselves.
|
||||||
*/
|
*/
|
||||||
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
|
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
|
||||||
IsSystemClass(classForm) &&
|
IsSystemClass(classForm) &&
|
||||||
@ -1648,23 +1650,23 @@ pg_namespace_aclmask(Oid nsp_oid, AclId userid,
|
|||||||
return mask;
|
return mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have been assigned this namespace as a temp namespace,
|
* If we have been assigned this namespace as a temp namespace, check
|
||||||
* check to make sure we have CREATE TEMP permission on the database,
|
* to make sure we have CREATE TEMP permission on the database, and if
|
||||||
* and if so act as though we have all standard (but not GRANT OPTION)
|
* so act as though we have all standard (but not GRANT OPTION)
|
||||||
* permissions on the namespace. If we don't have CREATE TEMP, act as
|
* permissions on the namespace. If we don't have CREATE TEMP, act as
|
||||||
* though we have only USAGE (and not CREATE) rights.
|
* though we have only USAGE (and not CREATE) rights.
|
||||||
*
|
*
|
||||||
* This may seem redundant given the check in InitTempTableNamespace,
|
* This may seem redundant given the check in InitTempTableNamespace, but
|
||||||
* but it really isn't since current user ID may have changed since then.
|
* it really isn't since current user ID may have changed since then.
|
||||||
* The upshot of this behavior is that a SECURITY DEFINER function can
|
* The upshot of this behavior is that a SECURITY DEFINER function can
|
||||||
* create temp tables that can then be accessed (if permission is granted)
|
* create temp tables that can then be accessed (if permission is
|
||||||
* by code in the same session that doesn't have permissions to create
|
* granted) by code in the same session that doesn't have permissions
|
||||||
* temp tables.
|
* to create temp tables.
|
||||||
*
|
*
|
||||||
* XXX Would it be safe to ereport a special error message as
|
* XXX Would it be safe to ereport a special error message as
|
||||||
* InitTempTableNamespace does? Returning zero here means we'll get a
|
* InitTempTableNamespace does? Returning zero here means we'll get a
|
||||||
* generic "permission denied for schema pg_temp_N" message, which is not
|
* generic "permission denied for schema pg_temp_N" message, which is
|
||||||
* remarkably user-friendly.
|
* not remarkably user-friendly.
|
||||||
*/
|
*/
|
||||||
if (isTempNamespace(nsp_oid))
|
if (isTempNamespace(nsp_oid))
|
||||||
{
|
{
|
||||||
@ -1731,8 +1733,8 @@ pg_tablespace_aclmask(Oid spc_oid, AclId userid,
|
|||||||
AclId ownerId;
|
AclId ownerId;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only shared relations can be stored in global space; don't let
|
* Only shared relations can be stored in global space; don't let even
|
||||||
* even superusers override this
|
* superusers override this
|
||||||
*/
|
*/
|
||||||
if (spc_oid == GLOBALTABLESPACE_OID && !IsBootstrapProcessingMode())
|
if (spc_oid == GLOBALTABLESPACE_OID && !IsBootstrapProcessingMode())
|
||||||
return 0;
|
return 0;
|
||||||
@ -1756,7 +1758,7 @@ pg_tablespace_aclmask(Oid spc_oid, AclId userid,
|
|||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("tablespace with OID %u does not exist", spc_oid)));
|
errmsg("tablespace with OID %u does not exist", spc_oid)));
|
||||||
|
|
||||||
ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
|
ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
|
||||||
|
|
||||||
@ -2034,7 +2036,7 @@ pg_tablespace_ownercheck(Oid spc_oid, AclId userid)
|
|||||||
if (!HeapTupleIsValid(spctuple))
|
if (!HeapTupleIsValid(spctuple))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("tablespace with OID %u does not exist", spc_oid)));
|
errmsg("tablespace with OID %u does not exist", spc_oid)));
|
||||||
|
|
||||||
spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
|
spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
|
||||||
|
|
||||||
@ -2131,7 +2133,7 @@ pg_conversion_ownercheck(Oid conv_oid, AclId userid)
|
|||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("conversion with OID %u does not exist", conv_oid)));
|
errmsg("conversion with OID %u does not exist", conv_oid)));
|
||||||
|
|
||||||
owner_id = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
|
owner_id = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.38 2004/08/29 04:12:27 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.39 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -970,6 +970,7 @@ find_expr_references_walker(Node *node,
|
|||||||
if (var->varno <= 0 || var->varno > list_length(rtable))
|
if (var->varno <= 0 || var->varno > list_length(rtable))
|
||||||
elog(ERROR, "invalid varno %d", var->varno);
|
elog(ERROR, "invalid varno %d", var->varno);
|
||||||
rte = rt_fetch(var->varno, rtable);
|
rte = rt_fetch(var->varno, rtable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A whole-row Var references no specific columns, so adds no new
|
* A whole-row Var references no specific columns, so adds no new
|
||||||
* dependency.
|
* dependency.
|
||||||
@ -995,7 +996,7 @@ find_expr_references_walker(Node *node,
|
|||||||
var->varattno > list_length(rte->joinaliasvars))
|
var->varattno > list_length(rte->joinaliasvars))
|
||||||
elog(ERROR, "invalid varattno %d", var->varattno);
|
elog(ERROR, "invalid varattno %d", var->varattno);
|
||||||
find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
|
find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
|
||||||
var->varattno - 1),
|
var->varattno - 1),
|
||||||
context);
|
context);
|
||||||
list_free(context->rtables);
|
list_free(context->rtables);
|
||||||
context->rtables = save_rtables;
|
context->rtables = save_rtables;
|
||||||
@ -1424,8 +1425,8 @@ getObjectDescription(const ObjectAddress *object)
|
|||||||
getRelationDescription(&buffer, object->objectId);
|
getRelationDescription(&buffer, object->objectId);
|
||||||
if (object->objectSubId != 0)
|
if (object->objectSubId != 0)
|
||||||
appendStringInfo(&buffer, gettext(" column %s"),
|
appendStringInfo(&buffer, gettext(" column %s"),
|
||||||
get_relid_attribute_name(object->objectId,
|
get_relid_attribute_name(object->objectId,
|
||||||
object->objectSubId));
|
object->objectSubId));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OCLASS_PROC:
|
case OCLASS_PROC:
|
||||||
@ -1624,7 +1625,7 @@ getObjectDescription(const ObjectAddress *object)
|
|||||||
|
|
||||||
appendStringInfo(&buffer, gettext("operator class %s for %s"),
|
appendStringInfo(&buffer, gettext("operator class %s for %s"),
|
||||||
quote_qualified_identifier(nspname,
|
quote_qualified_identifier(nspname,
|
||||||
NameStr(opcForm->opcname)),
|
NameStr(opcForm->opcname)),
|
||||||
NameStr(amForm->amname));
|
NameStr(amForm->amname));
|
||||||
|
|
||||||
ReleaseSysCache(amTup);
|
ReleaseSysCache(amTup);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.274 2004/08/29 04:12:27 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.275 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -265,10 +265,10 @@ heap_create(const char *relname,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Never allow a pg_class entry to explicitly specify the database's
|
* Never allow a pg_class entry to explicitly specify the database's
|
||||||
* default tablespace in reltablespace; force it to zero instead.
|
* default tablespace in reltablespace; force it to zero instead. This
|
||||||
* This ensures that if the database is cloned with a different
|
* ensures that if the database is cloned with a different default
|
||||||
* default tablespace, the pg_class entry will still match where
|
* tablespace, the pg_class entry will still match where CREATE
|
||||||
* CREATE DATABASE will put the physically copied relation.
|
* DATABASE will put the physically copied relation.
|
||||||
*
|
*
|
||||||
* Yes, this is a bit of a hack.
|
* Yes, this is a bit of a hack.
|
||||||
*/
|
*/
|
||||||
@ -294,7 +294,8 @@ heap_create(const char *relname,
|
|||||||
nailme);
|
nailme);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* have the storage manager create the relation's disk file, if needed.
|
* have the storage manager create the relation's disk file, if
|
||||||
|
* needed.
|
||||||
*/
|
*/
|
||||||
if (create_storage)
|
if (create_storage)
|
||||||
{
|
{
|
||||||
@ -980,12 +981,12 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the type OID to invalid. A dropped attribute's type link
|
* Set the type OID to invalid. A dropped attribute's type link
|
||||||
* cannot be relied on (once the attribute is dropped, the type might
|
* cannot be relied on (once the attribute is dropped, the type
|
||||||
* be too). Fortunately we do not need the type row --- the only
|
* might be too). Fortunately we do not need the type row --- the
|
||||||
* really essential information is the type's typlen and typalign,
|
* only really essential information is the type's typlen and
|
||||||
* which are preserved in the attribute's attlen and attalign. We set
|
* typalign, which are preserved in the attribute's attlen and
|
||||||
* atttypid to zero here as a means of catching code that incorrectly
|
* attalign. We set atttypid to zero here as a means of catching
|
||||||
* expects it to be valid.
|
* code that incorrectly expects it to be valid.
|
||||||
*/
|
*/
|
||||||
attStruct->atttypid = InvalidOid;
|
attStruct->atttypid = InvalidOid;
|
||||||
|
|
||||||
@ -995,7 +996,10 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
|
|||||||
/* We don't want to keep stats for it anymore */
|
/* We don't want to keep stats for it anymore */
|
||||||
attStruct->attstattarget = 0;
|
attStruct->attstattarget = 0;
|
||||||
|
|
||||||
/* Change the column name to something that isn't likely to conflict */
|
/*
|
||||||
|
* Change the column name to something that isn't likely to
|
||||||
|
* conflict
|
||||||
|
*/
|
||||||
snprintf(newattname, sizeof(newattname),
|
snprintf(newattname, sizeof(newattname),
|
||||||
"........pg.dropped.%d........", attnum);
|
"........pg.dropped.%d........", attnum);
|
||||||
namestrcpy(&(attStruct->attname), newattname);
|
namestrcpy(&(attStruct->attname), newattname);
|
||||||
@ -1199,7 +1203,7 @@ heap_drop_with_catalog(Oid relid)
|
|||||||
/*
|
/*
|
||||||
* Flush the relation from the relcache. We want to do this before
|
* Flush the relation from the relcache. We want to do this before
|
||||||
* starting to remove catalog entries, just to be certain that no
|
* starting to remove catalog entries, just to be certain that no
|
||||||
* relcache entry rebuild will happen partway through. (That should
|
* relcache entry rebuild will happen partway through. (That should
|
||||||
* not really matter, since we don't do CommandCounterIncrement here,
|
* not really matter, since we don't do CommandCounterIncrement here,
|
||||||
* but let's be safe.)
|
* but let's be safe.)
|
||||||
*/
|
*/
|
||||||
@ -1584,11 +1588,11 @@ AddRelationRawConstraints(Relation rel,
|
|||||||
if (pstate->p_hasSubLinks)
|
if (pstate->p_hasSubLinks)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot use subquery in check constraint")));
|
errmsg("cannot use subquery in check constraint")));
|
||||||
if (pstate->p_hasAggs)
|
if (pstate->p_hasAggs)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_GROUPING_ERROR),
|
(errcode(ERRCODE_GROUPING_ERROR),
|
||||||
errmsg("cannot use aggregate function in check constraint")));
|
errmsg("cannot use aggregate function in check constraint")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check name uniqueness, or generate a name if none was given.
|
* Check name uniqueness, or generate a name if none was given.
|
||||||
@ -1614,8 +1618,8 @@ AddRelationRawConstraints(Relation rel,
|
|||||||
if (strcmp((char *) lfirst(cell2), ccname) == 0)
|
if (strcmp((char *) lfirst(cell2), ccname) == 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||||
errmsg("check constraint \"%s\" already exists",
|
errmsg("check constraint \"%s\" already exists",
|
||||||
ccname)));
|
ccname)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1623,18 +1627,18 @@ AddRelationRawConstraints(Relation rel,
|
|||||||
/*
|
/*
|
||||||
* When generating a name, we want to create "tab_col_check"
|
* When generating a name, we want to create "tab_col_check"
|
||||||
* for a column constraint and "tab_check" for a table
|
* for a column constraint and "tab_check" for a table
|
||||||
* constraint. We no longer have any info about the
|
* constraint. We no longer have any info about the syntactic
|
||||||
* syntactic positioning of the constraint phrase, so we
|
* positioning of the constraint phrase, so we approximate
|
||||||
* approximate this by seeing whether the expression references
|
* this by seeing whether the expression references more than
|
||||||
* more than one column. (If the user played by the rules,
|
* one column. (If the user played by the rules, the result
|
||||||
* the result is the same...)
|
* is the same...)
|
||||||
*
|
*
|
||||||
* Note: pull_var_clause() doesn't descend into sublinks,
|
* Note: pull_var_clause() doesn't descend into sublinks, but we
|
||||||
* but we eliminated those above; and anyway this only needs
|
* eliminated those above; and anyway this only needs to be an
|
||||||
* to be an approximate answer.
|
* approximate answer.
|
||||||
*/
|
*/
|
||||||
List *vars;
|
List *vars;
|
||||||
char *colname;
|
char *colname;
|
||||||
|
|
||||||
vars = pull_var_clause(expr, false);
|
vars = pull_var_clause(expr, false);
|
||||||
|
|
||||||
@ -1763,7 +1767,7 @@ cookDefault(ParseState *pstate,
|
|||||||
if (contain_var_clause(expr))
|
if (contain_var_clause(expr))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||||
errmsg("cannot use column references in default expression")));
|
errmsg("cannot use column references in default expression")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It can't return a set either.
|
* It can't return a set either.
|
||||||
@ -1783,7 +1787,7 @@ cookDefault(ParseState *pstate,
|
|||||||
if (pstate->p_hasAggs)
|
if (pstate->p_hasAggs)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_GROUPING_ERROR),
|
(errcode(ERRCODE_GROUPING_ERROR),
|
||||||
errmsg("cannot use aggregate function in default expression")));
|
errmsg("cannot use aggregate function in default expression")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Coerce the expression to the correct type and typmod, if given.
|
* Coerce the expression to the correct type and typmod, if given.
|
||||||
@ -2047,7 +2051,7 @@ heap_truncate_check_FKs(Relation rel)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, must scan pg_constraint. Right now, this is a seqscan
|
* Otherwise, must scan pg_constraint. Right now, this is a seqscan
|
||||||
* because there is no available index on confrelid.
|
* because there is no available index on confrelid.
|
||||||
*/
|
*/
|
||||||
fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock);
|
fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.237 2004/08/29 04:12:27 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.238 2004/08/29 05:06:41 momjian Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -511,9 +511,10 @@ index_create(Oid heapRelationId,
|
|||||||
* We cannot allow indexing a shared relation after initdb (because
|
* We cannot allow indexing a shared relation after initdb (because
|
||||||
* there's no way to make the entry in other databases' pg_class).
|
* there's no way to make the entry in other databases' pg_class).
|
||||||
* Unfortunately we can't distinguish initdb from a manually started
|
* Unfortunately we can't distinguish initdb from a manually started
|
||||||
* standalone backend (toasting of shared rels happens after the bootstrap
|
* standalone backend (toasting of shared rels happens after the
|
||||||
* phase, so checking IsBootstrapProcessingMode() won't work). However,
|
* bootstrap phase, so checking IsBootstrapProcessingMode() won't
|
||||||
* we can at least prevent this mistake under normal multi-user operation.
|
* work). However, we can at least prevent this mistake under normal
|
||||||
|
* multi-user operation.
|
||||||
*/
|
*/
|
||||||
if (shared_relation && IsUnderPostmaster)
|
if (shared_relation && IsUnderPostmaster)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -800,8 +801,8 @@ index_drop(Oid indexId)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Close and flush the index's relcache entry, to ensure relcache
|
* Close and flush the index's relcache entry, to ensure relcache
|
||||||
* doesn't try to rebuild it while we're deleting catalog entries.
|
* doesn't try to rebuild it while we're deleting catalog entries. We
|
||||||
* We keep the lock though.
|
* keep the lock though.
|
||||||
*/
|
*/
|
||||||
index_close(userIndexRelation);
|
index_close(userIndexRelation);
|
||||||
|
|
||||||
@ -826,8 +827,8 @@ index_drop(Oid indexId)
|
|||||||
heap_close(indexRelation, RowExclusiveLock);
|
heap_close(indexRelation, RowExclusiveLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if it has any expression columns, we might have stored
|
* if it has any expression columns, we might have stored statistics
|
||||||
* statistics about them.
|
* about them.
|
||||||
*/
|
*/
|
||||||
if (hasexprs)
|
if (hasexprs)
|
||||||
RemoveStatistics(indexId, 0);
|
RemoveStatistics(indexId, 0);
|
||||||
@ -1008,7 +1009,7 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the tuple to update in pg_class. In bootstrap mode we can't
|
* Find the tuple to update in pg_class. In bootstrap mode we can't
|
||||||
* use heap_update, so cheat and overwrite the tuple in-place. In
|
* use heap_update, so cheat and overwrite the tuple in-place. In
|
||||||
* normal processing, make a copy to scribble on.
|
* normal processing, make a copy to scribble on.
|
||||||
*/
|
*/
|
||||||
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
@ -1122,13 +1123,13 @@ setNewRelfilenode(Relation relation)
|
|||||||
newrelfilenode = newoid();
|
newrelfilenode = newoid();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the pg_class tuple for the given relation. This is not used
|
* Find the pg_class tuple for the given relation. This is not used
|
||||||
* during bootstrap, so okay to use heap_update always.
|
* during bootstrap, so okay to use heap_update always.
|
||||||
*/
|
*/
|
||||||
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
|
|
||||||
tuple = SearchSysCacheCopy(RELOID,
|
tuple = SearchSysCacheCopy(RELOID,
|
||||||
ObjectIdGetDatum(RelationGetRelid(relation)),
|
ObjectIdGetDatum(RelationGetRelid(relation)),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "could not find tuple for relation %u",
|
elog(ERROR, "could not find tuple for relation %u",
|
||||||
@ -1206,15 +1207,15 @@ UpdateStats(Oid relid, double reltuples)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the tuple to update in pg_class. Normally we make a copy of
|
* Find the tuple to update in pg_class. Normally we make a copy of
|
||||||
* the tuple using the syscache, modify it, and apply heap_update.
|
* the tuple using the syscache, modify it, and apply heap_update. But
|
||||||
* But in bootstrap mode we can't use heap_update, so we cheat and
|
* in bootstrap mode we can't use heap_update, so we cheat and
|
||||||
* overwrite the tuple in-place.
|
* overwrite the tuple in-place.
|
||||||
*
|
*
|
||||||
* We also must cheat if reindexing pg_class itself, because the
|
* We also must cheat if reindexing pg_class itself, because the target
|
||||||
* target index may presently not be part of the set of indexes that
|
* index may presently not be part of the set of indexes that
|
||||||
* CatalogUpdateIndexes would update (see reindex_relation). In this
|
* CatalogUpdateIndexes would update (see reindex_relation). In this
|
||||||
* case the stats updates will not be WAL-logged and so could be lost
|
* case the stats updates will not be WAL-logged and so could be lost
|
||||||
* in a crash. This seems OK considering VACUUM does the same thing.
|
* in a crash. This seems OK considering VACUUM does the same thing.
|
||||||
*/
|
*/
|
||||||
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
|
|
||||||
@ -1454,7 +1455,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
scan = heap_beginscan(heapRelation, /* relation */
|
scan = heap_beginscan(heapRelation, /* relation */
|
||||||
snapshot, /* seeself */
|
snapshot, /* seeself */
|
||||||
0, /* number of keys */
|
0, /* number of keys */
|
||||||
NULL); /* scan key */
|
NULL); /* scan key */
|
||||||
|
|
||||||
reltuples = 0;
|
reltuples = 0;
|
||||||
|
|
||||||
@ -1513,7 +1514,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
* system catalogs before committing.
|
* system catalogs before committing.
|
||||||
*/
|
*/
|
||||||
if (!TransactionIdIsCurrentTransactionId(
|
if (!TransactionIdIsCurrentTransactionId(
|
||||||
HeapTupleHeaderGetXmin(heapTuple->t_data))
|
HeapTupleHeaderGetXmin(heapTuple->t_data))
|
||||||
&& !IsSystemRelation(heapRelation))
|
&& !IsSystemRelation(heapRelation))
|
||||||
elog(ERROR, "concurrent insert in progress");
|
elog(ERROR, "concurrent insert in progress");
|
||||||
indexIt = true;
|
indexIt = true;
|
||||||
@ -1531,7 +1532,7 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
* system catalogs before committing.
|
* system catalogs before committing.
|
||||||
*/
|
*/
|
||||||
if (!TransactionIdIsCurrentTransactionId(
|
if (!TransactionIdIsCurrentTransactionId(
|
||||||
HeapTupleHeaderGetXmax(heapTuple->t_data))
|
HeapTupleHeaderGetXmax(heapTuple->t_data))
|
||||||
&& !IsSystemRelation(heapRelation))
|
&& !IsSystemRelation(heapRelation))
|
||||||
elog(ERROR, "concurrent delete in progress");
|
elog(ERROR, "concurrent delete in progress");
|
||||||
indexIt = true;
|
indexIt = true;
|
||||||
@ -1659,11 +1660,11 @@ reindex_index(Oid indexId)
|
|||||||
* Note: for REINDEX INDEX, doing this before opening the parent heap
|
* Note: for REINDEX INDEX, doing this before opening the parent heap
|
||||||
* relation means there's a possibility for deadlock failure against
|
* relation means there's a possibility for deadlock failure against
|
||||||
* another xact that is doing normal accesses to the heap and index.
|
* another xact that is doing normal accesses to the heap and index.
|
||||||
* However, it's not real clear why you'd be wanting to do REINDEX INDEX
|
* However, it's not real clear why you'd be wanting to do REINDEX
|
||||||
* on a table that's in active use, so I'd rather have the protection of
|
* INDEX on a table that's in active use, so I'd rather have the
|
||||||
* making sure the index is locked down. In the REINDEX TABLE and
|
* protection of making sure the index is locked down. In the REINDEX
|
||||||
* REINDEX DATABASE cases, there is no problem because caller already
|
* TABLE and REINDEX DATABASE cases, there is no problem because
|
||||||
* holds exclusive lock on the parent table.
|
* caller already holds exclusive lock on the parent table.
|
||||||
*/
|
*/
|
||||||
iRel = index_open(indexId);
|
iRel = index_open(indexId);
|
||||||
LockRelation(iRel, AccessExclusiveLock);
|
LockRelation(iRel, AccessExclusiveLock);
|
||||||
@ -1680,8 +1681,8 @@ reindex_index(Oid indexId)
|
|||||||
* we can do it the normal transaction-safe way.
|
* we can do it the normal transaction-safe way.
|
||||||
*
|
*
|
||||||
* Since inplace processing isn't crash-safe, we only allow it in a
|
* Since inplace processing isn't crash-safe, we only allow it in a
|
||||||
* standalone backend. (In the REINDEX TABLE and REINDEX DATABASE cases,
|
* standalone backend. (In the REINDEX TABLE and REINDEX DATABASE
|
||||||
* the caller should have detected this.)
|
* cases, the caller should have detected this.)
|
||||||
*/
|
*/
|
||||||
inplace = iRel->rd_rel->relisshared;
|
inplace = iRel->rd_rel->relisshared;
|
||||||
|
|
||||||
@ -1705,7 +1706,8 @@ reindex_index(Oid indexId)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Release any buffers associated with this index. If they're
|
* Release any buffers associated with this index. If they're
|
||||||
* dirty, they're just dropped without bothering to flush to disk.
|
* dirty, they're just dropped without bothering to flush to
|
||||||
|
* disk.
|
||||||
*/
|
*/
|
||||||
DropRelationBuffers(iRel);
|
DropRelationBuffers(iRel);
|
||||||
|
|
||||||
@ -1724,8 +1726,8 @@ reindex_index(Oid indexId)
|
|||||||
index_build(heapRelation, iRel, indexInfo);
|
index_build(heapRelation, iRel, indexInfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* index_build will close both the heap and index relations (but not
|
* index_build will close both the heap and index relations (but
|
||||||
* give up the locks we hold on them). So we're done.
|
* not give up the locks we hold on them). So we're done.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
PG_CATCH();
|
PG_CATCH();
|
||||||
@ -1774,13 +1776,13 @@ reindex_relation(Oid relid, bool toast_too)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* reindex_index will attempt to update the pg_class rows for the
|
* reindex_index will attempt to update the pg_class rows for the
|
||||||
* relation and index. If we are processing pg_class itself, we
|
* relation and index. If we are processing pg_class itself, we want
|
||||||
* want to make sure that the updates do not try to insert index
|
* to make sure that the updates do not try to insert index entries
|
||||||
* entries into indexes we have not processed yet. (When we are
|
* into indexes we have not processed yet. (When we are trying to
|
||||||
* trying to recover from corrupted indexes, that could easily
|
* recover from corrupted indexes, that could easily cause a crash.)
|
||||||
* cause a crash.) We can accomplish this because CatalogUpdateIndexes
|
* We can accomplish this because CatalogUpdateIndexes will use the
|
||||||
* will use the relcache's index list to know which indexes to update.
|
* relcache's index list to know which indexes to update. We just
|
||||||
* We just force the index list to be only the stuff we've processed.
|
* force the index list to be only the stuff we've processed.
|
||||||
*
|
*
|
||||||
* It is okay to not insert entries into the indexes we have not
|
* It is okay to not insert entries into the indexes we have not
|
||||||
* processed yet because all of this is transaction-safe. If we fail
|
* processed yet because all of this is transaction-safe. If we fail
|
||||||
@ -1795,7 +1797,7 @@ reindex_relation(Oid relid, bool toast_too)
|
|||||||
/* Reindex all the indexes. */
|
/* Reindex all the indexes. */
|
||||||
foreach(indexId, indexIds)
|
foreach(indexId, indexIds)
|
||||||
{
|
{
|
||||||
Oid indexOid = lfirst_oid(indexId);
|
Oid indexOid = lfirst_oid(indexId);
|
||||||
|
|
||||||
if (is_pg_class)
|
if (is_pg_class)
|
||||||
RelationSetIndexList(rel, doneIndexes);
|
RelationSetIndexList(rel, doneIndexes);
|
||||||
@ -1819,8 +1821,8 @@ reindex_relation(Oid relid, bool toast_too)
|
|||||||
result = (indexIds != NIL);
|
result = (indexIds != NIL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the relation has a secondary toast rel, reindex that too while we
|
* If the relation has a secondary toast rel, reindex that too while
|
||||||
* still hold the lock on the master table.
|
* we still hold the lock on the master table.
|
||||||
*/
|
*/
|
||||||
if (toast_too && OidIsValid(toast_relid))
|
if (toast_too && OidIsValid(toast_relid))
|
||||||
result |= reindex_relation(toast_relid, false);
|
result |= reindex_relation(toast_relid, false);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user