1
0
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:
Bruce Momjian 2004-08-29 05:07:03 +00:00
parent 90cb9c3051
commit b6b71b85bc
527 changed files with 20550 additions and 18283 deletions

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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));
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);
}

View File

@ -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);
} }

View File

@ -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));
}

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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]);
} }
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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)
{ {

View File

@ -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

View File

@ -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;

View File

@ -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);
} }

View File

@ -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];

View File

@ -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++)

View File

@ -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,

View File

@ -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)
{ {

View File

@ -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), ")");

View File

@ -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")));
} }

View File

@ -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;

View File

@ -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);

View File

@ -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;
} }

View File

@ -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

View File

@ -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),

View File

@ -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;

View File

@ -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++;
} }

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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();
} }

View File

@ -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();
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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()),

View File

@ -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

View File

@ -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;
}
} }

View File

@ -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++)
{ {

View File

@ -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;

View File

@ -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),

View File

@ -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

View File

@ -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,

View File

@ -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.)

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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))
{ {

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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.
*/ */

View File

@ -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)));
} }

View File

@ -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:

View File

@ -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);

View File

@ -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 (;;)
{ {

View File

@ -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))
{ {

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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)));
} }

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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