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

@ -25,63 +25,70 @@ 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;
@ -108,39 +115,39 @@ 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);
else
{ {
retval = gbt_var_consistent( &r, query, &strategy, TRUE, &tinfo ); bytea *q = gbt_bit_xfrm((bytea *) query);
} else {
bytea * q = gbt_bit_xfrm ( ( bytea * ) query ); retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo );
pfree(q); pfree(q);
} }
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);
} }
@ -149,9 +156,10 @@ 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));
} }
@ -160,7 +168,8 @@ 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 );
gbt_var_picksplit(entryvec, v, &tinfo);
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }
@ -170,7 +179,8 @@ 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));
} }
@ -178,8 +188,8 @@ 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

@ -23,36 +23,42 @@ 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))));
} }
@ -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));
} }
@ -89,22 +96,20 @@ 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,9 +118,10 @@ 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));
} }
@ -124,7 +130,8 @@ 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 );
gbt_var_picksplit(entryvec, v, &tinfo);
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }
@ -134,7 +141,8 @@ 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));
} }
@ -142,8 +150,8 @@ 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

@ -25,37 +25,40 @@ 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;
} }
@ -84,7 +87,8 @@ 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));
} }
@ -94,13 +98,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -110,8 +115,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -122,16 +128,17 @@ gbt_cash_penalty(PG_FUNCTION_ARGS)
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);
@ -155,8 +162,6 @@ gbt_cash_same(PG_FUNCTION_ARGS)
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

@ -25,38 +25,43 @@ 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,12 +70,10 @@ 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;
} }
@ -99,7 +102,8 @@ 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));
} }
@ -108,16 +112,16 @@ 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)
); );
} }
@ -127,8 +131,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -138,7 +143,8 @@ 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,
@ -156,14 +162,15 @@ gbt_date_penalty(PG_FUNCTION_ARGS)
*result = 0.0; *result = 0.0;
if ( res > 0 ){ if (res > 0)
{
diff = DatumGetInt32(DirectFunctionCall2( diff = DatumGetInt32(DirectFunctionCall2(
date_mi, date_mi,
DateADTGetDatum(origentry->upper), DateADTGetDatum(origentry->upper),
DateADTGetDatum(origentry->lower))); DateADTGetDatum(origentry->lower)));
*result += FLT_MIN ; *result += FLT_MIN;
*result += (float) ( res / ( (double) ( res + diff ) ) ); *result += (float) (res / ((double) (res + diff)));
*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));
} }
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
@ -187,6 +194,6 @@ gbt_date_same(PG_FUNCTION_ARGS)
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

@ -24,37 +24,40 @@ 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;
} }
@ -83,7 +86,8 @@ 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));
} }
@ -93,13 +97,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -109,8 +114,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -121,16 +127,17 @@ gbt_float4_penalty(PG_FUNCTION_ARGS)
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);
@ -154,7 +161,6 @@ gbt_float4_same(PG_FUNCTION_ARGS)
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

@ -25,37 +25,40 @@ 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;
} }
@ -84,7 +87,8 @@ 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));
} }
@ -95,13 +99,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -111,8 +116,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -123,16 +129,17 @@ gbt_float8_penalty(PG_FUNCTION_ARGS)
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);
@ -156,6 +163,6 @@ gbt_float8_same(PG_FUNCTION_ARGS)
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

@ -42,4 +42,3 @@ gbt_decompress(PG_FUNCTION_ARGS)
{ {
PG_RETURN_POINTER(PG_GETARG_POINTER(0)); PG_RETURN_POINTER(PG_GETARG_POINTER(0));
} }

View File

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

@ -32,37 +32,40 @@ 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;
} }
@ -88,15 +91,16 @@ 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)); retval = palloc(sizeof(GISTENTRY));
r->lower = convert_network_to_scalar(entry->key, typid ); r->lower = convert_network_to_scalar(entry->key, typid);
r->upper = r->lower ; r->upper = r->lower;
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(inetKEY), FALSE); entry->offset, sizeof(inetKEY), FALSE);
@ -104,7 +108,7 @@ gbt_inet_compress_inetrnal(GISTENTRY *retval , GISTENTRY *entry , Oid typid)
else else
retval = entry; retval = entry;
return ( retval ); return (retval);
} }
@ -114,7 +118,8 @@ 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
@ -122,24 +127,26 @@ 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); inetKEY *kkk = (inetKEY *) DatumGetPointer(entry->key);
GBT_NUMKEY_R 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)
); );
} }
@ -148,11 +155,11 @@ 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)
); );
} }
@ -160,11 +167,11 @@ 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)
); );
} }
@ -174,8 +181,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -186,16 +194,17 @@ gbt_inet_penalty(PG_FUNCTION_ARGS)
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);
@ -219,6 +228,6 @@ gbt_inet_same(PG_FUNCTION_ARGS)
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

@ -24,37 +24,40 @@ 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;
} }
@ -87,7 +90,8 @@ 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));
} }
@ -97,13 +101,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -113,8 +118,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -124,16 +130,17 @@ 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);
@ -156,6 +163,6 @@ gbt_int2_same(PG_FUNCTION_ARGS)
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

@ -25,37 +25,40 @@ 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;
} }
@ -84,7 +87,8 @@ 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));
} }
@ -95,13 +99,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -110,9 +115,10 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -122,16 +128,17 @@ 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);
@ -154,6 +161,6 @@ gbt_int4_same(PG_FUNCTION_ARGS)
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

@ -25,37 +25,40 @@ 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;
} }
@ -84,7 +87,8 @@ 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));
} }
@ -94,13 +98,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -110,8 +115,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -121,16 +127,17 @@ 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);
@ -154,7 +161,6 @@ gbt_int8_same(PG_FUNCTION_ARGS)
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,7 +3,8 @@
typedef struct typedef struct
{ {
Interval lower, upper; Interval lower,
upper;
} intvKEY; } intvKEY;
@ -27,58 +28,65 @@ 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
@ -106,17 +114,24 @@ 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); if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
{
char *r = (char *) palloc(2 * INTERVALSIZE);
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
if ( entry->leafkey ) { if (entry->leafkey)
{
Interval *key = DatumGetIntervalP(entry->key); Interval *key = DatumGetIntervalP(entry->key);
memcpy( (void*) r , (void*)key, INTERVALSIZE);
memcpy( (void*)(r + INTERVALSIZE), (void*)key, INTERVALSIZE); memcpy((void *) r, (void *) key, INTERVALSIZE);
} else { memcpy((void *) (r + INTERVALSIZE), (void *) key, INTERVALSIZE);
intvKEY *key = ( intvKEY * ) DatumGetPointer(entry->key); }
else
{
intvKEY *key = (intvKEY *) DatumGetPointer(entry->key);
memcpy(r, &key->lower, INTERVALSIZE); memcpy(r, &key->lower, INTERVALSIZE);
memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE); memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE);
} }
@ -135,13 +150,14 @@ 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)); intvKEY *r = palloc(sizeof(intvKEY));
char *key = DatumGetPointer(entry->key); 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,
@ -157,14 +173,14 @@ 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)
); );
} }
@ -174,8 +190,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -185,21 +202,24 @@ 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);
@ -223,7 +243,6 @@ gbt_intv_same(PG_FUNCTION_ARGS)
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

@ -27,28 +27,33 @@ 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)));
} }
@ -57,9 +62,9 @@ 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])
) )
); );
} }
@ -84,13 +89,15 @@ 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)
{
unsigned char *mi = (unsigned char *) m;
uint64 res = 0; uint64 res = 0;
int i; int i;
for (i=0; i<6; i++ ){
res += ( ( (uint64) mi[i] ) << ( (uint64) ( (5-i)*8 ) ) ); for (i = 0; i < 6; i++)
} res += (((uint64) mi[i]) << ((uint64) ((5 - i) * 8)));
return res; return res;
} }
@ -101,7 +108,8 @@ 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));
} }
@ -112,13 +120,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -128,8 +137,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -139,22 +149,24 @@ 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],
inew[2];
uint64 res; 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);
@ -178,7 +190,6 @@ gbt_macad_same(PG_FUNCTION_ARGS)
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

@ -23,36 +23,42 @@ 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))));
} }
@ -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));
} }
@ -90,22 +97,20 @@ 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);
} }
@ -115,8 +120,9 @@ 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));
} }
@ -126,29 +132,34 @@ 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,
@ -156,7 +167,7 @@ gbt_numeric_penalty (PG_FUNCTION_ARGS)
PointerGetDatum(uk.lower) PointerGetDatum(uk.lower)
)); ));
pfree ( DatumGetPointer(uni) ); pfree(DatumGetPointer(uni));
os = DatumGetNumeric(DirectFunctionCall2( os = DatumGetNumeric(DirectFunctionCall2(
numeric_sub, numeric_sub,
@ -170,48 +181,48 @@ gbt_numeric_penalty (PG_FUNCTION_ARGS)
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);
} }
@ -221,7 +232,7 @@ 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 );
gbt_var_picksplit(entryvec, v, &tinfo);
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }

View File

@ -25,37 +25,40 @@ 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;
} }
@ -84,7 +87,8 @@ 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));
} }
@ -95,13 +99,14 @@ 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 ; key.lower = (GBT_NUMKEY *) & kkk->lower;
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)
); );
} }
@ -111,8 +116,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -123,16 +129,17 @@ gbt_oid_penalty(PG_FUNCTION_ARGS)
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);
@ -155,6 +162,6 @@ gbt_oid_same(PG_FUNCTION_ARGS)
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

@ -26,34 +26,40 @@ 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,26 +68,26 @@ 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);
@ -90,16 +96,17 @@ gbt_text_xfrm ( bytea * leaf )
} }
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;
@ -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 }
else
retval = entry; retval = entry;
PG_RETURN_POINTER ( retval ); PG_RETURN_POINTER(retval);
} }
@ -170,30 +179,29 @@ 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);
else
{ {
retval = gbt_var_consistent( &r, query, &strategy, TRUE, &tinfo ); bytea *q = gbt_text_xfrm((bytea *) query);
} else {
bytea * q = gbt_text_xfrm ( ( bytea * ) query ); retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo ); if (q != query)
if ( q != query )
pfree(q); pfree(q);
} }
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);
} }
@ -203,33 +211,32 @@ 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);
else
{ {
retval = gbt_var_consistent( &r, trim , &strategy, TRUE, &tinfo ); bytea *q = gbt_text_xfrm((bytea *) trim);
} else {
bytea * q = gbt_text_xfrm ( ( bytea * ) trim ); retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
retval = gbt_var_consistent( &r, (void*)q, &strategy, FALSE, &tinfo ); if (q != trim)
if ( q != trim )
pfree(q); pfree(q);
} }
pfree(trim); pfree(trim);
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);
} }
@ -241,7 +248,8 @@ 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));
} }
@ -250,7 +258,8 @@ 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 );
gbt_var_picksplit(entryvec, v, &tinfo);
PG_RETURN_POINTER(v); PG_RETURN_POINTER(v);
} }
@ -260,7 +269,8 @@ 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));
} }
@ -268,8 +278,8 @@ 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

@ -30,38 +30,43 @@ 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,12 +75,10 @@ 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;
} }
@ -104,7 +107,8 @@ 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));
} }
@ -122,7 +126,7 @@ gbt_timetz_compress(PG_FUNCTION_ARGS)
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);
@ -137,17 +141,17 @@ 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)
); );
} }
@ -155,17 +159,17 @@ 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)
); );
} }
@ -175,8 +179,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -187,8 +192,10 @@ gbt_time_penalty(PG_FUNCTION_ARGS)
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
@ -213,15 +220,16 @@ gbt_time_penalty(PG_FUNCTION_ARGS)
*result = 0.0; *result = 0.0;
if ( res > 0 ){ if (res > 0)
{
intr = DatumGetIntervalP(DirectFunctionCall2( intr = DatumGetIntervalP(DirectFunctionCall2(
time_mi_time, time_mi_time,
TimeADTGetDatum(origentry->upper), TimeADTGetDatum(origentry->upper),
TimeADTGetDatum(origentry->lower))); TimeADTGetDatum(origentry->lower)));
*result += FLT_MIN ; *result += FLT_MIN;
*result += (float) ( res / ( (double) ( res + intr->time + intr->month * (30 * 86400) ) ) ); *result += (float) (res / ((double) (res + intr->time + intr->month * (30 * 86400))));
*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 ( intr ); pfree(intr);
} }
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
@ -245,7 +253,6 @@ gbt_time_same(PG_FUNCTION_ARGS)
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

@ -29,38 +29,43 @@ 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))
); );
} }
@ -68,12 +73,10 @@ static bool gbt_tslt (const void *a, const void *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;
} }
@ -97,14 +100,16 @@ 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;
@ -127,7 +132,8 @@ 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));
} }
@ -135,19 +141,19 @@ 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);
@ -155,7 +161,7 @@ gbt_tstz_compress(PG_FUNCTION_ARGS)
else else
retval = entry; retval = entry;
PG_RETURN_POINTER( retval ); PG_RETURN_POINTER(retval);
} }
@ -165,14 +171,14 @@ 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)
); );
} }
@ -182,16 +188,16 @@ 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)
); );
} }
@ -201,8 +207,9 @@ 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); *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
} }
@ -214,8 +221,10 @@ gbt_ts_penalty(PG_FUNCTION_ARGS)
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
@ -243,15 +252,16 @@ gbt_ts_penalty(PG_FUNCTION_ARGS)
*result = 0.0; *result = 0.0;
if ( res > 0 ){ if (res > 0)
{
intr = DatumGetIntervalP(DirectFunctionCall2( intr = DatumGetIntervalP(DirectFunctionCall2(
timestamp_mi, timestamp_mi,
TimestampGetDatum(origentry->upper), TimestampGetDatum(origentry->upper),
TimestampGetDatum(origentry->lower) TimestampGetDatum(origentry->lower)
)); ));
*result += FLT_MIN ; *result += FLT_MIN;
*result += (float) ( res / ( (double) ( res + intr->time + intr->month * (30 * 86400) ) ) ); *result += (float) (res / ((double) (res + intr->time + intr->month * (30 * 86400))));
*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(intr); pfree(intr);
} }
@ -277,7 +287,6 @@ gbt_ts_same(PG_FUNCTION_ARGS)
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,55 +3,57 @@
#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; int16 i2;
int32 i4; int32 i4;
TimeADT ts; TimeADT ts;
DateADT dt; DateADT dt;
} v ; } 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 }
else
retval = entry; retval = entry;
return retval; return retval;
@ -65,31 +67,32 @@ 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,19 +104,21 @@ 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;
@ -122,7 +127,7 @@ extern bool gbt_num_same ( const GBT_NUMKEY * a, const GBT_NUMKEY * b, const gbt
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;
@ -133,18 +138,19 @@ gbt_num_bin_union(Datum * u , GBT_NUMKEY * e , const gbtree_ninfo * tinfo )
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);
} }
} }
@ -157,8 +163,8 @@ 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
) )
@ -169,28 +175,28 @@ gbt_num_consistent(
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;
@ -201,15 +207,15 @@ gbt_num_consistent(
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);
@ -225,7 +231,7 @@ gbt_num_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v,
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 */

View File

@ -4,7 +4,8 @@ typedef char GBT_NUMKEY;
/* Better readable key */ /* Better readable key */
typedef struct typedef struct
{ {
const GBT_NUMKEY * lower, * upper; const GBT_NUMKEY *lower,
*upper;
} GBT_NUMKEY_R; } GBT_NUMKEY_R;
@ -12,7 +13,7 @@ typedef struct
typedef struct typedef struct
{ {
int i; int i;
GBT_NUMKEY * t; GBT_NUMKEY *t;
} Nsrt; } Nsrt;
@ -23,17 +24,17 @@ 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;
@ -52,22 +53,22 @@ typedef struct
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);

View File

@ -4,34 +4,42 @@
/* Returns a better readable representaion of variable key ( sets pointer ) */ /* Returns a better readable representaion of variable key ( sets pointer ) */
extern GBT_VARKEY_R gbt_var_key_readable ( const GBT_VARKEY * k ){ extern GBT_VARKEY_R
gbt_var_key_readable(const GBT_VARKEY * k)
{
GBT_VARKEY_R r ; GBT_VARKEY_R r;
r.lower = ( bytea * ) &(((char*)k)[VARHDRSZ] ) ;
if ( VARSIZE(k) > ( VARHDRSZ+(VARSIZE(r.lower)) ) ) r.lower = (bytea *) &(((char *) k)[VARHDRSZ]);
r.upper = ( bytea * ) &(((char*)k)[VARHDRSZ+INTALIGN(VARSIZE(r.lower))] ) ; if (VARSIZE(k) > (VARHDRSZ + (VARSIZE(r.lower))))
r.upper = (bytea *) &(((char *) k)[VARHDRSZ + INTALIGN(VARSIZE(r.lower))]);
else else
r.upper = r.lower; r.upper = r.lower;
return r; return r;
} }
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)
{
GBT_VARKEY * r = NULL; GBT_VARKEY *r = NULL;
if ( u->lower == u->upper && !force_node ){ /* leaf key mode */ if (u->lower == u->upper && !force_node)
{ /* leaf key mode */
r = (GBT_VARKEY *) palloc(VARSIZE(u->lower) + VARHDRSZ ); r = (GBT_VARKEY *) palloc(VARSIZE(u->lower) + VARHDRSZ);
memcpy ( (void*) VARDATA(r), (void*) u->lower , VARSIZE(u->lower) ); memcpy((void *) VARDATA(r), (void *) u->lower, VARSIZE(u->lower));
r->vl_len = VARSIZE(u->lower) + VARHDRSZ ; r->vl_len = VARSIZE(u->lower) + VARHDRSZ;
} else { /* node key mode */ }
else
{ /* node key mode */
r = (GBT_VARKEY *) palloc(INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ ); r = (GBT_VARKEY *) palloc(INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ);
memcpy ( (void*) VARDATA(r) , (void*) u->lower , VARSIZE(u->lower) ); memcpy((void *) VARDATA(r), (void *) u->lower, VARSIZE(u->lower));
memcpy ( (void*)&(((char *)r)[VARHDRSZ+INTALIGN(VARSIZE(u->lower))]), (void*) u->upper , VARSIZE(u->upper) ); memcpy((void *) &(((char *) r)[VARHDRSZ + INTALIGN(VARSIZE(u->lower))]), (void *) u->upper, VARSIZE(u->upper));
r->vl_len = INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ ; r->vl_len = INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ;
} }
return r; return r;
@ -39,15 +47,14 @@ extern GBT_VARKEY * gbt_var_key_copy ( const GBT_VARKEY_R * u , bool force_node
} }
static GBT_VARKEY * gbt_var_leaf2node ( GBT_VARKEY * leaf, const gbtree_vinfo * tinfo ) static GBT_VARKEY *
gbt_var_leaf2node(GBT_VARKEY * leaf, const gbtree_vinfo * tinfo)
{ {
GBT_VARKEY *out = leaf ; GBT_VARKEY *out = leaf;
if ( tinfo->f_l2n ) if (tinfo->f_l2n)
{
out = (*tinfo->f_l2n) (leaf); out = (*tinfo->f_l2n) (leaf);
}
return out; return out;
@ -57,28 +64,27 @@ static GBT_VARKEY * gbt_var_leaf2node ( GBT_VARKEY * leaf, const gbtree_vinfo *
/* /*
* returns the common prefix length of a node key * returns the common prefix length of a node key
*/ */
static int32 gbt_var_node_cp_len ( const GBT_VARKEY * node , const gbtree_vinfo * tinfo ) static int32
gbt_var_node_cp_len(const GBT_VARKEY * node, const gbtree_vinfo * tinfo)
{ {
int32 i ; int32 i;
int32 s = (tinfo->str)?(1):(0); int32 s = (tinfo->str) ? (1) : (0);
GBT_VARKEY_R r = gbt_var_key_readable ( node ); GBT_VARKEY_R r = gbt_var_key_readable(node);
int32 t1len = VARSIZE(r.lower) - VARHDRSZ - s; int32 t1len = VARSIZE(r.lower) - VARHDRSZ - s;
int32 t2len = VARSIZE(r.upper) - VARHDRSZ - s; int32 t2len = VARSIZE(r.upper) - VARHDRSZ - s;
int32 ml = Min(t1len,t2len) ; int32 ml = Min(t1len, t2len);
char * p1 = VARDATA(r.lower) , char *p1 = VARDATA(r.lower),
* p2 = VARDATA(r.upper) ; *p2 = VARDATA(r.upper);
for ( i=0 ; i<ml; i++ ) for (i = 0; i < ml; i++)
{
if ( *p1 != *p2 )
{ {
if (*p1 != *p2)
return i; return i;
}
p1++; p1++;
p2++; p2++;
} }
return ( ml ); return (ml);
} }
@ -87,26 +93,30 @@ static int32 gbt_var_node_cp_len ( const GBT_VARKEY * node , const gbtree_vinfo
* returns true, if query matches prefix using common prefix * returns true, if query matches prefix using common prefix
*/ */
static bool gbt_bytea_pf_match ( const bytea * pf , const bytea * query , const gbtree_vinfo * tinfo ) static bool
gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo * tinfo)
{ {
int k ; int k;
int32 s = (tinfo->str)?(1):(0); int32 s = (tinfo->str) ? (1) : (0);
bool out = FALSE ; bool out = FALSE;
int32 qlen = VARSIZE(query) - VARHDRSZ - s ; int32 qlen = VARSIZE(query) - VARHDRSZ - s;
int32 nlen = VARSIZE(pf) - VARHDRSZ - s ; int32 nlen = VARSIZE(pf) - VARHDRSZ - s;
if ( nlen <= qlen )
if (nlen <= qlen)
{ {
char *q = VARDATA(query) ; char *q = VARDATA(query);
char *n = VARDATA(pf) ; char *n = VARDATA(pf);
out = TRUE; out = TRUE;
for ( k=0 ; k<nlen; k++ ) for (k = 0; k < nlen; k++)
{
if (*n != *q)
{ {
if ( *n != *q ){
out = FALSE; out = FALSE;
break; break;
} }
if ( k < (nlen-1) ) if (k < (nlen - 1))
{ {
q++; q++;
n++; n++;
@ -124,12 +134,13 @@ static bool gbt_bytea_pf_match ( const bytea * pf , const bytea * query , const
* returns true, if query matches node using common prefix * returns true, if query matches node using common prefix
*/ */
static bool gbt_var_node_pf_match ( const GBT_VARKEY_R * node , const bytea * query , const gbtree_vinfo * tinfo ) static bool
gbt_var_node_pf_match(const GBT_VARKEY_R * node, const bytea *query, const gbtree_vinfo * tinfo)
{ {
return ( return (
gbt_bytea_pf_match ( node->lower, query , tinfo ) || gbt_bytea_pf_match(node->lower, query, tinfo) ||
gbt_bytea_pf_match ( node->upper, query , tinfo ) gbt_bytea_pf_match(node->upper, query, tinfo)
); );
} }
@ -138,12 +149,13 @@ static bool gbt_var_node_pf_match ( const GBT_VARKEY_R * node , const bytea * qu
/* /*
* truncates / compresses the node key * truncates / compresses the node key
*/ */
static GBT_VARKEY * gbt_var_node_truncate ( const GBT_VARKEY * node , int32 length , const gbtree_vinfo * tinfo ) static GBT_VARKEY *
gbt_var_node_truncate(const GBT_VARKEY * node, int32 length, const gbtree_vinfo * tinfo)
{ {
int32 s = (tinfo->str)?(1):(0); int32 s = (tinfo->str) ? (1) : (0);
GBT_VARKEY * out = NULL; GBT_VARKEY *out = NULL;
GBT_VARKEY_R r = gbt_var_key_readable ( node ); GBT_VARKEY_R r = gbt_var_key_readable(node);
int32 len1 = VARSIZE(r.lower) - VARHDRSZ; int32 len1 = VARSIZE(r.lower) - VARHDRSZ;
int32 len2 = VARSIZE(r.upper) - VARHDRSZ; int32 len2 = VARSIZE(r.upper) - VARHDRSZ;
int32 si = 0; int32 si = 0;
@ -151,21 +163,21 @@ static GBT_VARKEY * gbt_var_node_truncate ( const GBT_VARKEY * node , int32 leng
if (tinfo->str) if (tinfo->str)
length++; /* because of tailing '\0' */ length++; /* because of tailing '\0' */
len1 = Min( len1, length ) ; len1 = Min(len1, length);
len2 = Min( len2, length ) ; len2 = Min(len2, length);
si = 2*VARHDRSZ + INTALIGN(VARHDRSZ+len1) + len2; si = 2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2;
out = (GBT_VARKEY *) palloc ( si ); out = (GBT_VARKEY *) palloc(si);
out->vl_len = si; out->vl_len = si;
memcpy ( (void*) &(((char*)out)[VARHDRSZ]) , (void*)r.lower, len1+VARHDRSZ-s ); memcpy((void *) &(((char *) out)[VARHDRSZ]), (void *) r.lower, len1 + VARHDRSZ - s);
memcpy ( (void*) &(((char*)out)[VARHDRSZ+INTALIGN(VARHDRSZ+len1)]) , (void*)r.upper, len2+VARHDRSZ-s ); memcpy((void *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)]), (void *) r.upper, len2 + VARHDRSZ - s);
if (tinfo->str) if (tinfo->str)
{ {
((char*)out)[VARHDRSZ+INTALIGN(VARHDRSZ+len1)-1] = '\0'; ((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1) - 1] = '\0';
((char*)out)[2*VARHDRSZ+INTALIGN(VARHDRSZ+len1)+len2-1] = '\0'; ((char *) out)[2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2 - 1] = '\0';
} }
*((int32*)&(((char*)out)[VARHDRSZ])) = len1 + VARHDRSZ; *((int32 *) &(((char *) out)[VARHDRSZ])) = len1 + VARHDRSZ;
*((int32*)&(((char*)out)[VARHDRSZ+INTALIGN(VARHDRSZ+len1)])) = len2 + VARHDRSZ; *((int32 *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)])) = len2 + VARHDRSZ;
return out; return out;
} }
@ -173,40 +185,42 @@ static GBT_VARKEY * gbt_var_node_truncate ( const GBT_VARKEY * node , int32 leng
extern void extern void
gbt_var_bin_union ( Datum * u , GBT_VARKEY * e , const gbtree_vinfo * tinfo ) gbt_var_bin_union(Datum *u, GBT_VARKEY * e, const gbtree_vinfo * tinfo)
{ {
GBT_VARKEY * nk = NULL; GBT_VARKEY *nk = NULL;
GBT_VARKEY * tmp = NULL; GBT_VARKEY *tmp = NULL;
GBT_VARKEY_R nr ; GBT_VARKEY_R nr;
GBT_VARKEY_R eo = gbt_var_key_readable ( e ); GBT_VARKEY_R eo = gbt_var_key_readable(e);
if ( eo.lower == eo.upper ) /* leaf */ if (eo.lower == eo.upper) /* leaf */
{ {
tmp = gbt_var_leaf2node ( e , tinfo ); tmp = gbt_var_leaf2node(e, tinfo);
if ( tmp != e ) if (tmp != e)
eo = gbt_var_key_readable ( tmp ); eo = gbt_var_key_readable(tmp);
} }
if ( DatumGetPointer(*u)) if (DatumGetPointer(*u))
{ {
GBT_VARKEY_R ro = gbt_var_key_readable ( ( GBT_VARKEY *) DatumGetPointer (*u) ); GBT_VARKEY_R ro = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(*u));
if ( (*tinfo->f_cmp) ( (bytea*)ro.lower, (bytea*)eo.lower ) > 0 ) { if ((*tinfo->f_cmp) ((bytea *) ro.lower, (bytea *) eo.lower) > 0)
{
nr.lower = eo.lower; nr.lower = eo.lower;
nr.upper = ro.upper; nr.upper = ro.upper;
nk = gbt_var_key_copy ( &nr, TRUE ); nk = gbt_var_key_copy(&nr, TRUE);
} }
if ( (*tinfo->f_cmp) ( (bytea*)ro.upper, (bytea*)eo.upper ) < 0 ) { if ((*tinfo->f_cmp) ((bytea *) ro.upper, (bytea *) eo.upper) < 0)
{
nr.upper = eo.upper; nr.upper = eo.upper;
nr.lower = ro.lower; nr.lower = ro.lower;
nk = gbt_var_key_copy ( &nr, TRUE ); nk = gbt_var_key_copy(&nr, TRUE);
} }
if ( nk ) if (nk)
{ {
pfree( DatumGetPointer (*u) ); pfree(DatumGetPointer(*u));
*u = PointerGetDatum(nk); *u = PointerGetDatum(nk);
} }
@ -217,40 +231,41 @@ gbt_var_bin_union ( Datum * u , GBT_VARKEY * e , const gbtree_vinfo * tinfo )
{ {
nr.lower = eo.lower; nr.lower = eo.lower;
nr.upper = eo.upper; nr.upper = eo.upper;
*u = PointerGetDatum( gbt_var_key_copy ( &nr, TRUE ) ); *u = PointerGetDatum(gbt_var_key_copy(&nr, TRUE));
} }
if ( tmp && tmp != e ) if (tmp && tmp != e)
pfree ( tmp ); pfree(tmp);
} }
extern GISTENTRY * extern GISTENTRY *
gbt_var_compress ( GISTENTRY *entry , const gbtree_vinfo * tinfo ) gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo * tinfo)
{ {
GISTENTRY * retval; GISTENTRY *retval;
if (entry->leafkey) if (entry->leafkey)
{ {
GBT_VARKEY * r = NULL; GBT_VARKEY *r = NULL;
bytea * tstd = ( bytea * ) DatumGetPointer ( entry->key ); /* toasted */ bytea *tstd = (bytea *) DatumGetPointer(entry->key); /* toasted */
bytea * leaf = ( bytea * ) DatumGetPointer ( PG_DETOAST_DATUM ( entry->key ) ); /* untoasted */ bytea *leaf = (bytea *) DatumGetPointer(PG_DETOAST_DATUM(entry->key)); /* untoasted */
GBT_VARKEY_R u ; GBT_VARKEY_R u;
u.lower = u.upper = leaf; u.lower = u.upper = leaf;
r = gbt_var_key_copy ( &u , FALSE ); r = gbt_var_key_copy(&u, FALSE);
if ( tstd != leaf ){ if (tstd != leaf)
pfree(leaf); pfree(leaf);
}
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, VARSIZE(r), TRUE); entry->offset, VARSIZE(r), TRUE);
} else { }
else
{
retval = entry; retval = entry;
@ -262,13 +277,13 @@ gbt_var_compress ( GISTENTRY *entry , const gbtree_vinfo * tinfo )
extern GBT_VARKEY * extern GBT_VARKEY *
gbt_var_union ( const GistEntryVector * entryvec , int32 * size , const gbtree_vinfo * tinfo ) gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo * tinfo)
{ {
int i = 0, int i = 0,
numranges = entryvec->n; numranges = entryvec->n;
GBT_VARKEY *cur, GBT_VARKEY *cur,
*tst=NULL; *tst = NULL;
Datum out; Datum out;
GBT_VARKEY_R rk; GBT_VARKEY_R rk;
@ -276,55 +291,65 @@ gbt_var_union ( const GistEntryVector * entryvec , int32 * size , const gbtree_
tst = (GBT_VARKEY *) DatumGetPointer((entryvec->vector[0].key)); tst = (GBT_VARKEY *) DatumGetPointer((entryvec->vector[0].key));
cur = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[0].key))); cur = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[0].key)));
rk = gbt_var_key_readable ( cur ); rk = gbt_var_key_readable(cur);
out = PointerGetDatum ( gbt_var_key_copy( &rk, TRUE ) ); out = PointerGetDatum(gbt_var_key_copy(&rk, TRUE));
if ( tst != cur ) pfree ( cur ); if (tst != cur)
pfree(cur);
for (i = 1; i < numranges; i++) for (i = 1; i < numranges; i++)
{ {
tst = (GBT_VARKEY *) DatumGetPointer((entryvec->vector[i].key)); tst = (GBT_VARKEY *) DatumGetPointer((entryvec->vector[i].key));
cur = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[i].key))); cur = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[i].key)));
gbt_var_bin_union ( &out , cur , tinfo ); gbt_var_bin_union(&out, cur, tinfo);
if ( tst != cur ) pfree ( cur ); if (tst != cur)
pfree(cur);
} }
/* Truncate (=compress) key */ /* Truncate (=compress) key */
if ( tinfo->trnc ) if (tinfo->trnc)
{ {
int32 plen ; int32 plen;
GBT_VARKEY *trc = NULL; GBT_VARKEY *trc = NULL;
plen = gbt_var_node_cp_len ( (GBT_VARKEY *) DatumGetPointer(out) , tinfo ); plen = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(out), tinfo);
trc = gbt_var_node_truncate ( (GBT_VARKEY *) DatumGetPointer(out) , plen+1 , tinfo ) ; trc = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(out), plen + 1, tinfo);
pfree ( DatumGetPointer(out) ); pfree(DatumGetPointer(out));
out = PointerGetDatum ( trc ); out = PointerGetDatum(trc);
} }
return ( (GBT_VARKEY *) DatumGetPointer ( out ) ); return ((GBT_VARKEY *) DatumGetPointer(out));
} }
extern bool gbt_var_same ( bool * result, const Datum d1 , const Datum d2 , const gbtree_vinfo * tinfo ){ extern bool
gbt_var_same(bool *result, const Datum d1, const Datum d2, const gbtree_vinfo * tinfo)
{
GBT_VARKEY *tst1 = (GBT_VARKEY *) DatumGetPointer(d1); GBT_VARKEY *tst1 = (GBT_VARKEY *) DatumGetPointer(d1);
GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer( PG_DETOAST_DATUM(d1) ); GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(d1));
GBT_VARKEY *tst2 = (GBT_VARKEY *) DatumGetPointer(d2); GBT_VARKEY *tst2 = (GBT_VARKEY *) DatumGetPointer(d2);
GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer( PG_DETOAST_DATUM(d2) ); GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(d2));
GBT_VARKEY_R r1, r2; GBT_VARKEY_R r1,
r1 = gbt_var_key_readable ( t1 ); r2;
r2 = gbt_var_key_readable ( t2 );
if (t1 && t2){ r1 = gbt_var_key_readable(t1);
*result = ( ( (*tinfo->f_cmp ) ( (bytea*)r1.lower, (bytea*)r2.lower) == 0 r2 = gbt_var_key_readable(t2);
&& (*tinfo->f_cmp) ( (bytea*)r1.upper, (bytea*)r2.upper) == 0 ) ? TRUE : FALSE );
} else if (t1 && t2)
{
*result = (((*tinfo->f_cmp) ((bytea *) r1.lower, (bytea *) r2.lower) == 0
&& (*tinfo->f_cmp) ((bytea *) r1.upper, (bytea *) r2.upper) == 0) ? TRUE : FALSE);
}
else
*result = (t1 == NULL && t2 == NULL) ? TRUE : FALSE; *result = (t1 == NULL && t2 == NULL) ? TRUE : FALSE;
if ( tst1 != t1 ) pfree (t1); if (tst1 != t1)
if ( tst2 != t2 ) pfree (t2); pfree(t1);
if (tst2 != t2)
pfree(t2);
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
@ -332,86 +357,91 @@ extern bool gbt_var_same ( bool * result, const Datum d1 , const Datum d2 , cons
extern float * extern float *
gbt_var_penalty ( float * res , const GISTENTRY * o , const GISTENTRY * n, const gbtree_vinfo * tinfo ) gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree_vinfo * tinfo)
{ {
GBT_VARKEY *orgt = (GBT_VARKEY *) DatumGetPointer(o->key); GBT_VARKEY *orgt = (GBT_VARKEY *) DatumGetPointer(o->key);
GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer( PG_DETOAST_DATUM(o->key) ); GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(o->key));
GBT_VARKEY *newt = (GBT_VARKEY *) DatumGetPointer(n->key); GBT_VARKEY *newt = (GBT_VARKEY *) DatumGetPointer(n->key);
GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer( PG_DETOAST_DATUM(n->key) ); GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(PG_DETOAST_DATUM(n->key));
GBT_VARKEY_R ok , nk; GBT_VARKEY_R ok,
nk;
GBT_VARKEY *tmp = NULL; GBT_VARKEY *tmp = NULL;
int32 s = (tinfo->str)?(1):(0); int32 s = (tinfo->str) ? (1) : (0);
*res = 0.0; *res = 0.0;
nk = gbt_var_key_readable ( newe ); nk = gbt_var_key_readable(newe);
if ( nk.lower == nk.upper ) /* leaf */ if (nk.lower == nk.upper) /* leaf */
{ {
tmp = gbt_var_leaf2node ( newe , tinfo ); tmp = gbt_var_leaf2node(newe, tinfo);
if ( tmp != newe ) if (tmp != newe)
nk = gbt_var_key_readable ( tmp ); nk = gbt_var_key_readable(tmp);
} }
ok = gbt_var_key_readable ( orge ); ok = gbt_var_key_readable(orge);
if ( ( VARSIZE(ok.lower) - VARHDRSZ ) == s && ( VARSIZE(ok.upper) - VARHDRSZ ) == s ) if ((VARSIZE(ok.lower) - VARHDRSZ) == s && (VARSIZE(ok.upper) - VARHDRSZ) == s)
{
*res = 0.0; *res = 0.0;
} else else if (!(
if ( ! (
( (
( (*tinfo->f_cmp) (nk.lower, ok.lower)>=0 || gbt_bytea_pf_match(ok.lower, nk.lower, tinfo ) ) && ((*tinfo->f_cmp) (nk.lower, ok.lower) >= 0 || gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
( (*tinfo->f_cmp) (nk.upper, ok.upper)<=0 || gbt_bytea_pf_match(ok.upper, nk.upper, tinfo ) ) ((*tinfo->f_cmp) (nk.upper, ok.upper) <= 0 || gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))
) )
) ) ))
{ {
Datum d = PointerGetDatum (0); Datum d = PointerGetDatum(0);
double dres = 0.0; double dres = 0.0;
int32 ol, ul; int32 ol,
ul;
gbt_var_bin_union ( &d , orge , tinfo ); gbt_var_bin_union(&d, orge, tinfo);
ol = gbt_var_node_cp_len ( ( GBT_VARKEY *) DatumGetPointer(d), tinfo ); ol = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
gbt_var_bin_union ( &d , newe , tinfo ); gbt_var_bin_union(&d, newe, tinfo);
ul = gbt_var_node_cp_len ( ( GBT_VARKEY *) DatumGetPointer(d), tinfo ); ul = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
if ( ul < ol ) { if (ul < ol)
dres = ( ol-ul ) ; /* lost of common prefix len */ {
} else { dres = (ol - ul); /* lost of common prefix len */
GBT_VARKEY_R uk = gbt_var_key_readable ( ( GBT_VARKEY *) DatumGetPointer(d) ); }
if ( tinfo->str ) else
{
GBT_VARKEY_R uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(d));
if (tinfo->str)
{
dres = (VARDATA(ok.lower)[ul] - VARDATA(uk.lower)[ul]) +
(VARDATA(uk.upper)[ul] - VARDATA(ok.upper)[ul]);
}
else
{ {
dres = ( VARDATA(ok.lower)[ul]-VARDATA(uk.lower)[ul] ) +
( VARDATA(uk.upper)[ul]-VARDATA(ok.upper)[ul] );
} else {
char tmp[4]; char tmp[4];
tmp[0] = ( ( VARSIZE(ok.lower) - VARHDRSZ ) == ul )?(CHAR_MIN):(VARDATA(ok.lower)[ul]);
tmp[1] = ( ( VARSIZE(uk.lower) - VARHDRSZ ) == ul )?(CHAR_MIN):(VARDATA(uk.lower)[ul]); tmp[0] = ((VARSIZE(ok.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.lower)[ul]);
tmp[2] = ( ( VARSIZE(ok.upper) - VARHDRSZ ) == ul )?(CHAR_MIN):(VARDATA(ok.upper)[ul]); tmp[1] = ((VARSIZE(uk.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.lower)[ul]);
tmp[3] = ( ( VARSIZE(uk.upper) - VARHDRSZ ) == ul )?(CHAR_MIN):(VARDATA(uk.upper)[ul]); tmp[2] = ((VARSIZE(ok.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.upper)[ul]);
dres = ( tmp[0] - tmp[1] ) + tmp[3] = ((VARSIZE(uk.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.upper)[ul]);
( tmp[3] - tmp[2] ); dres = (tmp[0] - tmp[1]) +
(tmp[3] - tmp[2]);
} }
dres /= 256.0; dres /= 256.0;
} }
pfree ( DatumGetPointer(d) ); pfree(DatumGetPointer(d));
*res += FLT_MIN ; *res += FLT_MIN;
*res += (float) ( dres / ( (double) ( ol +1 ) ) ); *res += (float) (dres / ((double) (ol + 1)));
*res *= ( FLT_MAX / ( o->rel->rd_att->natts + 1 ) ); *res *= (FLT_MAX / (o->rel->rd_att->natts + 1));
} }
if ( tmp && tmp != newe ) if (tmp && tmp != newe)
pfree (tmp); pfree(tmp);
if ( newe != newt ){ if (newe != newt)
pfree ( newe ); pfree(newe);
}
if ( orge != orgt ){ if (orge != orgt)
pfree ( orge ); pfree(orge);
} return res;
return res ;
} }
@ -419,32 +449,32 @@ gbt_var_penalty ( float * res , const GISTENTRY * o , const GISTENTRY * n, const
/* /*
* Fortunately, this sort comparsion routine needn't be reentrant... * Fortunately, this sort comparsion routine needn't be reentrant...
*/ */
static const gbtree_vinfo * gbt_vsrt_cmp_tinfo; static const gbtree_vinfo *gbt_vsrt_cmp_tinfo;
static int static int
gbt_vsrt_cmp(const void *a, const void *b) gbt_vsrt_cmp(const void *a, const void *b)
{ {
GBT_VARKEY_R ar = gbt_var_key_readable ( ((const Vsrt *) a)->t ); GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
GBT_VARKEY_R br = gbt_var_key_readable ( ((const Vsrt *) b)->t ); GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
return (*gbt_vsrt_cmp_tinfo->f_cmp) ( ar.lower, br.lower ); return (*gbt_vsrt_cmp_tinfo->f_cmp) (ar.lower, br.lower);
} }
extern GIST_SPLITVEC * extern GIST_SPLITVEC *
gbt_var_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_vinfo * tinfo ) gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_vinfo * tinfo)
{ {
OffsetNumber i, OffsetNumber i,
maxoff = entryvec->n - 1; maxoff = entryvec->n - 1;
Vsrt *arr; Vsrt *arr;
int pfrcntr = 0 , int pfrcntr = 0,
svcntr = 0 , svcntr = 0,
nbytes ; nbytes;
char * tst , char *tst,
* cur ; *cur;
char **pfr = NULL ; char **pfr = NULL;
GBT_VARKEY **sv = NULL; GBT_VARKEY **sv = NULL;
arr = (Vsrt *) palloc((maxoff+1) * sizeof(Vsrt)); arr = (Vsrt *) palloc((maxoff + 1) * sizeof(Vsrt));
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);
@ -453,37 +483,39 @@ gbt_var_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtr
v->spl_nleft = 0; v->spl_nleft = 0;
v->spl_nright = 0; v->spl_nright = 0;
pfr = palloc ( sizeof ( GBT_VARKEY* ) * (maxoff+1) ); pfr = palloc(sizeof(GBT_VARKEY *) * (maxoff + 1));
sv = palloc ( sizeof ( bytea * ) * (maxoff+1) ); sv = palloc(sizeof(bytea *) * (maxoff + 1));
/* Sort entries */ /* Sort entries */
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{ {
GBT_VARKEY_R ro; GBT_VARKEY_R ro;
tst = (char *) DatumGetPointer((entryvec->vector[i].key)); tst = (char *) DatumGetPointer((entryvec->vector[i].key));
cur = (char *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[i].key))); cur = (char *) DatumGetPointer(PG_DETOAST_DATUM((entryvec->vector[i].key)));
if ( tst != cur ){ if (tst != cur)
pfr[pfrcntr] = cur ; {
pfr[pfrcntr] = cur;
pfrcntr++; pfrcntr++;
} }
ro = gbt_var_key_readable( ( GBT_VARKEY *) cur ); ro = gbt_var_key_readable((GBT_VARKEY *) cur);
if ( ro.lower == ro.upper ) /* leaf */ if (ro.lower == ro.upper) /* leaf */
{ {
sv[svcntr] = gbt_var_leaf2node ( ( GBT_VARKEY *) cur , tinfo ); sv[svcntr] = gbt_var_leaf2node((GBT_VARKEY *) cur, tinfo);
arr[i].t = sv[svcntr]; arr[i].t = sv[svcntr];
if ( sv[svcntr] != ( GBT_VARKEY *) cur ) if (sv[svcntr] != (GBT_VARKEY *) cur)
svcntr++; svcntr++;
} else {
arr[i].t = ( GBT_VARKEY *) cur;
} }
else
arr[i].t = (GBT_VARKEY *) cur;
arr[i].i = i; arr[i].i = i;
} }
/* sort */ /* sort */
gbt_vsrt_cmp_tinfo = tinfo; gbt_vsrt_cmp_tinfo = tinfo;
qsort((void*) &arr[FirstOffsetNumber], qsort((void *) &arr[FirstOffsetNumber],
maxoff-FirstOffsetNumber+1, maxoff - FirstOffsetNumber + 1,
sizeof(Vsrt), sizeof(Vsrt),
gbt_vsrt_cmp); gbt_vsrt_cmp);
@ -506,44 +538,38 @@ gbt_var_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtr
} }
/* Free detoasted keys */ /* Free detoasted keys */
for ( i=0 ; i<pfrcntr; i++ ){ for (i = 0; i < pfrcntr; i++)
pfree( pfr[i] ); pfree(pfr[i]);
}
/* Free strxfrm'ed leafs */ /* Free strxfrm'ed leafs */
for ( i=0 ; i<svcntr; i++ ){ for (i = 0; i < svcntr; i++)
pfree( sv[i] ); pfree(sv[i]);
}
if ( pfr ) if (pfr)
{ pfree(pfr);
pfree (pfr);
}
if ( sv ) if (sv)
{ pfree(sv);
pfree (sv);
}
/* Truncate (=compress) key */ /* Truncate (=compress) key */
if ( tinfo->trnc ) if (tinfo->trnc)
{ {
int32 ll = gbt_var_node_cp_len ( (GBT_VARKEY *) DatumGetPointer(v->spl_ldatum) , tinfo ); int32 ll = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), tinfo);
int32 lr = gbt_var_node_cp_len ( (GBT_VARKEY *) DatumGetPointer(v->spl_rdatum) , tinfo ); int32 lr = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), tinfo);
GBT_VARKEY * dl ; GBT_VARKEY *dl;
GBT_VARKEY * dr ; GBT_VARKEY *dr;
ll = Max (ll,lr); ll = Max(ll, lr);
ll++; ll++;
dl = gbt_var_node_truncate ( (GBT_VARKEY *) DatumGetPointer(v->spl_ldatum) , ll, tinfo ) ; dl = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), ll, tinfo);
dr = gbt_var_node_truncate ( (GBT_VARKEY *) DatumGetPointer(v->spl_rdatum) , ll, tinfo ) ; dr = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), ll, tinfo);
pfree( DatumGetPointer(v->spl_ldatum) ); pfree(DatumGetPointer(v->spl_ldatum));
pfree( DatumGetPointer(v->spl_rdatum) ); pfree(DatumGetPointer(v->spl_rdatum));
v->spl_ldatum = PointerGetDatum ( dl ); v->spl_ldatum = PointerGetDatum(dl);
v->spl_rdatum = PointerGetDatum ( dr ); v->spl_rdatum = PointerGetDatum(dr);
} }
@ -559,8 +585,8 @@ gbt_var_picksplit( const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtr
extern bool extern bool
gbt_var_consistent( gbt_var_consistent(
GBT_VARKEY_R * key, GBT_VARKEY_R * key,
const void * query, const void *query,
const StrategyNumber * strategy, const StrategyNumber *strategy,
bool is_leaf, bool is_leaf,
const gbtree_vinfo * tinfo const gbtree_vinfo * tinfo
) )
@ -570,43 +596,43 @@ gbt_var_consistent(
switch (*strategy) switch (*strategy)
{ {
case BTLessEqualStrategyNumber: case BTLessEqualStrategyNumber:
if ( is_leaf ) if (is_leaf)
retval = (*tinfo->f_ge)(query, (void*) key->lower); retval = (*tinfo->f_ge) (query, (void *) key->lower);
else else
retval = (*tinfo->f_cmp)((bytea*) query, key->lower) >= 0 retval = (*tinfo->f_cmp) ((bytea *) query, key->lower) >= 0
|| gbt_var_node_pf_match( key ,query, tinfo ); || gbt_var_node_pf_match(key, query, tinfo);
break; break;
case BTLessStrategyNumber: case BTLessStrategyNumber:
if ( is_leaf ) if (is_leaf)
retval = (*tinfo->f_gt)(query, (void*) key->lower); retval = (*tinfo->f_gt) (query, (void *) key->lower);
else else
retval = (*tinfo->f_cmp)((bytea*)query, key->lower) >= 0 retval = (*tinfo->f_cmp) ((bytea *) query, key->lower) >= 0
|| gbt_var_node_pf_match( key, query , tinfo ); || gbt_var_node_pf_match(key, query, tinfo);
break; break;
case BTEqualStrategyNumber: case BTEqualStrategyNumber:
if ( is_leaf ) if (is_leaf)
retval = (*tinfo->f_eq)(query, (void*) key->lower); retval = (*tinfo->f_eq) (query, (void *) key->lower);
else else
retval = ( retval = (
( (
(*tinfo->f_cmp) (key->lower,(bytea*) query)<=0 && (*tinfo->f_cmp) (key->lower, (bytea *) query) <= 0 &&
(*tinfo->f_cmp) ((bytea*)query, (void*) key->upper)<=0 (*tinfo->f_cmp) ((bytea *) query, (void *) key->upper) <= 0
) || gbt_var_node_pf_match( key, query, tinfo ) ) || gbt_var_node_pf_match(key, query, tinfo)
); );
break; break;
case BTGreaterStrategyNumber: case BTGreaterStrategyNumber:
if ( is_leaf ) if (is_leaf)
retval = (*tinfo->f_lt)(query, (void*) key->upper); retval = (*tinfo->f_lt) (query, (void *) key->upper);
else else
retval = (*tinfo->f_cmp)((bytea*)query, key->upper)<=0 retval = (*tinfo->f_cmp) ((bytea *) query, key->upper) <= 0
|| gbt_var_node_pf_match( key, query, tinfo ); || gbt_var_node_pf_match(key, query, tinfo);
break; break;
case BTGreaterEqualStrategyNumber: case BTGreaterEqualStrategyNumber:
if ( is_leaf ) if (is_leaf)
retval = (*tinfo->f_le)(query, (void*) key->upper); retval = (*tinfo->f_le) (query, (void *) key->upper);
else else
retval = (*tinfo->f_cmp)((bytea*) query, key->upper)<=0 retval = (*tinfo->f_cmp) ((bytea *) query, key->upper) <= 0
|| gbt_var_node_pf_match( key, query, tinfo ); || gbt_var_node_pf_match(key, query, tinfo);
break; break;
default: default:
retval = FALSE; retval = FALSE;

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,
*upper;
} GBT_VARKEY_R; } 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
@ -25,43 +26,43 @@ 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

@ -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.
@ -53,7 +53,7 @@ int storePending(char *cpTableName, HeapTuple tBeforeTuple,
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,7 +84,7 @@ 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,14 +106,14 @@ 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;
} }
@ -154,7 +153,7 @@ 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")));
} }
@ -173,7 +172,7 @@ 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);
@ -203,7 +202,7 @@ storePending(char *cpTableName, HeapTuple tBeforeTuple,
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];
@ -218,7 +217,7 @@ 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")));
@ -252,7 +251,7 @@ 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
@ -262,7 +261,7 @@ storePending(char *cpTableName, HeapTuple 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,7 +311,7 @@ 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};
@ -383,7 +382,7 @@ storeData(char *cpTableName, HeapTuple tTupleData,
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);
@ -486,7 +485,7 @@ 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.
@ -590,17 +589,18 @@ 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);
@ -611,27 +611,27 @@ Datum setval(PG_FUNCTION_ARGS)
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);
@ -648,11 +648,11 @@ 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];
@ -670,47 +670,47 @@ nextval(PG_FUNCTION_ARGS)
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);
@ -721,52 +721,50 @@ nextval(PG_FUNCTION_ARGS)
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);
@ -775,4 +773,3 @@ saveSequenceUpdate(const text * sequenceName,
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,6 +50,7 @@ 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;
@ -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);
@ -104,7 +106,7 @@ 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,

View File

@ -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);
} }
@ -240,7 +248,6 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
(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 */
@ -254,7 +261,8 @@ typedef struct
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
@ -269,7 +277,7 @@ NewMetaString(char *init_str)
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;
@ -278,7 +286,7 @@ NewMetaString(char *init_str)
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;
@ -304,7 +312,7 @@ 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;
} }
@ -315,9 +323,7 @@ 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);
}
} }
@ -330,8 +336,8 @@ IsVowel(metastring * s, int pos)
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;
@ -378,7 +384,7 @@ 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;
@ -414,9 +420,7 @@ MetaphAdd(metastring * s, char *new_str)
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;
@ -574,8 +578,10 @@ 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' */ /*
* e.g., 'wachtler', 'wechsler', but not 'tichner'
*/
&& StringAt(original, (current + 2), 1, "L", "R", && StringAt(original, (current + 2), 1, "L", "R",
"N", "M", "B", "H", "F", "V", "W", "N", "M", "B", "H", "F", "V", "W",
" ", ""))) " ", "")))
@ -696,8 +702,7 @@ 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 else if (StringAt(original, (current + 1), 1, "C", "K", "Q", "")
if (StringAt(original, (current + 1), 1, "C", "K", "Q", "")
&& !StringAt(original, (current + 1), 2, && !StringAt(original, (current + 1), 2,
"CE", "CI", "")) "CE", "CI", ""))
current += 2; current += 2;
@ -780,8 +785,11 @@ 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,
@ -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",
@ -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;
@ -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", ""))
@ -1428,8 +1440,11 @@ 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);
*/
} }
@ -1451,13 +1466,14 @@ DoubleMetaphone(char *str, char **codes)
/* 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

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

@ -39,7 +39,8 @@ Datum _intbig_out(PG_FUNCTION_ARGS);
Datum Datum
_intbig_in(PG_FUNCTION_ARGS) { _intbig_in(PG_FUNCTION_ARGS)
{
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("_intbig_in() not implemented"))); errmsg("_intbig_in() not implemented")));
@ -47,7 +48,8 @@ _intbig_in(PG_FUNCTION_ARGS) {
} }
Datum Datum
_intbig_out(PG_FUNCTION_ARGS) { _intbig_out(PG_FUNCTION_ARGS)
{
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("_intbig_out() not implemented"))); errmsg("_intbig_out() not implemented")));
@ -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,7 +93,8 @@ _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);
@ -100,13 +105,16 @@ 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; int4 i;
BITVECP sa = GETSIGN(a), BITVECP sa = GETSIGN(a),
sb = GETSIGN(b); sb = GETSIGN(b);
*result = true; *result = true;
LOOPBYTE( LOOPBYTE(
if (sa[i] != sb[i]) { if (sa[i] != sb[i])
{
*result = false; *result = false;
break; break;
} }
@ -120,22 +128,24 @@ 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++;
} }
@ -144,11 +154,13 @@ g_intbig_compress(PG_FUNCTION_ARGS)
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));
@ -159,8 +171,8 @@ g_intbig_compress(PG_FUNCTION_ARGS)
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));
@ -176,8 +188,11 @@ 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);
@ -186,27 +201,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;
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
@ -230,17 +250,21 @@ unionkey(BITVECP sbase, GISTTYPE * add)
} }
Datum Datum
g_intbig_union(PG_FUNCTION_ARGS) { g_intbig_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;
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,31 +281,35 @@ 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); 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,
@ -290,7 +318,8 @@ g_intbig_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;
@ -310,11 +339,14 @@ g_intbig_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;
@ -368,14 +400,14 @@ g_intbig_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=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++)
{ {
@ -393,16 +425,19 @@ g_intbig_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 (ISALLTRUE(datum_l) || ISALLTRUE(_j) ) { if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
{
if (!ISALLTRUE(datum_l)) if (!ISALLTRUE(datum_l))
MemSet((void *) union_l, 0xff, sizeof(BITVEC)); MemSet((void *) union_l, 0xff, sizeof(BITVEC));
} else { }
ptr=GETSIGN(_j); else
{
ptr = GETSIGN(_j);
LOOPBYTE( LOOPBYTE(
union_l[i] |= ptr[i]; union_l[i] |= ptr[i];
); );
@ -412,11 +447,14 @@ g_intbig_picksplit(PG_FUNCTION_ARGS) {
} }
else else
{ {
if (ISALLTRUE(datum_r) || ISALLTRUE(_j) ) { if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
{
if (!ISALLTRUE(datum_r)) if (!ISALLTRUE(datum_r))
MemSet((void *) union_r, 0xff, sizeof(BITVEC)); MemSet((void *) union_r, 0xff, sizeof(BITVEC));
} else { }
ptr=GETSIGN(_j); else
{
ptr = GETSIGN(_j);
LOOPBYTE( LOOPBYTE(
union_r[i] |= ptr[i]; union_r[i] |= ptr[i];
); );
@ -443,10 +481,11 @@ 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,
num = ARRNELEMS(query);
int4 *ptr = ARRPTR(query);
BITVEC qp; BITVEC qp;
BITVECP dq, de; BITVECP dq,
memset(qp,0,sizeof(BITVEC)); 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; {
retval = false;
break; 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,
num = ARRNELEMS(query);
int4 *ptr = ARRPTR(query);
BITVEC qp; BITVEC qp;
BITVECP dq, de; BITVECP dq,
memset(qp,0,sizeof(BITVEC)); 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; {
retval = false;
break; 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

@ -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;
@ -175,7 +175,8 @@ _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(a))
{
if (LTG_ISALLTRUE(b)) if (LTG_ISALLTRUE(b))
return 0; return 0;
else else
return ASIGLENBIT-sizebitvec(LTG_SIGN(b)); return ASIGLENBIT - sizebitvec(LTG_SIGN(b));
} else if (LTG_ISALLTRUE(b)) }
return ASIGLENBIT-sizebitvec(LTG_SIGN(a)); 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);
} }
@ -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,16 +384,19 @@ _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];
); );
@ -393,11 +406,14 @@ _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];
); );
@ -498,7 +514,8 @@ 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); lquery *query = (lquery *) ARR_DATA_PTR(_query);
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query)); int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
@ -507,11 +524,12 @@ _arrq_cons(ltree_gist *key, ArrayType *_query) {
(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) ) {
if (gist_qe(key, query))
return true; return true;
num--; num--;
query = (lquery*)NEXTVAL(query); query = (lquery *) NEXTVAL(query);
} }
return false; return false;
} }

View File

@ -602,7 +602,8 @@ 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); lquery *query = (lquery *) ARR_DATA_PTR(_query);
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query)); int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
@ -611,8 +612,9 @@ arrq_cons(ltree_gist *key, ArrayType *_query) {
(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) ) {
if (gist_qe(key, query) && gist_between(key, query))
return true; return true;
num--; num--;
query = NEXTVAL(query); query = NEXTVAL(query);

View File

@ -230,9 +230,9 @@ 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)
{ {
@ -501,9 +501,9 @@ 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)
{ {
@ -539,8 +539,8 @@ update_db_list(Dllist *db_list)
* 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++)
{ {
@ -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;
@ -1114,19 +1112,21 @@ main(int argc, char *argv[])
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);
@ -1158,8 +1158,9 @@ 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. */
} }
/* /*

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

@ -31,7 +31,8 @@ typedef char trgm[3];
} while(0); } while(0);
typedef struct { typedef struct
{
int4 len; int4 len;
uint8 flag; uint8 flag;
char data[1]; char data[1];
@ -82,7 +83,7 @@ typedef char *BITVECP;
#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);
} }
} }
@ -138,35 +139,43 @@ 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 */
float4 tmpsml = cnt_sml(key, qtrg);
if ( GIST_LEAF( (GISTENTRY *) PG_GETARG_POINTER(0) ) ) { /* all leafs contains orig trgm */
float4 tmpsml = cnt_sml(key,qtrg);
/* strange bug at freebsd 5.2.1 and gcc 3.3.3 */ /* strange bug at freebsd 5.2.1 and gcc 3.3.3 */
res = ( *(int*)&tmpsml==*(int*)&trgm_limit || tmpsml > trgm_limit ) ? true : false; res = (*(int *) &tmpsml == *(int *) &trgm_limit || tmpsml > trgm_limit) ? true : false;
} else if ( ISALLTRUE(key) ) { /* non-leaf contains signature */ }
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);
} }
} }
@ -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;
@ -305,27 +315,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;
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
@ -340,17 +355,19 @@ gtrgm_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);
} }
@ -390,16 +407,19 @@ 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
@ -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,40 +477,48 @@ 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]));
@ -495,58 +526,73 @@ gtrgm_picksplit(PG_FUNCTION_ARGS)
} }
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));
} }
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
if ( ISALLTRUE(datum_r) && cache[j].allistrue )
size_beta=0;
else else
size_beta = SIGLENBIT-sizebitvec( size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));
( cache[j].allistrue ) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
);
} 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 (ISALLTRUE(datum_r) || cache[j].allistrue)
if (ISALLTRUE(datum_l) || cache[j].allistrue) { {
if (! ISALLTRUE(datum_l) ) if (ISALLTRUE(datum_r) && cache[j].allistrue)
size_beta = 0;
else
size_beta = SIGLENBIT - sizebitvec(
(cache[j].allistrue) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
);
}
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 (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];
); );

View File

@ -8,10 +8,12 @@ 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); float4 nlimit = PG_GETARG_FLOAT4(0);
if ( nlimit < 0 || nlimit > 1.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);
} }
@ -19,7 +21,8 @@ set_limit(PG_FUNCTION_ARGS) {
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);
} }
@ -27,112 +30,135 @@ show_limit(PG_FUNCTION_ARGS) {
#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;
char *buf,
*sptr,
*bufptr;
trgm *tptr; trgm *tptr;
int state=WORDWAIT; int state = WORDWAIT;
int wl,len; 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 { }
else
{
*bufptr = *sptr; /* put in buffer */ *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);
@ -158,7 +185,8 @@ 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); text *in = PG_GETARG_TEXT_P(0);
TRGM *trg; TRGM *trg;
Datum *d; Datum *d;
@ -166,14 +194,16 @@ show_trgm(PG_FUNCTION_ARGS) {
trgm *ptr; 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++;
} }
@ -187,23 +217,27 @@ show_trgm(PG_FUNCTION_ARGS) {
); );
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,9 +262,9 @@ 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
} }
@ -235,21 +272,23 @@ cnt_sml(TRGM *trg1, TRGM *trg2) {
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 *in1 = PG_GETARG_TEXT_P(0);
text *in2 = PG_GETARG_TEXT_P(1); text *in2 = PG_GETARG_TEXT_P(1);
TRGM *trg1, *trg2; TRGM *trg1,
*trg2;
float4 res; 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);
} }
@ -257,13 +296,13 @@ similarity(PG_FUNCTION_ARGS) {
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( {
float4 res = DatumGetFloat4(DirectFunctionCall2(
similarity, similarity,
PG_GETARG_DATUM(0), PG_GETARG_DATUM(0),
PG_GETARG_DATUM(1) 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

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

View File

@ -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,7 +323,7 @@ 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 = ',';
} }
} }

View File

@ -329,7 +329,8 @@ 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;

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

@ -121,8 +121,9 @@ text_cmp(text *a, text *b)
} }
char* char *
get_namespace(Oid funcoid) { get_namespace(Oid funcoid)
{
HeapTuple tuple; HeapTuple tuple;
Form_pg_proc proc; Form_pg_proc proc;
Form_pg_namespace nsp; Form_pg_namespace nsp;
@ -132,7 +133,7 @@ get_namespace(Oid funcoid) {
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);
@ -140,14 +141,15 @@ get_namespace(Oid funcoid) {
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; HeapTuple tuple;
Form_pg_proc proc; Form_pg_proc proc;
Oid nspoid; Oid nspoid;
@ -155,10 +157,9 @@ get_oidnamespace(Oid funcoid) {
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,8 +21,9 @@ 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 */
char *get_namespace(Oid funcoid);
Oid get_oidnamespace(Oid funcoid); Oid get_oidnamespace(Oid funcoid);
#define SET_FUNCOID() do { \ #define SET_FUNCOID() do { \

View File

@ -35,9 +35,9 @@ init_dict(Oid id, DictInfo * dict)
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");
@ -143,7 +143,8 @@ name2id_dict(text *name)
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,6 +246,7 @@ 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(
@ -279,6 +281,7 @@ 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,
@ -294,6 +297,7 @@ 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,

View File

@ -329,7 +329,8 @@ 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;
@ -425,27 +426,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;
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,16 +518,19 @@ 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
@ -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,40 +589,48 @@ 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]));
@ -616,58 +638,73 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
} }
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));
} }
if (ISALLTRUE(datum_r) || cache[j].allistrue) {
if ( ISALLTRUE(datum_r) && cache[j].allistrue )
size_beta=0;
else else
size_beta = SIGLENBIT-sizebitvec( size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));
( cache[j].allistrue ) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
);
} 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 (ISALLTRUE(datum_r) || cache[j].allistrue)
if (ISALLTRUE(datum_l) || cache[j].allistrue) { {
if (! ISALLTRUE(datum_l) ) if (ISALLTRUE(datum_r) && cache[j].allistrue)
size_beta = 0;
else
size_beta = SIGLENBIT - sizebitvec(
(cache[j].allistrue) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
);
}
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 (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];
); );

View File

@ -7,11 +7,12 @@
#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;
@ -23,84 +24,110 @@ RS_isRegis(const char *str) {
#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; RegisNode *ptr;
ptr = (RegisNode*)malloc(RNHDRSZ+len+1);
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 i,
len = strlen(str);
int state = RS_IN_WAIT; int state = RS_IN_WAIT;
RegisNode *ptr=NULL; 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,7 +3,8 @@
#include "postgres.h" #include "postgres.h"
typedef struct RegisNode { typedef struct RegisNode
{
uint32 uint32
type:2, type:2,
len:16, len:16,
@ -17,7 +18,8 @@ typedef struct RegisNode {
#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,
@ -27,8 +29,10 @@ typedef struct Regis {
int RS_isRegis(const char *str); int RS_isRegis(const char *str);
int RS_compile(Regis *r, int issuffix, const char *str); int RS_compile(Regis * r, int issuffix, const char *str);
void RS_free(Regis *r); 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,7 +10,8 @@
struct SPNode; struct SPNode;
typedef struct { typedef struct
{
uint32 uint32
val:8, val:8,
isword:1, isword:1,
@ -19,7 +20,8 @@ typedef struct {
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;
@ -30,9 +32,11 @@ 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 affix;
int len; int len;
} d; } d;
@ -53,7 +57,8 @@ typedef struct aff_struct
char mask[32]; char mask[32];
char find[16]; char find[16];
char repl[16]; char repl[16];
union { union
{
regex_t regex; regex_t regex;
Regis regis; Regis regis;
} reg; } reg;
@ -67,7 +72,8 @@ typedef struct aff_struct
struct AffixNode; struct AffixNode;
typedef struct { typedef struct
{
uint32 uint32
val:8, val:8,
naff:24; naff:24;
@ -75,7 +81,8 @@ typedef struct {
struct AffixNode *node; struct AffixNode *node;
} AffixNodeData; } AffixNodeData;
typedef struct AffixNode { typedef struct AffixNode
{
uint32 isvoid:1, uint32 isvoid:1,
length:31; length:31;
AffixNodeData data[1]; AffixNodeData data[1];
@ -83,7 +90,8 @@ typedef struct AffixNode {
#define ANHRDSZ (sizeof(uint32)) #define ANHRDSZ (sizeof(uint32))
typedef struct { typedef struct
{
char *affix; char *affix;
int len; int len;
} CMPDAffix; } CMPDAffix;

View File

@ -484,6 +484,7 @@ 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)
{ {
@ -865,6 +866,7 @@ 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);
@ -888,6 +890,7 @@ 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)),

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,7 +38,7 @@ 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;
@ -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");
@ -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++;
@ -559,7 +560,7 @@ get_currcfg(void)
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);
@ -605,6 +606,7 @@ 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,
@ -632,4 +634,3 @@ reset_tsearch(PG_FUNCTION_ARGS)
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 len = POSDATALEN(txt, wptr);
int num=0; int num = 0;
WordEntryPos *ptr = POSDATAPTR(txt, wptr); 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;
@ -525,9 +540,10 @@ ts_stat(PG_FUNCTION_ARGS)
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,6 +404,7 @@ 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;
@ -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]++;
} }
@ -753,6 +755,7 @@ 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,
@ -769,6 +772,7 @@ 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,
@ -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;
@ -992,44 +1000,50 @@ 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

@ -31,17 +31,18 @@ init_prs(Oid id, WParserInfo * prs)
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,7 +141,8 @@ 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],
*nsp;
void *plan; void *plan;
arg[0] = TEXTOID; arg[0] = TEXTOID;
@ -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,6 +244,7 @@ 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())
{ {
@ -263,6 +266,7 @@ 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())
{ {
@ -287,6 +291,7 @@ 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())
{ {
@ -321,6 +326,7 @@ 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,
@ -444,6 +450,7 @@ parse(PG_FUNCTION_ARGS)
{ {
FuncCallContext *funcctx; FuncCallContext *funcctx;
Datum result; Datum result;
SET_FUNCOID(); SET_FUNCOID();
if (SRF_IS_FIRSTCALL()) if (SRF_IS_FIRSTCALL())
{ {
@ -468,6 +475,7 @@ 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())
{ {
@ -495,6 +503,7 @@ 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())
{ {
@ -566,6 +575,7 @@ 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,

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,12 +225,12 @@ 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);
@ -239,7 +240,8 @@ 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),
@ -255,7 +257,8 @@ prsd_headline(PG_FUNCTION_ARGS)
} }
} }
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,7 +280,7 @@ 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++)
@ -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,7 +312,7 @@ 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
@ -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;
} }

View File

@ -22,7 +22,7 @@ static void *pgxml_palloc(size_t size);
static void *pgxml_repalloc(void *ptr, size_t size); static void *pgxml_repalloc(void *ptr, size_t size);
static void pgxml_pfree(void *ptr); static void pgxml_pfree(void *ptr);
static char *pgxml_pstrdup(const char *string); static char *pgxml_pstrdup(const char *string);
static void pgxml_errorHandler (void * ctxt, const char *msg, ...); static void pgxml_errorHandler(void *ctxt, const char *msg,...);
void elog_error(int level, char *explain, int force); void elog_error(int level, char *explain, int force);
void pgxml_parser_init(void); void pgxml_parser_init(void);
@ -31,12 +31,12 @@ static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
xmlChar * toptagname, xmlChar * septagname, xmlChar * toptagname, xmlChar * septagname,
xmlChar * plainsep); xmlChar * plainsep);
text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag, text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar * toptag,
xmlChar *septag, xmlChar *plainsep); xmlChar * septag, xmlChar * plainsep);
xmlChar *pgxml_texttoxmlchar(text *textstring); xmlChar *pgxml_texttoxmlchar(text *textstring);
static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar* xpath); static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar * xpath);
Datum xml_valid(PG_FUNCTION_ARGS); Datum xml_valid(PG_FUNCTION_ARGS);
@ -93,7 +93,7 @@ pgxml_pstrdup(const char *string)
*/ */
static void static void
pgxml_errorHandler (void * ctxt, const char *msg, ...) pgxml_errorHandler(void *ctxt, const char *msg,...)
{ {
va_list args; va_list args;
@ -102,35 +102,35 @@ pgxml_errorHandler (void * ctxt, const char *msg, ...)
va_end(args); va_end(args);
/* Now copy the argument across */ /* Now copy the argument across */
if (pgxml_errorMsg == NULL) if (pgxml_errorMsg == NULL)
{
pgxml_errorMsg = pstrdup(errbuf); pgxml_errorMsg = pstrdup(errbuf);
} else
else
{ {
int32 xsize = strlen(pgxml_errorMsg); int32 xsize = strlen(pgxml_errorMsg);
pgxml_errorMsg = repalloc(pgxml_errorMsg, pgxml_errorMsg = repalloc(pgxml_errorMsg,
(size_t) (xsize + strlen(errbuf) + 1)); (size_t) (xsize + strlen(errbuf) + 1));
strncpy(&pgxml_errorMsg[xsize-1],errbuf,strlen(errbuf)); strncpy(&pgxml_errorMsg[xsize - 1], errbuf, strlen(errbuf));
pgxml_errorMsg[xsize+strlen(errbuf)-1]='\0'; pgxml_errorMsg[xsize + strlen(errbuf) - 1] = '\0';
} }
memset(errbuf,0,ERRBUF_SIZE); memset(errbuf, 0, ERRBUF_SIZE);
} }
/* This function reports the current message at the level specified */ /* This function reports the current message at the level specified */
void elog_error(int level, char *explain, int force) void
elog_error(int level, char *explain, int force)
{ {
if (force || (pgxml_errorMsg != NULL)) if (force || (pgxml_errorMsg != NULL))
{ {
if (pgxml_errorMsg == NULL) if (pgxml_errorMsg == NULL)
{ {
ereport(level,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), ereport(level, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
errmsg(explain))); errmsg(explain)));
} }
else else
{ {
ereport(level,(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), ereport(level, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
errmsg("%s:%s",explain,pgxml_errorMsg))); errmsg("%s:%s", explain, pgxml_errorMsg)));
pfree(pgxml_errorMsg); pfree(pgxml_errorMsg);
} }
} }
@ -155,7 +155,7 @@ pgxml_parser_init()
pgxml_errorMsg = NULL; pgxml_errorMsg = NULL;
errbuf = palloc(200); errbuf = palloc(200);
memset(errbuf,0,200); memset(errbuf, 0, 200);
} }
@ -201,8 +201,11 @@ pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
*/ */
/* each representation is surrounded by <tagname> ... </tagname> */ /* each representation is surrounded by <tagname> ... </tagname> */
/* plainsep is an ordinary (not tag) seperator - if used, then
* nodes are cast to string as output method */ /*
* plainsep is an ordinary (not tag) seperator - if used, then nodes
* are cast to string as output method
*/
xmlBufferPtr buf; xmlBufferPtr buf;
@ -222,15 +225,17 @@ pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
for (i = 0; i < nodeset->nodeNr; i++) for (i = 0; i < nodeset->nodeNr; i++)
{ {
if (plainsep != NULL) { if (plainsep != NULL)
{
xmlBufferWriteCHAR(buf, xmlBufferWriteCHAR(buf,
xmlXPathCastNodeToString(nodeset->nodeTab[i])); xmlXPathCastNodeToString(nodeset->nodeTab[i]));
/* If this isn't the last entry, write the plain sep. */ /* If this isn't the last entry, write the plain sep. */
if (i < (nodeset->nodeNr)-1) { if (i < (nodeset->nodeNr) - 1)
xmlBufferWriteChar(buf, plainsep); xmlBufferWriteChar(buf, plainsep);
} }
} else { else
{
if ((septagname != NULL) && (xmlStrlen(septagname) > 0)) if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
@ -294,7 +299,9 @@ PG_FUNCTION_INFO_V1(xpath_nodeset);
Datum Datum
xpath_nodeset(PG_FUNCTION_ARGS) xpath_nodeset(PG_FUNCTION_ARGS)
{ {
xmlChar *xpath, *toptag, *septag; xmlChar *xpath,
*toptag,
*septag;
int32 pathsize; int32 pathsize;
text text
*xpathsupp, *xpathsupp,
@ -311,28 +318,27 @@ xpath_nodeset(PG_FUNCTION_ARGS)
xpath = pgxml_texttoxmlchar(xpathsupp); xpath = pgxml_texttoxmlchar(xpathsupp);
xpres = pgxml_result_to_text( xpres = pgxml_result_to_text(
pgxml_xpath(PG_GETARG_TEXT_P(0),xpath), pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
toptag,septag,NULL); toptag, septag, NULL);
/* xmlCleanupParser(); done by result_to_text routine */ /* xmlCleanupParser(); done by result_to_text routine */
pfree((void *) xpath); pfree((void *) xpath);
if (xpres == NULL) if (xpres == NULL)
{
PG_RETURN_NULL(); PG_RETURN_NULL();
}
PG_RETURN_TEXT_P(xpres); PG_RETURN_TEXT_P(xpres);
} }
// The following function is almost identical, but returns the elements in /* The following function is almost identical, but returns the elements in */
// a list. /* a list. */
PG_FUNCTION_INFO_V1(xpath_list); PG_FUNCTION_INFO_V1(xpath_list);
Datum Datum
xpath_list(PG_FUNCTION_ARGS) xpath_list(PG_FUNCTION_ARGS)
{ {
xmlChar *xpath, *plainsep; xmlChar *xpath,
*plainsep;
int32 pathsize; int32 pathsize;
text text
*xpathsupp, *xpathsupp,
@ -348,16 +354,14 @@ xpath_list(PG_FUNCTION_ARGS)
xpath = pgxml_texttoxmlchar(xpathsupp); xpath = pgxml_texttoxmlchar(xpathsupp);
xpres = pgxml_result_to_text( xpres = pgxml_result_to_text(
pgxml_xpath(PG_GETARG_TEXT_P(0),xpath), pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
NULL,NULL,plainsep); NULL, NULL, plainsep);
/* xmlCleanupParser(); done by result_to_text routine */ /* xmlCleanupParser(); done by result_to_text routine */
pfree((void *) xpath); pfree((void *) xpath);
if (xpres == NULL) if (xpres == NULL)
{
PG_RETURN_NULL(); PG_RETURN_NULL();
}
PG_RETURN_TEXT_P(xpres); PG_RETURN_TEXT_P(xpres);
} }
@ -378,27 +382,27 @@ xpath_string(PG_FUNCTION_ARGS)
pathsize = VARSIZE(xpathsupp) - VARHDRSZ; pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
/* We encapsulate the supplied path with "string()" /*
* = 8 chars + 1 for NUL at end */ * We encapsulate the supplied path with "string()" = 8 chars + 1 for
* NUL at end
*/
/* We could try casting to string using the libxml function? */ /* We could try casting to string using the libxml function? */
xpath =(xmlChar *) palloc(pathsize + 9); xpath = (xmlChar *) palloc(pathsize + 9);
memcpy((char *) (xpath+7), VARDATA(xpathsupp), pathsize); memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize);
strncpy((char *) xpath, "string(",7); strncpy((char *) xpath, "string(", 7);
xpath[pathsize+7] = ')'; xpath[pathsize + 7] = ')';
xpath[pathsize+8] = '\0'; xpath[pathsize + 8] = '\0';
xpres = pgxml_result_to_text( xpres = pgxml_result_to_text(
pgxml_xpath(PG_GETARG_TEXT_P(0),xpath), pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
NULL,NULL,NULL); NULL, NULL, NULL);
xmlCleanupParser(); xmlCleanupParser();
pfree((void *) xpath); pfree((void *) xpath);
if (xpres == NULL) if (xpres == NULL)
{
PG_RETURN_NULL(); PG_RETURN_NULL();
}
PG_RETURN_TEXT_P(xpres); PG_RETURN_TEXT_P(xpres);
} }
@ -424,7 +428,7 @@ xpath_number(PG_FUNCTION_ARGS)
xpath = pgxml_texttoxmlchar(xpathsupp); xpath = pgxml_texttoxmlchar(xpathsupp);
res = pgxml_xpath(PG_GETARG_TEXT_P(0),xpath); res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
pfree((void *) xpath); pfree((void *) xpath);
if (res == NULL) if (res == NULL)
@ -436,9 +440,7 @@ xpath_number(PG_FUNCTION_ARGS)
fRes = xmlXPathCastToNumber(res); fRes = xmlXPathCastToNumber(res);
xmlCleanupParser(); xmlCleanupParser();
if (xmlXPathIsNaN(fRes)) if (xmlXPathIsNaN(fRes))
{
PG_RETURN_NULL(); PG_RETURN_NULL();
}
PG_RETURN_FLOAT4(fRes); PG_RETURN_FLOAT4(fRes);
@ -466,7 +468,7 @@ xpath_bool(PG_FUNCTION_ARGS)
xpath = pgxml_texttoxmlchar(xpathsupp); xpath = pgxml_texttoxmlchar(xpathsupp);
res = pgxml_xpath(PG_GETARG_TEXT_P(0),xpath); res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
pfree((void *) xpath); pfree((void *) xpath);
if (res == NULL) if (res == NULL)
@ -486,8 +488,8 @@ xpath_bool(PG_FUNCTION_ARGS)
/* Core function to evaluate XPath query */ /* Core function to evaluate XPath query */
xmlXPathObjectPtr xmlXPathObjectPtr
pgxml_xpath(text *document, xmlChar *xpath) pgxml_xpath(text *document, xmlChar * xpath)
{ {
xmlDocPtr doctree; xmlDocPtr doctree;
xmlXPathContextPtr ctxt; xmlXPathContextPtr ctxt;
@ -518,7 +520,7 @@ xmlXPathObjectPtr
{ {
xmlCleanupParser(); xmlCleanupParser();
xmlFreeDoc(doctree); xmlFreeDoc(doctree);
elog_error(ERROR,"XPath Syntax Error",1); elog_error(ERROR, "XPath Syntax Error", 1);
return NULL; return NULL;
} }
@ -530,29 +532,28 @@ xmlXPathObjectPtr
if (res == NULL) if (res == NULL)
{ {
xmlXPathFreeContext(ctxt); xmlXPathFreeContext(ctxt);
// xmlCleanupParser(); /* xmlCleanupParser(); */
xmlFreeDoc(doctree); xmlFreeDoc(doctree);
return NULL; return NULL;
} }
/* xmlFreeDoc(doctree); */ /* xmlFreeDoc(doctree); */
return res; return res;
} }
text text
*pgxml_result_to_text(xmlXPathObjectPtr res, *
xmlChar *toptag, pgxml_result_to_text(xmlXPathObjectPtr res,
xmlChar *septag, xmlChar * toptag,
xmlChar *plainsep) xmlChar * septag,
xmlChar * plainsep)
{ {
xmlChar *xpresstr; xmlChar *xpresstr;
int32 ressize; int32 ressize;
text *xpres; text *xpres;
if (res == NULL) if (res == NULL)
{
return NULL; return NULL;
}
switch (res->type) switch (res->type)
{ {
case XPATH_NODESET: case XPATH_NODESET:
@ -583,7 +584,7 @@ text
xmlFree(xpresstr); xmlFree(xpresstr);
elog_error(ERROR,"XPath error",0); elog_error(ERROR, "XPath error", 0);
return xpres; return xpres;
@ -595,7 +596,8 @@ text
PG_FUNCTION_INFO_V1(xpath_table); PG_FUNCTION_INFO_V1(xpath_table);
Datum xpath_table(PG_FUNCTION_ARGS) Datum
xpath_table(PG_FUNCTION_ARGS)
{ {
/* SPI (input tuple) support */ /* SPI (input tuple) support */
SPITupleTable *tuptable; SPITupleTable *tuptable;
@ -622,21 +624,23 @@ Datum xpath_table(PG_FUNCTION_ARGS)
char **values; char **values;
xmlChar **xpaths; xmlChar **xpaths;
xmlChar *pos; xmlChar *pos;
xmlChar *pathsep= "|"; xmlChar *pathsep = "|";
int numpaths; int numpaths;
int ret; int ret;
int proc; int proc;
int i; int i;
int j; int j;
int rownr; /* For issuing multiple rows from one original document */ int rownr; /* For issuing multiple rows from one
* original document */
int had_values; /* To determine end of nodeset results */ int had_values; /* To determine end of nodeset results */
StringInfo querysql; StringInfo querysql;
/* We only have a valid tuple description in table function mode */ /* We only have a valid tuple description in table function mode */
if (rsinfo->expectedDesc == NULL) { if (rsinfo->expectedDesc == NULL)
ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR), {
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("xpath_table must be called as a table function"))); errmsg("xpath_table must be called as a table function")));
} }
@ -657,17 +661,19 @@ Datum xpath_table(PG_FUNCTION_ARGS)
/* get the requested return tuple description */ /* get the requested return tuple description */
ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
/* At the moment we assume that the returned attributes make sense /*
* for the XPath specififed (i.e. we trust the caller). * At the moment we assume that the returned attributes make sense for
* It's not fatal if they get it wrong - the input function for the * the XPath specififed (i.e. we trust the caller). It's not fatal if
* column type will raise an error if the path result can't be converted * they get it wrong - the input function for the column type will
* into the correct binary representation. * raise an error if the path result can't be converted into the
* correct binary representation.
*/ */
attinmeta = TupleDescGetAttInMetadata(ret_tupdesc); attinmeta = TupleDescGetAttInMetadata(ret_tupdesc);
/* We want to materialise because it means that we don't have to /*
* carry libxml2 parser state between invocations of this function * We want to materialise because it means that we don't have to carry
* libxml2 parser state between invocations of this function
*/ */
/* check to see if caller supports us returning a tuplestore */ /* check to see if caller supports us returning a tuplestore */
@ -676,7 +682,7 @@ Datum xpath_table(PG_FUNCTION_ARGS)
errmsg("xpath_table requires Materialize mode, but it is not " errmsg("xpath_table requires Materialize mode, but it is not "
"allowed in this context"))); "allowed in this context")));
// Set return mode and allocate value space. /* Set return mode and allocate value space. */
rsinfo->returnMode = SFRM_Materialize; rsinfo->returnMode = SFRM_Materialize;
rsinfo->setDesc = ret_tupdesc; rsinfo->setDesc = ret_tupdesc;
@ -688,17 +694,19 @@ Datum xpath_table(PG_FUNCTION_ARGS)
/* Note that we stop splitting once we've done all needed for tupdesc */ /* Note that we stop splitting once we've done all needed for tupdesc */
numpaths=0; numpaths = 0;
pos = xpathset; pos = xpathset;
do { do
{
xpaths[numpaths] = pos; xpaths[numpaths] = pos;
pos = strstr(pos,pathsep); pos = strstr(pos, pathsep);
if (pos != NULL) { if (pos != NULL)
{
*pos = '\0'; *pos = '\0';
pos++; pos++;
} }
numpaths++; numpaths++;
} while ((pos != NULL) && (numpaths < (ret_tupdesc->natts - 1) )); } while ((pos != NULL) && (numpaths < (ret_tupdesc->natts - 1)));
/* Now build query */ /* Now build query */
@ -713,15 +721,13 @@ Datum xpath_table(PG_FUNCTION_ARGS)
); );
if ((ret = SPI_connect()) < 0) { if ((ret = SPI_connect()) < 0)
elog(ERROR, "xpath_table: SPI_connect returned %d", ret); elog(ERROR, "xpath_table: SPI_connect returned %d", ret);
}
if ((ret = SPI_exec(querysql->data,0)) != SPI_OK_SELECT) { if ((ret = SPI_exec(querysql->data, 0)) != SPI_OK_SELECT)
elog(ERROR,"xpath_table: SPI execution failed for query %s",querysql->data); elog(ERROR, "xpath_table: SPI execution failed for query %s", querysql->data);
}
proc= SPI_processed; proc = SPI_processed;
/* elog(DEBUG1,"xpath_table: SPI returned %d rows",proc); */ /* elog(DEBUG1,"xpath_table: SPI returned %d rows",proc); */
tuptable = SPI_tuptable; tuptable = SPI_tuptable;
spi_tupdesc = tuptable->tupdesc; spi_tupdesc = tuptable->tupdesc;
@ -735,10 +741,11 @@ Datum xpath_table(PG_FUNCTION_ARGS)
* e.g. 3 columns. * e.g. 3 columns.
*/ */
if (spi_tupdesc->natts != 2) { if (spi_tupdesc->natts != 2)
ereport(ERROR,(errcode(ERRCODE_INVALID_PARAMETER_VALUE), {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Expression returning multiple columns is not valid in parameter list"), errmsg("Expression returning multiple columns is not valid in parameter list"),
errdetail("Expected two columns in SPI result, got %d",spi_tupdesc->natts))); errdetail("Expected two columns in SPI result, got %d", spi_tupdesc->natts)));
} }
/* Setup the parser. Beware that this must happen in the same context as the /* Setup the parser. Beware that this must happen in the same context as the
@ -748,7 +755,8 @@ Datum xpath_table(PG_FUNCTION_ARGS)
pgxml_parser_init(); pgxml_parser_init();
/* For each row i.e. document returned from SPI */ /* For each row i.e. document returned from SPI */
for (i=0; i < proc; i++) { for (i = 0; i < proc; i++)
{
char *pkey; char *pkey;
char *xmldoc; char *xmldoc;
@ -763,27 +771,28 @@ Datum xpath_table(PG_FUNCTION_ARGS)
/* Extract the row data as C Strings */ /* Extract the row data as C Strings */
spi_tuple = tuptable->vals[i]; spi_tuple = tuptable->vals[i];
pkey = SPI_getvalue(spi_tuple, spi_tupdesc,1); pkey = SPI_getvalue(spi_tuple, spi_tupdesc, 1);
xmldoc = SPI_getvalue(spi_tuple, spi_tupdesc,2); xmldoc = SPI_getvalue(spi_tuple, spi_tupdesc, 2);
/* Clear the values array, so that not-well-formed documents /*
* Clear the values array, so that not-well-formed documents
* return NULL in all columns. * return NULL in all columns.
*/ */
/* Note that this also means that spare columns will be NULL. */ /* Note that this also means that spare columns will be NULL. */
for (j=0; j < ret_tupdesc->natts; j++) { for (j = 0; j < ret_tupdesc->natts; j++)
values[j]= NULL; values[j] = NULL;
}
/* Insert primary key */ /* Insert primary key */
values[0]=pkey; values[0] = pkey;
/* Parse the document */ /* Parse the document */
doctree = xmlParseMemory(xmldoc, strlen(xmldoc)); doctree = xmlParseMemory(xmldoc, strlen(xmldoc));
if (doctree == NULL) if (doctree == NULL)
{ /* not well-formed, so output all-NULL tuple */ { /* not well-formed, so output all-NULL
* tuple */
ret_tuple = BuildTupleFromCStrings(attinmeta, values); ret_tuple = BuildTupleFromCStrings(attinmeta, values);
oldcontext = MemoryContextSwitchTo(per_query_ctx); oldcontext = MemoryContextSwitchTo(per_query_ctx);
@ -794,12 +803,14 @@ Datum xpath_table(PG_FUNCTION_ARGS)
else else
{ {
/* New loop here - we have to deal with nodeset results */ /* New loop here - we have to deal with nodeset results */
rownr=0; rownr = 0;
do { do
{
/* Now evaluate the set of xpaths. */ /* Now evaluate the set of xpaths. */
had_values=0; had_values = 0;
for (j=0; j < numpaths; j++) { for (j = 0; j < numpaths; j++)
{
ctxt = xmlXPathNewContext(doctree); ctxt = xmlXPathNewContext(doctree);
ctxt->node = xmlDocGetRootElement(doctree); ctxt->node = xmlDocGetRootElement(doctree);
@ -812,7 +823,7 @@ Datum xpath_table(PG_FUNCTION_ARGS)
xmlCleanupParser(); xmlCleanupParser();
xmlFreeDoc(doctree); xmlFreeDoc(doctree);
elog_error(ERROR,"XPath Syntax Error",1); elog_error(ERROR, "XPath Syntax Error", 1);
PG_RETURN_NULL(); /* Keep compiler happy */ PG_RETURN_NULL(); /* Keep compiler happy */
} }
@ -827,13 +838,14 @@ Datum xpath_table(PG_FUNCTION_ARGS)
{ {
case XPATH_NODESET: case XPATH_NODESET:
/* We see if this nodeset has enough nodes */ /* We see if this nodeset has enough nodes */
if ((res->nodesetval != NULL) && (rownr < res->nodesetval->nodeNr)) { if ((res->nodesetval != NULL) && (rownr < res->nodesetval->nodeNr))
{
resstr = resstr =
xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]); xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
had_values=1; had_values = 1;
} else {
resstr = NULL;
} }
else
resstr = NULL;
break; break;
@ -847,13 +859,17 @@ Datum xpath_table(PG_FUNCTION_ARGS)
} }
// Insert this into the appropriate column in the result tuple. /*
values[j+1] = resstr; * Insert this into the appropriate column in the
* result tuple.
*/
values[j + 1] = resstr;
} }
xmlXPathFreeContext(ctxt); xmlXPathFreeContext(ctxt);
} }
// Now add the tuple to the output, if there is one. /* Now add the tuple to the output, if there is one. */
if (had_values) { if (had_values)
{
ret_tuple = BuildTupleFromCStrings(attinmeta, values); ret_tuple = BuildTupleFromCStrings(attinmeta, values);
oldcontext = MemoryContextSwitchTo(per_query_ctx); oldcontext = MemoryContextSwitchTo(per_query_ctx);
tuplestore_puttuple(tupstore, ret_tuple); tuplestore_puttuple(tupstore, ret_tuple);
@ -879,7 +895,7 @@ Datum xpath_table(PG_FUNCTION_ARGS)
SPI_finish(); SPI_finish();
rsinfo->setResult=tupstore; rsinfo->setResult = tupstore;
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual

View File

@ -39,7 +39,9 @@ Datum xslt_process(PG_FUNCTION_ARGS);
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 */
@ -60,12 +62,11 @@ Datum xslt_process(PG_FUNCTION_ARGS) {
if (fcinfo->nargs == 3) if (fcinfo->nargs == 3)
{ {
paramstr = PG_GETARG_TEXT_P(2); paramstr = PG_GETARG_TEXT_P(2);
parse_params(params,paramstr); parse_params(params, paramstr);
} }
else /* No parameters */ else
{ /* No parameters */
params[0] = NULL; params[0] = NULL;
}
/* Setup parser */ /* Setup parser */
pgxml_parser_init(); pgxml_parser_init();
@ -73,18 +74,14 @@ Datum xslt_process(PG_FUNCTION_ARGS) {
/* Check to see if document is a file or a literal */ /* Check to see if document is a file or a literal */
if (VARDATA(doct)[0] == '<') if (VARDATA(doct)[0] == '<')
{ doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct)-VARHDRSZ);
}
else else
{
doctree = xmlParseFile(GET_STR(doct)); doctree = xmlParseFile(GET_STR(doct));
}
if (doctree == NULL) if (doctree == NULL)
{ {
xmlCleanupParser(); xmlCleanupParser();
elog_error(ERROR,"Error parsing XML document",0); elog_error(ERROR, "Error parsing XML document", 0);
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
@ -93,21 +90,19 @@ Datum xslt_process(PG_FUNCTION_ARGS) {
if (VARDATA(ssheet)[0] == '<') if (VARDATA(ssheet)[0] == '<')
{ {
ssdoc = xmlParseMemory((char *) VARDATA(ssheet), ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
VARSIZE(ssheet)-VARHDRSZ); VARSIZE(ssheet) - VARHDRSZ);
if (ssdoc == NULL) if (ssdoc == NULL)
{ {
xmlFreeDoc(doctree); xmlFreeDoc(doctree);
xmlCleanupParser(); xmlCleanupParser();
elog_error(ERROR,"Error parsing stylesheet as XML document",0); elog_error(ERROR, "Error parsing stylesheet as XML document", 0);
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
stylesheet = xsltParseStylesheetDoc(ssdoc); stylesheet = xsltParseStylesheetDoc(ssdoc);
} }
else else
{
stylesheet = xsltParseStylesheetFile(GET_STR(ssheet)); stylesheet = xsltParseStylesheetFile(GET_STR(ssheet));
}
if (stylesheet == NULL) if (stylesheet == NULL)
@ -115,7 +110,7 @@ Datum xslt_process(PG_FUNCTION_ARGS) {
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();
} }
@ -129,56 +124,58 @@ Datum xslt_process(PG_FUNCTION_ARGS) {
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 = '\0';
pos++; pos++;
} else { }
params[i]=NULL; else
{
params[i] = NULL;
break; break;
} }
/* Value */ /* Value */
i++; i++;
params[i]=pos; params[i] = pos;
pos = strstr(pos,itsep); pos = strstr(pos, itsep);
if (pos != NULL) { if (pos != NULL)
{
*pos = '\0'; *pos = '\0';
pos++; pos++;
} else {
break;
} }
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,13 +468,15 @@ 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:
{ {
@ -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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

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

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

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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -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)
{ {

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,10 +115,8 @@ 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);
@ -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;
} }

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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -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);
@ -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.
@ -44,8 +44,8 @@ bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
/* 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);
} }
@ -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)
{ {
@ -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
@ -239,10 +239,10 @@ _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);
@ -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 */
@ -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()
*/ */
@ -399,11 +401,11 @@ _hash_expandtable(Relation rel, Buffer metabuf)
* 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,7 +137,8 @@ _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,
@ -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);
@ -1146,7 +1146,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
/* /*
* 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))
@ -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:
@ -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))

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;

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,23 +200,23 @@ _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 */

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

@ -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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -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,
@ -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.
@ -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);
@ -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);
@ -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);
@ -805,15 +806,15 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
* 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);
@ -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],
@ -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;
} }
@ -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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

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,
@ -285,9 +285,9 @@ ReleaseResources_rtree(void)
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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -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);
@ -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

@ -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)
@ -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
@ -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
@ -91,14 +92,14 @@ GetNewTransactionId(bool isSubXact)
* *
* 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,11 +113,9 @@ GetNewTransactionId(bool isSubXact)
MyProc->subxids.nxids++; MyProc->subxids.nxids++;
} }
else else
{
MyProc->subxids.overflowed = true; MyProc->subxids.overflowed = true;
} }
} }
}
LWLockRelease(XidGenLock); LWLockRelease(XidGenLock);

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.182 2004/08/29 04:12:23 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.183 2004/08/29 05:06:40 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -96,7 +96,8 @@ typedef struct TransactionStateData
TransState state; /* low-level state */ TransState state; /* low-level state */
TBlockState blockState; /* high-level state */ TBlockState blockState; /* high-level state */
int nestingLevel; /* nest depth */ int nestingLevel; /* nest depth */
MemoryContext curTransactionContext; /* my xact-lifetime context */ MemoryContext curTransactionContext; /* my xact-lifetime
* context */
ResourceOwner curTransactionOwner; /* my query resources */ ResourceOwner curTransactionOwner; /* my query resources */
List *childXids; /* subcommitted child XIDs */ List *childXids; /* subcommitted child XIDs */
AclId currentUser; /* subxact start current_user */ AclId currentUser; /* subxact start current_user */
@ -362,11 +363,11 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
} }
/* /*
* We will return true for the Xid of the current subtransaction, * We will return true for the Xid of the current subtransaction, any
* any of its subcommitted children, any of its parents, or any of * of its subcommitted children, any of its parents, or any of their
* their previously subcommitted children. However, a transaction * previously subcommitted children. However, a transaction being
* being aborted is no longer "current", even though it may still * aborted is no longer "current", even though it may still have an
* have an entry on the state stack. * entry on the state stack.
*/ */
for (s = CurrentTransactionState; s != NULL; s = s->parent) for (s = CurrentTransactionState; s != NULL; s = s->parent)
{ {
@ -502,9 +503,10 @@ AtSubStart_Memory(void)
Assert(CurTransactionContext != NULL); Assert(CurTransactionContext != NULL);
/* /*
* Create a CurTransactionContext, which will be used to hold data that * Create a CurTransactionContext, which will be used to hold data
* survives subtransaction commit but disappears on subtransaction abort. * that survives subtransaction commit but disappears on
* We make it a child of the immediate parent's CurTransactionContext. * subtransaction abort. We make it a child of the immediate parent's
* CurTransactionContext.
*/ */
CurTransactionContext = AllocSetContextCreate(CurTransactionContext, CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
"CurTransactionContext", "CurTransactionContext",
@ -528,8 +530,8 @@ AtSubStart_ResourceOwner(void)
Assert(s->parent != NULL); Assert(s->parent != NULL);
/* /*
* Create a resource owner for the subtransaction. We make it a * Create a resource owner for the subtransaction. We make it a child
* child of the immediate parent's resource owner. * of the immediate parent's resource owner.
*/ */
s->curTransactionOwner = s->curTransactionOwner =
ResourceOwnerCreate(s->parent->curTransactionOwner, ResourceOwnerCreate(s->parent->curTransactionOwner,
@ -560,10 +562,11 @@ RecordTransactionCommit(void)
nchildren = xactGetCommittedChildren(&children); nchildren = xactGetCommittedChildren(&children);
/* /*
* If we made neither any XLOG entries nor any temp-rel updates, * If we made neither any XLOG entries nor any temp-rel updates, and
* and have no files to be deleted, we can omit recording the transaction * have no files to be deleted, we can omit recording the transaction
* commit at all. (This test includes the effects of subtransactions, * commit at all. (This test includes the effects of subtransactions,
* so the presence of committed subxacts need not alone force a write.) * so the presence of committed subxacts need not alone force a
* write.)
*/ */
if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0) if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
{ {
@ -577,17 +580,18 @@ RecordTransactionCommit(void)
START_CRIT_SECTION(); START_CRIT_SECTION();
/* /*
* If our transaction made any transaction-controlled XLOG entries, * If our transaction made any transaction-controlled XLOG
* we need to lock out checkpoint start between writing our XLOG * entries, we need to lock out checkpoint start between writing
* record and updating pg_clog. Otherwise it is possible for the * our XLOG record and updating pg_clog. Otherwise it is possible
* checkpoint to set REDO after the XLOG record but fail to flush the * for the checkpoint to set REDO after the XLOG record but fail
* pg_clog update to disk, leading to loss of the transaction commit * to flush the pg_clog update to disk, leading to loss of the
* if we crash a little later. Slightly klugy fix for problem * transaction commit if we crash a little later. Slightly klugy
* discovered 2004-08-10. * fix for problem discovered 2004-08-10.
* *
* (If it made no transaction-controlled XLOG entries, its XID * (If it made no transaction-controlled XLOG entries, its XID
* appears nowhere in permanent storage, so no one else will ever care * appears nowhere in permanent storage, so no one else will ever
* if it committed; so it doesn't matter if we lose the commit flag.) * care if it committed; so it doesn't matter if we lose the
* commit flag.)
* *
* Note we only need a shared lock. * Note we only need a shared lock.
*/ */
@ -798,16 +802,16 @@ static void
RecordSubTransactionCommit(void) RecordSubTransactionCommit(void)
{ {
/* /*
* We do not log the subcommit in XLOG; it doesn't matter until * We do not log the subcommit in XLOG; it doesn't matter until the
* the top-level transaction commits. * top-level transaction commits.
* *
* We must mark the subtransaction subcommitted in clog if its XID * We must mark the subtransaction subcommitted in clog if its XID
* appears either in permanent rels or in local temporary rels. We * appears either in permanent rels or in local temporary rels. We
* test this by seeing if we made transaction-controlled entries * test this by seeing if we made transaction-controlled entries *OR*
* *OR* local-rel tuple updates. (The test here actually covers the * local-rel tuple updates. (The test here actually covers the entire
* entire transaction tree so far, so it may mark subtransactions that * transaction tree so far, so it may mark subtransactions that don't
* don't really need it, but it's probably not worth being tenser. * really need it, but it's probably not worth being tenser. Note that
* Note that if a prior subtransaction dirtied these variables, then * if a prior subtransaction dirtied these variables, then
* RecordTransactionCommit will have to do the full pushup anyway...) * RecordTransactionCommit will have to do the full pushup anyway...)
*/ */
if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate) if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
@ -846,9 +850,9 @@ RecordTransactionAbort(void)
/* /*
* If we made neither any transaction-controlled XLOG entries nor any * If we made neither any transaction-controlled XLOG entries nor any
* temp-rel updates, and are not going to delete any files, we can omit * temp-rel updates, and are not going to delete any files, we can
* recording the transaction abort at all. No one will ever care that * omit recording the transaction abort at all. No one will ever care
* it aborted. (These tests cover our whole transaction tree.) * that it aborted. (These tests cover our whole transaction tree.)
*/ */
if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0) if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
{ {
@ -867,13 +871,13 @@ RecordTransactionAbort(void)
* We only need to log the abort in XLOG if the transaction made * We only need to log the abort in XLOG if the transaction made
* any transaction-controlled XLOG entries or will delete files. * any transaction-controlled XLOG entries or will delete files.
* (If it made no transaction-controlled XLOG entries, its XID * (If it made no transaction-controlled XLOG entries, its XID
* appears nowhere in permanent storage, so no one else will ever care * appears nowhere in permanent storage, so no one else will ever
* if it committed.) * care if it committed.)
* *
* We do not flush XLOG to disk unless deleting files, since the * We do not flush XLOG to disk unless deleting files, since the
* default assumption after a crash would be that we aborted, anyway. * default assumption after a crash would be that we aborted,
* For the same reason, we don't need to worry about interlocking * anyway. For the same reason, we don't need to worry about
* against checkpoint start. * interlocking against checkpoint start.
*/ */
if (MyLastRecPtr.xrecoff != 0 || nrels > 0) if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
{ {
@ -1000,10 +1004,10 @@ RecordSubTransactionAbort(void)
/* /*
* If we made neither any transaction-controlled XLOG entries nor any * If we made neither any transaction-controlled XLOG entries nor any
* temp-rel updates, and are not going to delete any files, we can omit * temp-rel updates, and are not going to delete any files, we can
* recording the transaction abort at all. No one will ever care that * omit recording the transaction abort at all. No one will ever care
* it aborted. (These tests cover our whole transaction tree, and * that it aborted. (These tests cover our whole transaction tree,
* therefore may mark subxacts that don't really need it, but it's * and therefore may mark subxacts that don't really need it, but it's
* probably not worth being tenser.) * probably not worth being tenser.)
* *
* In this case we needn't worry about marking subcommitted children as * In this case we needn't worry about marking subcommitted children as
@ -1071,8 +1075,8 @@ RecordSubTransactionAbort(void)
/* /*
* We can immediately remove failed XIDs from PGPROC's cache of * We can immediately remove failed XIDs from PGPROC's cache of
* running child XIDs. It's easiest to do it here while we have the * running child XIDs. It's easiest to do it here while we have the
* child XID array at hand, even though in the main-transaction * child XID array at hand, even though in the main-transaction case
* case the equivalent work happens just after return from * the equivalent work happens just after return from
* RecordTransactionAbort. * RecordTransactionAbort.
*/ */
XidCacheRemoveRunningXids(xid, nchildren, children); XidCacheRemoveRunningXids(xid, nchildren, children);
@ -1169,7 +1173,8 @@ StartTransaction(void)
s->state = TRANS_START; s->state = TRANS_START;
/* /*
* Make sure we've freed any old snapshot, and reset xact state variables * Make sure we've freed any old snapshot, and reset xact state
* variables
*/ */
FreeXactSnapshot(); FreeXactSnapshot();
XactIsoLevel = DefaultXactIsoLevel; XactIsoLevel = DefaultXactIsoLevel;
@ -1323,9 +1328,9 @@ CommitTransaction(void)
* want to release locks at the point where any backend waiting for us * want to release locks at the point where any backend waiting for us
* will see our transaction as being fully cleaned up. * will see our transaction as being fully cleaned up.
* *
* Resources that can be associated with individual queries are * Resources that can be associated with individual queries are handled
* handled by the ResourceOwner mechanism. The other calls here * by the ResourceOwner mechanism. The other calls here are for
* are for backend-wide state. * backend-wide state.
*/ */
smgrDoPendingDeletes(true); smgrDoPendingDeletes(true);
@ -1342,7 +1347,8 @@ CommitTransaction(void)
* after relcache references are dropped (see comments for * after relcache references are dropped (see comments for
* AtEOXact_RelationCache), but before locks are released (if anyone * AtEOXact_RelationCache), but before locks are released (if anyone
* is waiting for lock on a relation we've modified, we want them to * is waiting for lock on a relation we've modified, we want them to
* know about the catalog change before they start using the relation). * know about the catalog change before they start using the
* relation).
*/ */
AtEOXact_Inval(true); AtEOXact_Inval(true);
@ -1428,7 +1434,8 @@ AbortTransaction(void)
/* /*
* Reset user id which might have been changed transiently. We cannot * Reset user id which might have been changed transiently. We cannot
* use s->currentUser, but must get the session userid from miscinit.c. * use s->currentUser, but must get the session userid from
* miscinit.c.
* *
* (Note: it is not necessary to restore session authorization here * (Note: it is not necessary to restore session authorization here
* because that can only be changed via GUC, and GUC will take care of * because that can only be changed via GUC, and GUC will take care of
@ -1561,9 +1568,10 @@ StartTransactionCommand(void)
break; break;
/* /*
* This is the case when we are somewhere in a transaction block * This is the case when we are somewhere in a transaction
* and about to start a new command. For now we do nothing * block and about to start a new command. For now we do
* but someday we may do command-local resource initialization. * nothing but someday we may do command-local resource
* initialization.
*/ */
case TBLOCK_INPROGRESS: case TBLOCK_INPROGRESS:
case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBINPROGRESS:
@ -1616,8 +1624,8 @@ CommitTransactionCommand(void)
/* /*
* This shouldn't happen, because it means the previous * This shouldn't happen, because it means the previous
* StartTransactionCommand didn't set the STARTED state * StartTransactionCommand didn't set the STARTED state
* appropriately, or we didn't manage previous pending * appropriately, or we didn't manage previous pending abort
* abort states. * states.
*/ */
case TBLOCK_DEFAULT: case TBLOCK_DEFAULT:
case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBABORT_PENDING:
@ -1694,14 +1702,16 @@ CommitTransactionCommand(void)
*/ */
case TBLOCK_SUBENDABORT_ALL: case TBLOCK_SUBENDABORT_ALL:
AbortOutOfAnyTransaction(); AbortOutOfAnyTransaction();
s = CurrentTransactionState; /* changed by AbortOutOfAnyTransaction */ s = CurrentTransactionState; /* changed by
* AbortOutOfAnyTransaction
* */
/* AbortOutOfAnyTransaction sets the blockState */ /* AbortOutOfAnyTransaction sets the blockState */
break; break;
/* /*
* We were just issued a SAVEPOINT inside a transaction block. * We were just issued a SAVEPOINT inside a transaction block.
* Start a subtransaction. (DefineSavepoint already * Start a subtransaction. (DefineSavepoint already did
* did PushTransaction, so as to have someplace to put the * PushTransaction, so as to have someplace to put the
* SUBBEGIN state.) * SUBBEGIN state.)
*/ */
case TBLOCK_SUBBEGIN: case TBLOCK_SUBBEGIN:
@ -1720,11 +1730,12 @@ CommitTransactionCommand(void)
* We were issued a RELEASE command, so we end the current * We were issued a RELEASE command, so we end the current
* subtransaction and return to the parent transaction. * subtransaction and return to the parent transaction.
* *
* Since RELEASE can exit multiple levels of subtransaction, * Since RELEASE can exit multiple levels of subtransaction, we
* we must loop here until we get out of all SUBEND'ed levels. * must loop here until we get out of all SUBEND'ed levels.
*/ */
case TBLOCK_SUBEND: case TBLOCK_SUBEND:
do { do
{
CommitSubTransaction(); CommitSubTransaction();
PopTransaction(); PopTransaction();
s = CurrentTransactionState; /* changed by pop */ s = CurrentTransactionState; /* changed by pop */
@ -1738,17 +1749,17 @@ CommitTransactionCommand(void)
break; break;
/* /*
* The current subtransaction is ending. Do the equivalent * The current subtransaction is ending. Do the equivalent of
* of a ROLLBACK TO followed by a RELEASE command. * a ROLLBACK TO followed by a RELEASE command.
*/ */
case TBLOCK_SUBENDABORT_RELEASE: case TBLOCK_SUBENDABORT_RELEASE:
CleanupAbortedSubTransactions(false); CleanupAbortedSubTransactions(false);
break; break;
/* /*
* The current subtransaction is ending due to a ROLLBACK * The current subtransaction is ending due to a ROLLBACK TO
* TO command, so close all savepoints up to the target * command, so close all savepoints up to the target level.
* level. When finished, recreate the savepoint. * When finished, recreate the savepoint.
*/ */
case TBLOCK_SUBENDABORT: case TBLOCK_SUBENDABORT:
{ {
@ -1756,7 +1767,8 @@ CommitTransactionCommand(void)
Assert(PointerIsValid(name)); Assert(PointerIsValid(name));
DefineSavepoint(name); DefineSavepoint(name);
s = CurrentTransactionState; /* changed by DefineSavepoint */ s = CurrentTransactionState; /* changed by
* DefineSavepoint */
pfree(name); pfree(name);
/* This is the same as TBLOCK_SUBBEGIN case */ /* This is the same as TBLOCK_SUBBEGIN case */
@ -1856,10 +1868,10 @@ AbortCurrentTransaction(void)
break; break;
/* /*
* This is the case when we are somewhere in a transaction block * This is the case when we are somewhere in a transaction
* and we've gotten a failure, so we abort the transaction and * block and we've gotten a failure, so we abort the
* set up the persistent ABORT state. We will stay in ABORT * transaction and set up the persistent ABORT state. We will
* until we get an "END TRANSACTION". * stay in ABORT until we get an "END TRANSACTION".
*/ */
case TBLOCK_INPROGRESS: case TBLOCK_INPROGRESS:
AbortTransaction(); AbortTransaction();
@ -1900,8 +1912,8 @@ AbortCurrentTransaction(void)
break; break;
/* /*
* If we are just starting a subtransaction, put it * If we are just starting a subtransaction, put it in aborted
* in aborted state. * state.
*/ */
case TBLOCK_SUBBEGIN: case TBLOCK_SUBBEGIN:
StartAbortedSubTransaction(); StartAbortedSubTransaction();
@ -1914,8 +1926,8 @@ AbortCurrentTransaction(void)
break; break;
/* /*
* If we are aborting an ending transaction, * If we are aborting an ending transaction, we have to abort
* we have to abort the parent transaction too. * the parent transaction too.
*/ */
case TBLOCK_SUBEND: case TBLOCK_SUBEND:
case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBABORT_PENDING:
@ -1942,8 +1954,8 @@ AbortCurrentTransaction(void)
break; break;
/* /*
* We are already aborting the whole transaction tree. * We are already aborting the whole transaction tree. Do
* Do nothing, CommitTransactionCommand will call * nothing, CommitTransactionCommand will call
* AbortOutOfAnyTransaction and set things straight. * AbortOutOfAnyTransaction and set things straight.
*/ */
case TBLOCK_SUBENDABORT_ALL: case TBLOCK_SUBENDABORT_ALL:
@ -2068,8 +2080,8 @@ bool
IsInTransactionChain(void *stmtNode) IsInTransactionChain(void *stmtNode)
{ {
/* /*
* Return true on same conditions that would make PreventTransactionChain * Return true on same conditions that would make
* error out * PreventTransactionChain error out
*/ */
if (IsTransactionBlock()) if (IsTransactionBlock())
return true; return true;
@ -2141,9 +2153,7 @@ CallXactCallbacks(XactEvent event, TransactionId parentXid)
XactCallbackItem *item; XactCallbackItem *item;
for (item = Xact_callbacks; item; item = item->next) for (item = Xact_callbacks; item; item = item->next)
{
(*item->callback) (event, parentXid, item->arg); (*item->callback) (event, parentXid, item->arg);
}
} }
@ -2164,8 +2174,8 @@ BeginTransactionBlock(void)
switch (s->blockState) switch (s->blockState)
{ {
/* /*
* We are not inside a transaction block, so allow one * We are not inside a transaction block, so allow one to
* to begin. * begin.
*/ */
case TBLOCK_STARTED: case TBLOCK_STARTED:
s->blockState = TBLOCK_BEGIN; s->blockState = TBLOCK_BEGIN;
@ -2217,9 +2227,10 @@ EndTransactionBlock(void)
{ {
/* /*
* We are in a transaction block which should commit when we * We are in a transaction block which should commit when we
* get to the upcoming CommitTransactionCommand() so we set the * get to the upcoming CommitTransactionCommand() so we set
* state to "END". CommitTransactionCommand() will recognize this * the state to "END". CommitTransactionCommand() will
* and commit the transaction and return us to the default state. * recognize this and commit the transaction and return us to
* the default state.
*/ */
case TBLOCK_INPROGRESS: case TBLOCK_INPROGRESS:
case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBINPROGRESS:
@ -2229,30 +2240,31 @@ EndTransactionBlock(void)
/* /*
* We are in a transaction block which aborted. Since the * We are in a transaction block which aborted. Since the
* AbortTransaction() was already done, we need only * AbortTransaction() was already done, we need only change to
* change to the special "END ABORT" state. The upcoming * the special "END ABORT" state. The upcoming
* CommitTransactionCommand() will recognise this and then put us * CommitTransactionCommand() will recognise this and then put
* back in the default state. * us back in the default state.
*/ */
case TBLOCK_ABORT: case TBLOCK_ABORT:
s->blockState = TBLOCK_ENDABORT; s->blockState = TBLOCK_ENDABORT;
break; break;
/* /*
* Here we are inside an aborted subtransaction. Go to the "abort * Here we are inside an aborted subtransaction. Go to the
* the whole tree" state so that CommitTransactionCommand() calls * "abort the whole tree" state so that
* AbortOutOfAnyTransaction. * CommitTransactionCommand() calls AbortOutOfAnyTransaction.
*/ */
case TBLOCK_SUBABORT: case TBLOCK_SUBABORT:
s->blockState = TBLOCK_SUBENDABORT_ALL; s->blockState = TBLOCK_SUBENDABORT_ALL;
break; break;
case TBLOCK_STARTED: case TBLOCK_STARTED:
/* /*
* here, the user issued COMMIT when not inside a * here, the user issued COMMIT when not inside a transaction.
* transaction. Issue a WARNING and go to abort state. The * Issue a WARNING and go to abort state. The upcoming call
* upcoming call to CommitTransactionCommand() will then put us * to CommitTransactionCommand() will then put us back into
* back into the default state. * the default state.
*/ */
ereport(WARNING, ereport(WARNING,
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
@ -2303,11 +2315,10 @@ UserAbortTransactionBlock(void)
break; break;
/* /*
* We are inside a failed subtransaction and we got an * We are inside a failed subtransaction and we got an abort
* abort command from the user. Abort processing is already * command from the user. Abort processing is already done,
* done, so go to the "abort all" state and * so go to the "abort all" state and CommitTransactionCommand
* CommitTransactionCommand will call AbortOutOfAnyTransaction * will call AbortOutOfAnyTransaction to set things straight.
* to set things straight.
*/ */
case TBLOCK_SUBABORT: case TBLOCK_SUBABORT:
s->blockState = TBLOCK_SUBENDABORT_ALL; s->blockState = TBLOCK_SUBENDABORT_ALL;
@ -2382,10 +2393,11 @@ DefineSavepoint(char *name)
/* Normal subtransaction start */ /* Normal subtransaction start */
PushTransaction(); PushTransaction();
s = CurrentTransactionState; /* changed by push */ s = CurrentTransactionState; /* changed by push */
/* /*
* Note that we are allocating the savepoint name in the * Note that we are allocating the savepoint name in the
* parent transaction's CurTransactionContext, since we * parent transaction's CurTransactionContext, since we don't
* don't yet have a transaction context for the new guy. * yet have a transaction context for the new guy.
*/ */
s->name = MemoryContextStrdup(CurTransactionContext, name); s->name = MemoryContextStrdup(CurTransactionContext, name);
s->blockState = TBLOCK_SUBBEGIN; s->blockState = TBLOCK_SUBBEGIN;
@ -2437,8 +2449,8 @@ ReleaseSavepoint(List *options)
break; break;
/* /*
* We are in a non-aborted subtransaction. This is * We are in a non-aborted subtransaction. This is the only
* the only valid case. * valid case.
*/ */
case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBINPROGRESS:
break; break;
@ -2461,7 +2473,7 @@ ReleaseSavepoint(List *options)
break; break;
} }
foreach (cell, options) foreach(cell, options)
{ {
DefElem *elem = lfirst(cell); DefElem *elem = lfirst(cell);
@ -2490,8 +2502,8 @@ ReleaseSavepoint(List *options)
/* /*
* Mark "commit pending" all subtransactions up to the target * Mark "commit pending" all subtransactions up to the target
* subtransaction. The actual commits will happen when control * subtransaction. The actual commits will happen when control gets
* gets to CommitTransactionCommand. * to CommitTransactionCommand.
*/ */
xact = CurrentTransactionState; xact = CurrentTransactionState;
for (;;) for (;;)
@ -2536,9 +2548,10 @@ RollbackToSavepoint(List *options)
*/ */
case TBLOCK_SUBABORT: case TBLOCK_SUBABORT:
case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBINPROGRESS:
/* /*
* Have to do AbortSubTransaction, but first check * Have to do AbortSubTransaction, but first check if this is
* if this is the right subtransaction * the right subtransaction
*/ */
break; break;
@ -2559,7 +2572,7 @@ RollbackToSavepoint(List *options)
break; break;
} }
foreach (cell, options) foreach(cell, options)
{ {
DefElem *elem = lfirst(cell); DefElem *elem = lfirst(cell);
@ -2633,10 +2646,11 @@ BeginInternalSubTransaction(char *name)
/* Normal subtransaction start */ /* Normal subtransaction start */
PushTransaction(); PushTransaction();
s = CurrentTransactionState; /* changed by push */ s = CurrentTransactionState; /* changed by push */
/* /*
* Note that we are allocating the savepoint name in the * Note that we are allocating the savepoint name in the
* parent transaction's CurTransactionContext, since we * parent transaction's CurTransactionContext, since we don't
* don't yet have a transaction context for the new guy. * yet have a transaction context for the new guy.
*/ */
if (name) if (name)
s->name = MemoryContextStrdup(CurTransactionContext, name); s->name = MemoryContextStrdup(CurTransactionContext, name);
@ -2748,7 +2762,8 @@ AbortOutOfAnyTransaction(void)
/* /*
* Get out of any transaction or nested transaction * Get out of any transaction or nested transaction
*/ */
do { do
{
switch (s->blockState) switch (s->blockState)
{ {
case TBLOCK_DEFAULT: case TBLOCK_DEFAULT:
@ -2770,9 +2785,10 @@ AbortOutOfAnyTransaction(void)
s->blockState = TBLOCK_DEFAULT; s->blockState = TBLOCK_DEFAULT;
break; break;
case TBLOCK_SUBBEGIN: case TBLOCK_SUBBEGIN:
/* /*
* We didn't get as far as starting the subxact, so there's * We didn't get as far as starting the subxact, so
* nothing to abort. Just pop back to parent. * there's nothing to abort. Just pop back to parent.
*/ */
PopTransaction(); PopTransaction();
s = CurrentTransactionState; /* changed by pop */ s = CurrentTransactionState; /* changed by pop */
@ -2780,7 +2796,11 @@ AbortOutOfAnyTransaction(void)
case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBINPROGRESS:
case TBLOCK_SUBEND: case TBLOCK_SUBEND:
case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBABORT_PENDING:
/* In a subtransaction, so clean it up and abort parent too */
/*
* In a subtransaction, so clean it up and abort parent
* too
*/
AbortSubTransaction(); AbortSubTransaction();
CleanupSubTransaction(); CleanupSubTransaction();
PopTransaction(); PopTransaction();
@ -2928,9 +2948,10 @@ StartSubTransaction(void)
/* /*
* Generate a new Xid and record it in pg_subtrans. NB: we must make * Generate a new Xid and record it in pg_subtrans. NB: we must make
* the subtrans entry BEFORE the Xid appears anywhere in shared storage, * the subtrans entry BEFORE the Xid appears anywhere in shared
* such as in the lock table; because until it's made the Xid may not * storage, such as in the lock table; because until it's made the Xid
* appear to be "running" to other backends. See GetNewTransactionId. * may not appear to be "running" to other backends. See
* GetNewTransactionId.
*/ */
s->transactionIdData = GetNewTransactionId(true); s->transactionIdData = GetNewTransactionId(true);
@ -3020,9 +3041,9 @@ CommitSubTransaction(void)
s->parent->transactionIdData); s->parent->transactionIdData);
/* /*
* We need to restore the upper transaction's read-only state, * We need to restore the upper transaction's read-only state, in case
* in case the upper is read-write while the child is read-only; * the upper is read-write while the child is read-only; GUC will
* GUC will incorrectly think it should leave the child state in place. * incorrectly think it should leave the child state in place.
*/ */
XactReadOnly = s->prevXactReadOnly; XactReadOnly = s->prevXactReadOnly;
@ -3117,14 +3138,16 @@ AbortSubTransaction(void)
/* /*
* Reset user id which might have been changed transiently. Here we * Reset user id which might have been changed transiently. Here we
* want to restore to the userid that was current at subxact entry. * want to restore to the userid that was current at subxact entry.
* (As in AbortTransaction, we need not worry about the session userid.) * (As in AbortTransaction, we need not worry about the session
* userid.)
* *
* Must do this after AtEOXact_GUC to handle the case where we entered * Must do this after AtEOXact_GUC to handle the case where we entered
* the subxact inside a SECURITY DEFINER function (hence current and * the subxact inside a SECURITY DEFINER function (hence current and
* session userids were different) and then session auth was changed * session userids were different) and then session auth was changed
* inside the subxact. GUC will reset both current and session userids * inside the subxact. GUC will reset both current and session
* to the entry-time session userid. This is right in every other * userids to the entry-time session userid. This is right in every
* scenario so it seems simplest to let GUC do that and fix it here. * other scenario so it seems simplest to let GUC do that and fix it
* here.
*/ */
SetUserId(s->currentUser); SetUserId(s->currentUser);
@ -3197,7 +3220,8 @@ StartAbortedSubTransaction(void)
s->currentUser = s->parent->currentUser; s->currentUser = s->parent->currentUser;
/* /*
* Initialize only what has to be there for CleanupSubTransaction to work. * Initialize only what has to be there for CleanupSubTransaction to
* work.
*/ */
AtSubStart_Memory(); AtSubStart_Memory();
AtSubStart_ResourceOwner(); AtSubStart_ResourceOwner();
@ -3502,6 +3526,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec)
for (i = 0; i < xlrec->nrels; i++) for (i = 0; i < xlrec->nrels; i++)
{ {
RelFileNode rnode = xlrec->xnodes[i]; RelFileNode rnode = xlrec->xnodes[i];
sprintf(buf + strlen(buf), " %u/%u/%u", sprintf(buf + strlen(buf), " %u/%u/%u",
rnode.spcNode, rnode.dbNode, rnode.relNode); rnode.spcNode, rnode.dbNode, rnode.relNode);
} }
@ -3530,6 +3555,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec)
for (i = 0; i < xlrec->nrels; i++) for (i = 0; i < xlrec->nrels; i++)
{ {
RelFileNode rnode = xlrec->xnodes[i]; RelFileNode rnode = xlrec->xnodes[i];
sprintf(buf + strlen(buf), " %u/%u/%u", sprintf(buf + strlen(buf), " %u/%u/%u",
rnode.spcNode, rnode.dbNode, rnode.relNode); rnode.spcNode, rnode.dbNode, rnode.relNode);
} }
@ -3549,7 +3575,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec)
} }
void void
XactPushRollback(void (*func) (void *), void *data) XactPushRollback(void (*func) (void *), void *data)
{ {
#ifdef XLOG_II #ifdef XLOG_II
if (_RollbackFunc != NULL) if (_RollbackFunc != NULL)

View File

@ -7,7 +7,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/xlog.c,v 1.165 2004/08/29 04:12:23 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.166 2004/08/29 05:06:40 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -128,8 +128,10 @@ TimeLineID ThisTimeLineID = 0;
/* Are we doing recovery from XLOG? */ /* Are we doing recovery from XLOG? */
bool InRecovery = false; bool InRecovery = false;
/* Are we recovering using offline XLOG archives? */ /* Are we recovering using offline XLOG archives? */
static bool InArchiveRecovery = false; static bool InArchiveRecovery = false;
/* Was the last xlog file restored from archive, or local? */ /* Was the last xlog file restored from archive, or local? */
static bool restoredFromArchive = false; static bool restoredFromArchive = false;
@ -147,7 +149,7 @@ static time_t recoveryStopTime;
static bool recoveryStopAfter; static bool recoveryStopAfter;
/* constraint set by read_backup_label */ /* constraint set by read_backup_label */
static XLogRecPtr recoveryMinXlogOffset = { 0, 0 }; static XLogRecPtr recoveryMinXlogOffset = {0, 0};
/* /*
* During normal operation, the only timeline we care about is ThisTimeLineID. * During normal operation, the only timeline we care about is ThisTimeLineID.
@ -453,6 +455,7 @@ static void WriteControlFile(void);
static void ReadControlFile(void); static void ReadControlFile(void);
static char *str_time(time_t tnow); static char *str_time(time_t tnow);
static void issue_xlog_fsync(void); static void issue_xlog_fsync(void);
#ifdef WAL_DEBUG #ifdef WAL_DEBUG
static void xlog_outrec(char *buf, XLogRecord *record); static void xlog_outrec(char *buf, XLogRecord *record);
#endif #endif
@ -514,7 +517,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID) if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
{ {
RecPtr.xlogid = 0; RecPtr.xlogid = 0;
RecPtr.xrecoff = SizeOfXLogLongPHD; /* start of 1st chkpt record */ RecPtr.xrecoff = SizeOfXLogLongPHD; /* start of 1st chkpt
* record */
return (RecPtr); return (RecPtr);
} }
@ -724,7 +728,8 @@ begin:;
/* /*
* If there isn't enough space on the current XLOG page for a record * If there isn't enough space on the current XLOG page for a record
* header, advance to the next page (leaving the unused space as zeroes). * header, advance to the next page (leaving the unused space as
* zeroes).
*/ */
updrqst = false; updrqst = false;
freespace = INSERT_FREESPACE(Insert); freespace = INSERT_FREESPACE(Insert);
@ -900,14 +905,16 @@ XLogArchiveNotify(const char *xlog)
/* insert an otherwise empty file called <XLOG>.ready */ /* insert an otherwise empty file called <XLOG>.ready */
StatusFilePath(archiveStatusPath, xlog, ".ready"); StatusFilePath(archiveStatusPath, xlog, ".ready");
fd = AllocateFile(archiveStatusPath, "w"); fd = AllocateFile(archiveStatusPath, "w");
if (fd == NULL) { if (fd == NULL)
{
ereport(LOG, ereport(LOG,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not create archive status file \"%s\": %m", errmsg("could not create archive status file \"%s\": %m",
archiveStatusPath))); archiveStatusPath)));
return; return;
} }
if (FreeFile(fd)) { if (FreeFile(fd))
{
ereport(LOG, ereport(LOG,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not write archive status file \"%s\": %m", errmsg("could not write archive status file \"%s\": %m",
@ -1823,11 +1830,11 @@ XLogFileRead(uint32 log, uint32 seg, int emode)
int fd; int fd;
/* /*
* Loop looking for a suitable timeline ID: we might need to * Loop looking for a suitable timeline ID: we might need to read any
* read any of the timelines listed in expectedTLIs. * of the timelines listed in expectedTLIs.
* *
* We expect curFileTLI on entry to be the TLI of the preceding file * We expect curFileTLI on entry to be the TLI of the preceding file in
* in sequence, or 0 if there was no predecessor. We do not allow * sequence, or 0 if there was no predecessor. We do not allow
* curFileTLI to go backwards; this prevents us from picking up the * curFileTLI to go backwards; this prevents us from picking up the
* wrong file when a parent timeline extends to higher segment numbers * wrong file when a parent timeline extends to higher segment numbers
* than the child we want to read. * than the child we want to read.
@ -1902,25 +1909,26 @@ RestoreArchivedFile(char *path, const char *xlogfname,
/* /*
* When doing archive recovery, we always prefer an archived log file * When doing archive recovery, we always prefer an archived log file
* even if a file of the same name exists in XLogDir. The reason is * even if a file of the same name exists in XLogDir. The reason is
* that the file in XLogDir could be an old, un-filled or partly-filled * that the file in XLogDir could be an old, un-filled or
* version that was copied and restored as part of backing up $PGDATA. * partly-filled version that was copied and restored as part of
* backing up $PGDATA.
* *
* We could try to optimize this slightly by checking the local * We could try to optimize this slightly by checking the local copy
* copy lastchange timestamp against the archived copy, * lastchange timestamp against the archived copy, but we have no API
* but we have no API to do this, nor can we guarantee that the * to do this, nor can we guarantee that the lastchange timestamp was
* lastchange timestamp was preserved correctly when we copied * preserved correctly when we copied to archive. Our aim is
* to archive. Our aim is robustness, so we elect not to do this. * robustness, so we elect not to do this.
* *
* If we cannot obtain the log file from the archive, however, we * If we cannot obtain the log file from the archive, however, we will
* will try to use the XLogDir file if it exists. This is so that * try to use the XLogDir file if it exists. This is so that we can
* we can make use of log segments that weren't yet transferred to * make use of log segments that weren't yet transferred to the
* the archive. * archive.
* *
* Notice that we don't actually overwrite any files when we copy back * Notice that we don't actually overwrite any files when we copy back
* from archive because the recoveryRestoreCommand may inadvertently * from archive because the recoveryRestoreCommand may inadvertently
* restore inappropriate xlogs, or they may be corrupt, so we may * restore inappropriate xlogs, or they may be corrupt, so we may wish
* wish to fallback to the segments remaining in current XLogDir later. * to fallback to the segments remaining in current XLogDir later. The
* The copy-from-archive filename is always the same, ensuring that we * copy-from-archive filename is always the same, ensuring that we
* don't run out of disk space on long recoveries. * don't run out of disk space on long recoveries.
*/ */
snprintf(xlogpath, MAXPGPATH, "%s/%s", XLogDir, recovername); snprintf(xlogpath, MAXPGPATH, "%s/%s", XLogDir, recovername);
@ -1961,14 +1969,14 @@ RestoreArchivedFile(char *path, const char *xlogfname,
case 'p': case 'p':
/* %p: full path of target file */ /* %p: full path of target file */
sp++; sp++;
StrNCpy(dp, xlogpath, endp-dp); StrNCpy(dp, xlogpath, endp - dp);
make_native_path(dp); make_native_path(dp);
dp += strlen(dp); dp += strlen(dp);
break; break;
case 'f': case 'f':
/* %f: filename of desired file */ /* %f: filename of desired file */
sp++; sp++;
StrNCpy(dp, xlogfname, endp-dp); StrNCpy(dp, xlogfname, endp - dp);
dp += strlen(dp); dp += strlen(dp);
break; break;
case '%': case '%':
@ -2006,9 +2014,9 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* command apparently succeeded, but let's make sure the file is * command apparently succeeded, but let's make sure the file is
* really there now and has the correct size. * really there now and has the correct size.
* *
* XXX I made wrong-size a fatal error to ensure the DBA would * XXX I made wrong-size a fatal error to ensure the DBA would notice
* notice it, but is that too strong? We could try to plow ahead * it, but is that too strong? We could try to plow ahead with a
* with a local copy of the file ... but the problem is that there * local copy of the file ... but the problem is that there
* probably isn't one, and we'd incorrectly conclude we've reached * probably isn't one, and we'd incorrectly conclude we've reached
* the end of WAL and we're done recovering ... * the end of WAL and we're done recovering ...
*/ */
@ -2041,11 +2049,10 @@ RestoreArchivedFile(char *path, const char *xlogfname,
} }
/* /*
* remember, we rollforward UNTIL the restore fails * remember, we rollforward UNTIL the restore fails so failure here is
* so failure here is just part of the process... * just part of the process... that makes it difficult to determine
* that makes it difficult to determine whether the restore * whether the restore failed because there isn't an archive to
* failed because there isn't an archive to restore, or * restore, or because the administrator has specified the restore
* because the administrator has specified the restore
* program incorrectly. We have to assume the former. * program incorrectly. We have to assume the former.
*/ */
ereport(DEBUG1, ereport(DEBUG1,
@ -2053,11 +2060,12 @@ RestoreArchivedFile(char *path, const char *xlogfname,
xlogfname, rc))); xlogfname, rc)));
/* /*
* if an archived file is not available, there might still be a version * if an archived file is not available, there might still be a
* of this file in XLogDir, so return that as the filename to open. * version of this file in XLogDir, so return that as the filename to
* open.
* *
* In many recovery scenarios we expect this to fail also, but * In many recovery scenarios we expect this to fail also, but if so that
* if so that just means we've reached the end of WAL. * just means we've reached the end of WAL.
*/ */
snprintf(path, MAXPGPATH, "%s/%s", XLogDir, xlogfname); snprintf(path, MAXPGPATH, "%s/%s", XLogDir, xlogfname);
return false; return false;
@ -2124,8 +2132,8 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
* segments of non-parent timelines, but that would be a whole lot * segments of non-parent timelines, but that would be a whole lot
* more complicated. * more complicated.
* *
* We use the alphanumeric sorting property of the filenames to decide * We use the alphanumeric sorting property of the filenames to
* which ones are earlier than the lastoff segment. * decide which ones are earlier than the lastoff segment.
*/ */
if (strlen(xlde->d_name) == 24 && if (strlen(xlde->d_name) == 24 &&
strspn(xlde->d_name, "0123456789ABCDEF") == 24 && strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
@ -2171,8 +2179,11 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
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
@ -2361,12 +2372,13 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
ereport(PANIC, ereport(PANIC,
(errmsg("invalid record offset at %X/%X", (errmsg("invalid record offset at %X/%X",
RecPtr->xlogid, RecPtr->xrecoff))); RecPtr->xlogid, RecPtr->xrecoff)));
/* /*
* Since we are going to a random position in WAL, forget any * Since we are going to a random position in WAL, forget any
* prior state about what timeline we were in, and allow it * prior state about what timeline we were in, and allow it to be
* to be any timeline in expectedTLIs. We also set a flag to * any timeline in expectedTLIs. We also set a flag to allow
* allow curFileTLI to go backwards (but we can't reset that * curFileTLI to go backwards (but we can't reset that variable
* variable right here, since we might not change files at all). * right here, since we might not change files at all).
*/ */
lastPageTLI = 0; /* see comment in ValidXLOGHeader */ lastPageTLI = 0; /* see comment in ValidXLOGHeader */
randAccess = true; /* allow curFileTLI to go backwards too */ randAccess = true; /* allow curFileTLI to go backwards too */
@ -2418,9 +2430,9 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
if (targetRecOff == 0) if (targetRecOff == 0)
{ {
/* /*
* Can only get here in the continuing-from-prev-page case, because * Can only get here in the continuing-from-prev-page case,
* XRecOffIsValid eliminated the zero-page-offset case otherwise. * because XRecOffIsValid eliminated the zero-page-offset case
* Need to skip over the new page's header. * otherwise. Need to skip over the new page's header.
*/ */
tmpRecPtr.xrecoff += pageHeaderSize; tmpRecPtr.xrecoff += pageHeaderSize;
targetRecOff = pageHeaderSize; targetRecOff = pageHeaderSize;
@ -2671,9 +2683,9 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
* immediate parent's TLI, we should never see TLI go backwards across * immediate parent's TLI, we should never see TLI go backwards across
* successive pages of a consistent WAL sequence. * successive pages of a consistent WAL sequence.
* *
* Of course this check should only be applied when advancing sequentially * Of course this check should only be applied when advancing
* across pages; therefore ReadRecord resets lastPageTLI to zero when * sequentially across pages; therefore ReadRecord resets lastPageTLI
* going to a random page. * to zero when going to a random page.
*/ */
if (hdr->xlp_tli < lastPageTLI) if (hdr->xlp_tli < lastPageTLI)
{ {
@ -2827,12 +2839,12 @@ findNewestTimeLine(TimeLineID startTLI)
TimeLineID probeTLI; TimeLineID probeTLI;
/* /*
* The algorithm is just to probe for the existence of timeline history * The algorithm is just to probe for the existence of timeline
* files. XXX is it useful to allow gaps in the sequence? * history files. XXX is it useful to allow gaps in the sequence?
*/ */
newestTLI = startTLI; newestTLI = startTLI;
for (probeTLI = startTLI + 1; ; probeTLI++) for (probeTLI = startTLI + 1;; probeTLI++)
{ {
if (existsTimeLineHistory(probeTLI)) if (existsTimeLineHistory(probeTLI))
{ {
@ -2932,7 +2944,11 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
* space * space
*/ */
unlink(tmppath); unlink(tmppath);
/* if write didn't set errno, assume problem is no disk space */
/*
* if write didn't set errno, assume problem is no disk
* space
*/
errno = save_errno ? save_errno : ENOSPC; errno = save_errno ? save_errno : ENOSPC;
ereport(PANIC, ereport(PANIC,
@ -2946,8 +2962,8 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
/* /*
* Append one line with the details of this timeline split. * Append one line with the details of this timeline split.
* *
* If we did have a parent file, insert an extra newline just in case * If we did have a parent file, insert an extra newline just in case the
* the parent file failed to end with one. * parent file failed to end with one.
*/ */
XLogFileName(xlogfname, endTLI, endLogId, endLogSeg); XLogFileName(xlogfname, endTLI, endLogId, endLogSeg);
@ -2967,8 +2983,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
int save_errno = errno; int save_errno = errno;
/* /*
* If we fail to make the file, delete it to release disk * If we fail to make the file, delete it to release disk space
* space
*/ */
unlink(tmppath); unlink(tmppath);
/* if write didn't set errno, assume problem is no disk space */ /* if write didn't set errno, assume problem is no disk space */
@ -3336,7 +3351,8 @@ XLOGShmemSize(void)
void void
XLOGShmemInit(void) XLOGShmemInit(void)
{ {
bool foundXLog, foundCFile; bool foundXLog,
foundCFile;
/* this must agree with space requested by XLOGShmemSize() */ /* this must agree with space requested by XLOGShmemSize() */
if (XLOGbuffers < MinXLOGbuffers) if (XLOGbuffers < MinXLOGbuffers)
@ -3414,16 +3430,17 @@ BootStrapXLOG(void)
crc64 crc; crc64 crc;
/* /*
* Select a hopefully-unique system identifier code for this installation. * Select a hopefully-unique system identifier code for this
* We use the result of gettimeofday(), including the fractional seconds * installation. We use the result of gettimeofday(), including the
* field, as being about as unique as we can easily get. (Think not to * fractional seconds field, as being about as unique as we can easily
* use random(), since it hasn't been seeded and there's no portable way * get. (Think not to use random(), since it hasn't been seeded and
* to seed it other than the system clock value...) The upper half of the * there's no portable way to seed it other than the system clock
* uint64 value is just the tv_sec part, while the lower half is the XOR * value...) The upper half of the uint64 value is just the tv_sec
* of tv_sec and tv_usec. This is to ensure that we don't lose uniqueness * part, while the lower half is the XOR of tv_sec and tv_usec. This
* unnecessarily if "uint64" is really only 32 bits wide. A person * is to ensure that we don't lose uniqueness unnecessarily if
* knowing this encoding can determine the initialization time of the * "uint64" is really only 32 bits wide. A person knowing this
* installation, which could perhaps be useful sometimes. * encoding can determine the initialization time of the installation,
* which could perhaps be useful sometimes.
*/ */
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
sysidentifier = ((uint64) tv.tv_sec) << 32; sysidentifier = ((uint64) tv.tv_sec) << 32;
@ -3611,13 +3628,15 @@ readRecoveryCommandFile(void)
break; break;
} }
if (strcmp(tok1,"restore_command") == 0) { if (strcmp(tok1, "restore_command") == 0)
{
recoveryRestoreCommand = pstrdup(tok2); recoveryRestoreCommand = pstrdup(tok2);
ereport(LOG, ereport(LOG,
(errmsg("restore_command = \"%s\"", (errmsg("restore_command = \"%s\"",
recoveryRestoreCommand))); recoveryRestoreCommand)));
} }
else if (strcmp(tok1,"recovery_target_timeline") == 0) { else if (strcmp(tok1, "recovery_target_timeline") == 0)
{
rtliGiven = true; rtliGiven = true;
if (strcmp(tok2, "latest") == 0) if (strcmp(tok2, "latest") == 0)
rtli = 0; rtli = 0;
@ -3637,7 +3656,8 @@ readRecoveryCommandFile(void)
ereport(LOG, ereport(LOG,
(errmsg("recovery_target_timeline = latest"))); (errmsg("recovery_target_timeline = latest")));
} }
else if (strcmp(tok1,"recovery_target_xid") == 0) { else if (strcmp(tok1, "recovery_target_xid") == 0)
{
errno = 0; errno = 0;
recoveryTargetXid = (TransactionId) strtoul(tok2, NULL, 0); recoveryTargetXid = (TransactionId) strtoul(tok2, NULL, 0);
if (errno == EINVAL || errno == ERANGE) if (errno == EINVAL || errno == ERANGE)
@ -3650,7 +3670,8 @@ readRecoveryCommandFile(void)
recoveryTarget = true; recoveryTarget = true;
recoveryTargetExact = true; recoveryTargetExact = true;
} }
else if (strcmp(tok1,"recovery_target_time") == 0) { else if (strcmp(tok1, "recovery_target_time") == 0)
{
/* /*
* if recovery_target_xid specified, then this overrides * if recovery_target_xid specified, then this overrides
* recovery_target_time * recovery_target_time
@ -3659,10 +3680,11 @@ readRecoveryCommandFile(void)
continue; continue;
recoveryTarget = true; recoveryTarget = true;
recoveryTargetExact = false; recoveryTargetExact = false;
/* /*
* Convert the time string given by the user to the time_t format. * Convert the time string given by the user to the time_t
* We use type abstime's input converter because we know abstime * format. We use type abstime's input converter because we
* has the same representation as time_t. * know abstime has the same representation as time_t.
*/ */
recoveryTargetTime = (time_t) recoveryTargetTime = (time_t)
DatumGetAbsoluteTime(DirectFunctionCall1(abstimein, DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
@ -3672,7 +3694,8 @@ readRecoveryCommandFile(void)
DatumGetCString(DirectFunctionCall1(abstimeout, DatumGetCString(DirectFunctionCall1(abstimeout,
AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime)))))); AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime))))));
} }
else if (strcmp(tok1,"recovery_target_inclusive") == 0) { else if (strcmp(tok1, "recovery_target_inclusive") == 0)
{
/* /*
* does nothing if a recovery_target is not also set * does nothing if a recovery_target is not also set
*/ */
@ -3710,10 +3733,10 @@ readRecoveryCommandFile(void)
InArchiveRecovery = true; InArchiveRecovery = true;
/* /*
* If user specified recovery_target_timeline, validate it or compute the * If user specified recovery_target_timeline, validate it or compute
* "latest" value. We can't do this until after we've gotten the restore * the "latest" value. We can't do this until after we've gotten the
* command and set InArchiveRecovery, because we need to fetch timeline * restore command and set InArchiveRecovery, because we need to fetch
* history files from the archive. * timeline history files from the archive.
*/ */
if (rtliGiven) if (rtliGiven)
{ {
@ -3751,9 +3774,9 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
InArchiveRecovery = false; InArchiveRecovery = false;
/* /*
* We should have the ending log segment currently open. Verify, * We should have the ending log segment currently open. Verify, and
* and then close it (to avoid problems on Windows with trying to * then close it (to avoid problems on Windows with trying to rename
* rename or delete an open file). * or delete an open file).
*/ */
Assert(readFile >= 0); Assert(readFile >= 0);
Assert(readId == endLogId); Assert(readId == endLogId);
@ -3763,17 +3786,17 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
readFile = -1; readFile = -1;
/* /*
* If the segment was fetched from archival storage, we want to replace * If the segment was fetched from archival storage, we want to
* the existing xlog segment (if any) with the archival version. This * replace the existing xlog segment (if any) with the archival
* is because whatever is in XLogDir is very possibly older than what * version. This is because whatever is in XLogDir is very possibly
* we have from the archives, since it could have come from restoring * older than what we have from the archives, since it could have come
* a PGDATA backup. In any case, the archival version certainly is * from restoring a PGDATA backup. In any case, the archival version
* more descriptive of what our current database state is, because that * certainly is more descriptive of what our current database state
* is what we replayed from. * is, because that is what we replayed from.
* *
* Note that if we are establishing a new timeline, ThisTimeLineID is * Note that if we are establishing a new timeline, ThisTimeLineID is
* already set to the new value, and so we will create a new file instead * already set to the new value, and so we will create a new file
* of overwriting any existing file. * instead of overwriting any existing file.
*/ */
snprintf(recoveryPath, MAXPGPATH, "%s/RECOVERYXLOG", XLogDir); snprintf(recoveryPath, MAXPGPATH, "%s/RECOVERYXLOG", XLogDir);
XLogFilePath(xlogpath, ThisTimeLineID, endLogId, endLogSeg); XLogFilePath(xlogpath, ThisTimeLineID, endLogId, endLogSeg);
@ -3798,6 +3821,7 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
* RECOVERYXLOG laying about, get rid of it. * RECOVERYXLOG laying about, get rid of it.
*/ */
unlink(recoveryPath); /* ignore any error */ unlink(recoveryPath); /* ignore any error */
/* /*
* If we are establishing a new timeline, we have to copy data * If we are establishing a new timeline, we have to copy data
* from the last WAL segment of the old timeline to create a * from the last WAL segment of the old timeline to create a
@ -3809,8 +3833,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
} }
/* /*
* Let's just make real sure there are not .ready or .done flags posted * Let's just make real sure there are not .ready or .done flags
* for the new segment. * posted for the new segment.
*/ */
XLogFileName(xlogpath, ThisTimeLineID, endLogId, endLogSeg); XLogFileName(xlogpath, ThisTimeLineID, endLogId, endLogSeg);
XLogArchiveCleanup(xlogpath); XLogArchiveCleanup(xlogpath);
@ -3820,8 +3844,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
unlink(recoveryPath); /* ignore any error */ unlink(recoveryPath); /* ignore any error */
/* /*
* Rename the config file out of the way, so that we don't accidentally * Rename the config file out of the way, so that we don't
* re-enter archive recovery mode in a subsequent crash. * accidentally re-enter archive recovery mode in a subsequent crash.
*/ */
snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir); snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir);
snprintf(recoveryCommandDone, MAXPGPATH, "%s/recovery.done", DataDir); snprintf(recoveryCommandDone, MAXPGPATH, "%s/recovery.done", DataDir);
@ -3880,14 +3904,13 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
if (recoveryTargetExact) if (recoveryTargetExact)
{ {
/* /*
* there can be only one transaction end record * there can be only one transaction end record with this exact
* with this exact transactionid * transactionid
* *
* when testing for an xid, we MUST test for * when testing for an xid, we MUST test for equality only, since
* equality only, since transactions are numbered * transactions are numbered in the order they start, not the
* in the order they start, not the order they * order they complete. A higher numbered xid will complete before
* complete. A higher numbered xid will complete * you about 50% of the time...
* before you about 50% of the time...
*/ */
stopsHere = (record->xl_xid == recoveryTargetXid); stopsHere = (record->xl_xid == recoveryTargetXid);
if (stopsHere) if (stopsHere)
@ -3896,11 +3919,9 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
else else
{ {
/* /*
* there can be many transactions that * there can be many transactions that share the same commit time,
* share the same commit time, so * so we stop after the last one, if we are inclusive, or stop at
* we stop after the last one, if we are * the first one if we are exclusive
* inclusive, or stop at the first one
* if we are exclusive
*/ */
if (recoveryTargetInclusive) if (recoveryTargetInclusive)
stopsHere = (recordXtime > recoveryTargetTime); stopsHere = (recordXtime > recoveryTargetTime);
@ -4009,14 +4030,14 @@ StartupXLOG(void)
#endif #endif
/* /*
* Initialize on the assumption we want to recover to the same timeline * Initialize on the assumption we want to recover to the same
* that's active according to pg_control. * timeline that's active according to pg_control.
*/ */
recoveryTargetTLI = ControlFile->checkPointCopy.ThisTimeLineID; recoveryTargetTLI = ControlFile->checkPointCopy.ThisTimeLineID;
/* /*
* Check for recovery control file, and if so set up state for * Check for recovery control file, and if so set up state for offline
* offline recovery * recovery
*/ */
readRecoveryCommandFile(); readRecoveryCommandFile();
@ -4038,8 +4059,9 @@ StartupXLOG(void)
if (read_backup_label(&checkPointLoc)) if (read_backup_label(&checkPointLoc))
{ {
/* /*
* When a backup_label file is present, we want to roll forward from * When a backup_label file is present, we want to roll forward
* the checkpoint it identifies, rather than using pg_control. * from the checkpoint it identifies, rather than using
* pg_control.
*/ */
record = ReadCheckpointRecord(checkPointLoc, 0, buffer); record = ReadCheckpointRecord(checkPointLoc, 0, buffer);
if (record != NULL) if (record != NULL)
@ -4059,8 +4081,8 @@ StartupXLOG(void)
else else
{ {
/* /*
* Get the last valid checkpoint record. If the latest one according * Get the last valid checkpoint record. If the latest one
* to pg_control is broken, try the next-to-last one. * according to pg_control is broken, try the next-to-last one.
*/ */
checkPointLoc = ControlFile->checkPoint; checkPointLoc = ControlFile->checkPoint;
record = ReadCheckpointRecord(checkPointLoc, 1, buffer); record = ReadCheckpointRecord(checkPointLoc, 1, buffer);
@ -4079,7 +4101,8 @@ StartupXLOG(void)
ereport(LOG, ereport(LOG,
(errmsg("using previous checkpoint record at %X/%X", (errmsg("using previous checkpoint record at %X/%X",
checkPointLoc.xlogid, checkPointLoc.xrecoff))); checkPointLoc.xlogid, checkPointLoc.xrecoff)));
InRecovery = true; /* force recovery even if SHUTDOWNED */ InRecovery = true; /* force recovery even if
* SHUTDOWNED */
} }
else else
ereport(PANIC, ereport(PANIC,
@ -4108,9 +4131,9 @@ StartupXLOG(void)
ShmemVariableCache->oidCount = 0; ShmemVariableCache->oidCount = 0;
/* /*
* We must replay WAL entries using the same TimeLineID they were created * We must replay WAL entries using the same TimeLineID they were
* under, so temporarily adopt the TLI indicated by the checkpoint (see * created under, so temporarily adopt the TLI indicated by the
* also xlog_redo()). * checkpoint (see also xlog_redo()).
*/ */
ThisTimeLineID = checkPoint.ThisTimeLineID; ThisTimeLineID = checkPoint.ThisTimeLineID;
@ -4123,8 +4146,8 @@ StartupXLOG(void)
checkPoint.undo = RecPtr; checkPoint.undo = RecPtr;
/* /*
* Check whether we need to force recovery from WAL. If it appears * Check whether we need to force recovery from WAL. If it appears to
* to have been a clean shutdown and we did not have a recovery.conf * have been a clean shutdown and we did not have a recovery.conf
* file, then assume no recovery needed. * file, then assume no recovery needed.
*/ */
if (XLByteLT(checkPoint.undo, RecPtr) || if (XLByteLT(checkPoint.undo, RecPtr) ||
@ -4242,6 +4265,7 @@ StartupXLOG(void)
record = ReadRecord(NULL, LOG, buffer); record = ReadRecord(NULL, LOG, buffer);
} while (record != NULL && recoveryContinue); } while (record != NULL && recoveryContinue);
/* /*
* end of main redo apply loop * end of main redo apply loop
*/ */
@ -4276,7 +4300,8 @@ StartupXLOG(void)
if (needNewTimeLine) /* stopped because of stop request */ if (needNewTimeLine) /* stopped because of stop request */
ereport(FATAL, ereport(FATAL,
(errmsg("requested recovery stop point is before end time of backup dump"))); (errmsg("requested recovery stop point is before end time of backup dump")));
else /* ran off end of WAL */ else
/* ran off end of WAL */
ereport(FATAL, ereport(FATAL,
(errmsg("WAL ends before end time of backup dump"))); (errmsg("WAL ends before end time of backup dump")));
} }
@ -4284,10 +4309,10 @@ StartupXLOG(void)
/* /*
* Consider whether we need to assign a new timeline ID. * Consider whether we need to assign a new timeline ID.
* *
* If we stopped short of the end of WAL during recovery, then we * If we stopped short of the end of WAL during recovery, then we are
* are generating a new timeline and must assign it a unique new ID. * generating a new timeline and must assign it a unique new ID.
* Otherwise, we can just extend the timeline we were in when we * Otherwise, we can just extend the timeline we were in when we ran
* ran out of WAL. * out of WAL.
*/ */
if (needNewTimeLine) if (needNewTimeLine)
{ {
@ -4302,8 +4327,8 @@ StartupXLOG(void)
XLogCtl->ThisTimeLineID = ThisTimeLineID; XLogCtl->ThisTimeLineID = ThisTimeLineID;
/* /*
* We are now done reading the old WAL. Turn off archive fetching * We are now done reading the old WAL. Turn off archive fetching if
* if it was active, and make a writable copy of the last WAL segment. * it was active, and make a writable copy of the last WAL segment.
* (Note that we also have a copy of the last block of the old WAL in * (Note that we also have a copy of the last block of the old WAL in
* readBuf; we will use that below.) * readBuf; we will use that below.)
*/ */
@ -4434,8 +4459,8 @@ StartupXLOG(void)
XLogCloseRelationCache(); XLogCloseRelationCache();
/* /*
* Now that we've checkpointed the recovery, it's safe to * Now that we've checkpointed the recovery, it's safe to flush
* flush old backup_label, if present. * old backup_label, if present.
*/ */
remove_backup_label(); remove_backup_label();
} }
@ -4791,8 +4816,8 @@ CreateCheckPoint(bool shutdown, bool force)
* so there's a risk of deadlock. Need to find a better solution. See * so there's a risk of deadlock. Need to find a better solution. See
* pgsql-hackers discussion of 17-Dec-01. * pgsql-hackers discussion of 17-Dec-01.
* *
* XXX actually, the whole UNDO code is dead code and unlikely to ever * XXX actually, the whole UNDO code is dead code and unlikely to ever be
* be revived, so the lack of a good solution here is not troubling. * revived, so the lack of a good solution here is not troubling.
*/ */
#ifdef NOT_USED #ifdef NOT_USED
checkPoint.undo = GetUndoRecPtr(); checkPoint.undo = GetUndoRecPtr();
@ -4919,11 +4944,11 @@ CreateCheckPoint(bool shutdown, bool force)
PreallocXlogFiles(recptr); PreallocXlogFiles(recptr);
/* /*
* Truncate pg_subtrans if possible. We can throw away all data before * Truncate pg_subtrans if possible. We can throw away all data
* the oldest XMIN of any running transaction. No future transaction will * before the oldest XMIN of any running transaction. No future
* attempt to reference any pg_subtrans entry older than that (see Asserts * transaction will attempt to reference any pg_subtrans entry older
* in subtrans.c). During recovery, though, we mustn't do this because * than that (see Asserts in subtrans.c). During recovery, though, we
* StartupSUBTRANS hasn't been called yet. * mustn't do this because StartupSUBTRANS hasn't been called yet.
*/ */
if (!InRecovery) if (!InRecovery)
TruncateSUBTRANS(GetOldestXmin(true)); TruncateSUBTRANS(GetOldestXmin(true));
@ -4974,8 +4999,10 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
ShmemVariableCache->nextXid = checkPoint.nextXid; ShmemVariableCache->nextXid = checkPoint.nextXid;
ShmemVariableCache->nextOid = checkPoint.nextOid; ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0; ShmemVariableCache->oidCount = 0;
/* /*
* TLI may change in a shutdown checkpoint, but it shouldn't decrease * TLI may change in a shutdown checkpoint, but it shouldn't
* decrease
*/ */
if (checkPoint.ThisTimeLineID != ThisTimeLineID) if (checkPoint.ThisTimeLineID != ThisTimeLineID)
{ {
@ -5071,7 +5098,6 @@ xlog_outrec(char *buf, XLogRecord *record)
sprintf(buf + strlen(buf), ": %s", sprintf(buf + strlen(buf), ": %s",
RmgrTable[record->xl_rmid].rm_name); RmgrTable[record->xl_rmid].rm_name);
} }
#endif /* WAL_DEBUG */ #endif /* WAL_DEBUG */
@ -5215,18 +5241,20 @@ pg_start_backup(PG_FUNCTION_ARGS)
(errmsg("must be superuser to run a backup")))); (errmsg("must be superuser to run a backup"))));
backupidstr = DatumGetCString(DirectFunctionCall1(textout, backupidstr = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(backupid))); PointerGetDatum(backupid)));
/* /*
* Force a CHECKPOINT. This is not strictly necessary, but it seems * Force a CHECKPOINT. This is not strictly necessary, but it seems
* like a good idea to minimize the amount of past WAL needed to use the * like a good idea to minimize the amount of past WAL needed to use
* backup. Also, this guarantees that two successive backup runs * the backup. Also, this guarantees that two successive backup runs
* will have different checkpoint positions and hence different history * will have different checkpoint positions and hence different
* file names, even if nothing happened in between. * history file names, even if nothing happened in between.
*/ */
RequestCheckpoint(true); RequestCheckpoint(true);
/* /*
* Now we need to fetch the checkpoint record location, and also its * Now we need to fetch the checkpoint record location, and also its
* REDO pointer. The oldest point in WAL that would be needed to restore * REDO pointer. The oldest point in WAL that would be needed to
* starting from the checkpoint is precisely the REDO pointer. * restore starting from the checkpoint is precisely the REDO pointer.
*/ */
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
checkpointloc = ControlFile->checkPoint; checkpointloc = ControlFile->checkPoint;
@ -5235,18 +5263,21 @@ pg_start_backup(PG_FUNCTION_ARGS)
XLByteToSeg(startpoint, _logId, _logSeg); XLByteToSeg(startpoint, _logId, _logSeg);
XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
/* /*
* We deliberately use strftime/localtime not the src/timezone functions, * We deliberately use strftime/localtime not the src/timezone
* so that backup labels will consistently be recorded in the same * functions, so that backup labels will consistently be recorded in
* timezone regardless of TimeZone setting. This matches elog.c's * the same timezone regardless of TimeZone setting. This matches
* practice. * elog.c's practice.
*/ */
stamp_time = time(NULL); stamp_time = time(NULL);
strftime(strfbuf, sizeof(strfbuf), strftime(strfbuf, sizeof(strfbuf),
"%Y-%m-%d %H:%M:%S %Z", "%Y-%m-%d %H:%M:%S %Z",
localtime(&stamp_time)); localtime(&stamp_time));
/* /*
* Check for existing backup label --- implies a backup is already running * Check for existing backup label --- implies a backup is already
* running
*/ */
snprintf(labelfilepath, MAXPGPATH, "%s/backup_label", DataDir); snprintf(labelfilepath, MAXPGPATH, "%s/backup_label", DataDir);
if (stat(labelfilepath, &stat_buf) != 0) if (stat(labelfilepath, &stat_buf) != 0)
@ -5263,6 +5294,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
errmsg("a backup is already in progress"), errmsg("a backup is already in progress"),
errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.", errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
labelfilepath))); labelfilepath)));
/* /*
* Okay, write the file * Okay, write the file
*/ */
@ -5283,6 +5315,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not write file \"%s\": %m", errmsg("could not write file \"%s\": %m",
labelfilepath))); labelfilepath)));
/* /*
* We're done. As a convenience, return the starting WAL offset. * We're done. As a convenience, return the starting WAL offset.
*/ */
@ -5325,6 +5358,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to run a backup")))); (errmsg("must be superuser to run a backup"))));
/* /*
* Get the current end-of-WAL position; it will be unsafe to use this * Get the current end-of-WAL position; it will be unsafe to use this
* dump to restore to a point in advance of this time. * dump to restore to a point in advance of this time.
@ -5335,16 +5369,18 @@ pg_stop_backup(PG_FUNCTION_ARGS)
XLByteToSeg(stoppoint, _logId, _logSeg); XLByteToSeg(stoppoint, _logId, _logSeg);
XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg); XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg);
/* /*
* We deliberately use strftime/localtime not the src/timezone functions, * We deliberately use strftime/localtime not the src/timezone
* so that backup labels will consistently be recorded in the same * functions, so that backup labels will consistently be recorded in
* timezone regardless of TimeZone setting. This matches elog.c's * the same timezone regardless of TimeZone setting. This matches
* practice. * elog.c's practice.
*/ */
stamp_time = time(NULL); stamp_time = time(NULL);
strftime(strfbuf, sizeof(strfbuf), strftime(strfbuf, sizeof(strfbuf),
"%Y-%m-%d %H:%M:%S %Z", "%Y-%m-%d %H:%M:%S %Z",
localtime(&stamp_time)); localtime(&stamp_time));
/* /*
* Open the existing label file * Open the existing label file
*/ */
@ -5361,9 +5397,11 @@ pg_stop_backup(PG_FUNCTION_ARGS)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("a backup is not in progress"))); errmsg("a backup is not in progress")));
} }
/* /*
* Read and parse the START WAL LOCATION line (this code is pretty * Read and parse the START WAL LOCATION line (this code is pretty
* crude, but we are not expecting any variability in the file format). * crude, but we are not expecting any variability in the file
* format).
*/ */
if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %24s)%c", if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %24s)%c",
&startpoint.xlogid, &startpoint.xrecoff, startxlogfilename, &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename,
@ -5371,6 +5409,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("invalid data in file \"%s\"", labelfilepath))); errmsg("invalid data in file \"%s\"", labelfilepath)));
/* /*
* Write the backup history file * Write the backup history file
*/ */
@ -5396,6 +5435,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not write file \"%s\": %m", errmsg("could not write file \"%s\": %m",
histfilepath))); histfilepath)));
/* /*
* Close and remove the backup label file * Close and remove the backup label file
*/ */
@ -5409,6 +5449,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not remove file \"%s\": %m", errmsg("could not remove file \"%s\": %m",
labelfilepath))); labelfilepath)));
/* /*
* Notify archiver that history file may be archived immediately * Notify archiver that history file may be archived immediately
*/ */
@ -5418,6 +5459,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
startpoint.xrecoff % XLogSegSize); startpoint.xrecoff % XLogSegSize);
XLogArchiveNotify(histfilepath); XLogArchiveNotify(histfilepath);
} }
/* /*
* We're done. As a convenience, return the ending WAL offset. * We're done. As a convenience, return the ending WAL offset.
*/ */
@ -5476,10 +5518,11 @@ read_backup_label(XLogRecPtr *checkPointLoc)
labelfilepath))); labelfilepath)));
return false; /* it's not there, all is fine */ return false; /* it's not there, all is fine */
} }
/* /*
* Read and parse the START WAL LOCATION and CHECKPOINT lines (this code * Read and parse the START WAL LOCATION and CHECKPOINT lines (this
* is pretty crude, but we are not expecting any variability in the file * code is pretty crude, but we are not expecting any variability in
* format). * the file format).
*/ */
if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c", if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c",
&startpoint.xlogid, &startpoint.xrecoff, &tli, &startpoint.xlogid, &startpoint.xrecoff, &tli,
@ -5498,6 +5541,7 @@ read_backup_label(XLogRecPtr *checkPointLoc)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not read file \"%s\": %m", errmsg("could not read file \"%s\": %m",
labelfilepath))); labelfilepath)));
/* /*
* Try to retrieve the backup history file (no error if we can't) * Try to retrieve the backup history file (no error if we can't)
*/ */

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

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.
@ -128,19 +128,19 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant,
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,14 +157,15 @@ 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,
@ -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)
@ -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)
@ -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;

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.

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);
@ -1623,15 +1627,15 @@ 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;

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);
@ -1206,12 +1207,12 @@ 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.
@ -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
@ -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);

View File

@ -13,7 +13,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/namespace.c,v 1.69 2004/08/29 04:12:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.70 2004/08/29 05:06:41 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -699,12 +699,13 @@ OpernameGetCandidates(List *names, char oprkind)
/* /*
* In typical scenarios, most if not all of the operators found by the * In typical scenarios, most if not all of the operators found by the
* catcache search will end up getting returned; and there can be quite * catcache search will end up getting returned; and there can be
* a few, for common operator names such as '=' or '+'. To reduce the * quite a few, for common operator names such as '=' or '+'. To
* time spent in palloc, we allocate the result space as an array large * reduce the time spent in palloc, we allocate the result space as an
* enough to hold all the operators. The original coding of this routine * array large enough to hold all the operators. The original coding
* did a separate palloc for each operator, but profiling revealed that * of this routine did a separate palloc for each operator, but
* the pallocs used an unreasonably large fraction of parsing time. * profiling revealed that the pallocs used an unreasonably large
* fraction of parsing time.
*/ */
#define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid)) #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
@ -1645,10 +1646,11 @@ InitTempTableNamespace(void)
* tables. We use a nonstandard error message here since * tables. We use a nonstandard error message here since
* "databasename: permission denied" might be a tad cryptic. * "databasename: permission denied" might be a tad cryptic.
* *
* Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask; * Note that ACL_CREATE_TEMP rights are rechecked in
* that's necessary since current user ID could change during the session. * pg_namespace_aclmask; that's necessary since current user ID could
* But there's no need to make the namespace in the first place until a * change during the session. But there's no need to make the
* temp table creation request is made by someone with appropriate rights. * namespace in the first place until a temp table creation request is
* made by someone with appropriate rights.
*/ */
if (pg_database_aclcheck(MyDatabaseId, GetUserId(), if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
ACL_CREATE_TEMP) != ACLCHECK_OK) ACL_CREATE_TEMP) != ACLCHECK_OK)
@ -1847,7 +1849,8 @@ assign_search_path(const char *newval, bool doit, GucSource source)
* ALTER DATABASE SET or ALTER USER SET command. It could be that * ALTER DATABASE SET or ALTER USER SET command. It could be that
* the intended use of the search path is for some other database, * the intended use of the search path is for some other database,
* so we should not error out if it mentions schemas not present * so we should not error out if it mentions schemas not present
* in the current database. We reduce the message to NOTICE instead. * in the current database. We reduce the message to NOTICE
* instead.
*/ */
foreach(l, namelist) foreach(l, namelist)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.67 2004/08/29 04:12:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.68 2004/08/29 05:06:41 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.118 2004/08/29 04:12:29 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.119 2004/08/29 05:06:41 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -329,7 +329,7 @@ create_parameternames_array(int parameterCount, const char *parameterNames[])
if (!parameterNames) if (!parameterNames)
return PointerGetDatum(NULL); return PointerGetDatum(NULL);
for (i=0; i<parameterCount; i++) for (i = 0; i < parameterCount; i++)
{ {
const char *s = parameterNames[i]; const char *s = parameterNames[i];
@ -562,8 +562,9 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
} }
/* /*
* Otherwise assume we are returning the whole tuple. Crosschecking * Otherwise assume we are returning the whole tuple.
* against what the caller expects will happen at runtime. * Crosschecking against what the caller expects will happen at
* runtime.
*/ */
return true; return true;
} }
@ -652,9 +653,10 @@ fmgr_c_validator(PG_FUNCTION_ARGS)
char *probin; char *probin;
/* /*
* It'd be most consistent to skip the check if !check_function_bodies, * It'd be most consistent to skip the check if
* but the purpose of that switch is to be helpful for pg_dump loading, * !check_function_bodies, but the purpose of that switch is to be
* and for pg_dump loading it's much better if we *do* check. * helpful for pg_dump loading, and for pg_dump loading it's much
* better if we *do* check.
*/ */
tuple = SearchSysCache(PROCOID, tuple = SearchSysCache(PROCOID,
@ -760,10 +762,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
error_context_stack = &sqlerrcontext; error_context_stack = &sqlerrcontext;
/* /*
* We can't do full prechecking of the function definition if there * We can't do full prechecking of the function definition if
* are any polymorphic input types, because actual datatypes of * there are any polymorphic input types, because actual datatypes
* expression results will be unresolvable. The check will be done * of expression results will be unresolvable. The check will be
* at runtime instead. * done at runtime instead.
* *
* We can run the text through the raw parser though; this will at * We can run the text through the raw parser though; this will at
* least catch silly syntactic errors. * least catch silly syntactic errors.
@ -832,11 +834,11 @@ function_parse_error_transpose(const char *prosrc)
const char *queryText; const char *queryText;
/* /*
* Nothing to do unless we are dealing with a syntax error that has * Nothing to do unless we are dealing with a syntax error that has a
* a cursor position. * cursor position.
* *
* Some PLs may prefer to report the error position as an internal * Some PLs may prefer to report the error position as an internal error
* error to begin with, so check that too. * to begin with, so check that too.
*/ */
origerrposition = geterrposition(); origerrposition = geterrposition();
if (origerrposition <= 0) if (origerrposition <= 0)
@ -897,11 +899,11 @@ match_prosrc_to_query(const char *prosrc, const char *queryText,
int curpos; int curpos;
int newcursorpos; int newcursorpos;
for (curpos = 0; curpos < querylen-prosrclen; curpos++) for (curpos = 0; curpos < querylen - prosrclen; curpos++)
{ {
if (queryText[curpos] == '$' && if (queryText[curpos] == '$' &&
strncmp(prosrc, &queryText[curpos+1], prosrclen) == 0 && strncmp(prosrc, &queryText[curpos + 1], prosrclen) == 0 &&
queryText[curpos+1+prosrclen] == '$') queryText[curpos + 1 + prosrclen] == '$')
{ {
/* /*
* Found a $foo$ match. Since there are no embedded quoting * Found a $foo$ match. Since there are no embedded quoting
@ -910,20 +912,21 @@ match_prosrc_to_query(const char *prosrc, const char *queryText,
*/ */
if (matchpos) if (matchpos)
return 0; /* multiple matches, fail */ return 0; /* multiple matches, fail */
matchpos = pg_mbstrlen_with_len(queryText, curpos+1) matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
+ cursorpos; + cursorpos;
} }
else if (queryText[curpos] == '\'' && else if (queryText[curpos] == '\'' &&
match_prosrc_to_literal(prosrc, &queryText[curpos+1], match_prosrc_to_literal(prosrc, &queryText[curpos + 1],
cursorpos, &newcursorpos)) cursorpos, &newcursorpos))
{ {
/* /*
* Found a 'foo' match. match_prosrc_to_literal() has adjusted * Found a 'foo' match. match_prosrc_to_literal() has
* for any quotes or backslashes embedded in the literal. * adjusted for any quotes or backslashes embedded in the
* literal.
*/ */
if (matchpos) if (matchpos)
return 0; /* multiple matches, fail */ return 0; /* multiple matches, fail */
matchpos = pg_mbstrlen_with_len(queryText, curpos+1) matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
+ newcursorpos; + newcursorpos;
} }
} }
@ -951,12 +954,13 @@ match_prosrc_to_literal(const char *prosrc, const char *literal,
* string literal. It does not handle the SQL syntax for literals * string literal. It does not handle the SQL syntax for literals
* continued across line boundaries. * continued across line boundaries.
* *
* We do the comparison a character at a time, not a byte at a time, * We do the comparison a character at a time, not a byte at a time, so
* so that we can do the correct cursorpos math. * that we can do the correct cursorpos math.
*/ */
while (*prosrc) while (*prosrc)
{ {
cursorpos--; /* characters left before cursor */ cursorpos--; /* characters left before cursor */
/* /*
* Check for backslashes and doubled quotes in the literal; adjust * Check for backslashes and doubled quotes in the literal; adjust
* newcp when one is found before the cursor. * newcp when one is found before the cursor.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.95 2004/08/29 04:12:29 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.96 2004/08/29 05:06:41 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.20 2004/08/29 04:12:29 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.21 2004/08/29 05:06:41 momjian Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -223,9 +223,9 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
/* /*
* if a basetype is passed in, then attempt to find an aggregate for * if a basetype is passed in, then attempt to find an aggregate for
* that specific type; else attempt to find an aggregate with a basetype * that specific type; else attempt to find an aggregate with a
* of ANYOID. This means that the aggregate applies to all basetypes * basetype of ANYOID. This means that the aggregate applies to all
* (eg, COUNT). * basetypes (eg, COUNT).
*/ */
if (basetype) if (basetype)
basetypeOid = typenameTypeId(basetype); basetypeOid = typenameTypeId(basetype);
@ -302,9 +302,9 @@ AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
/* /*
* if a basetype is passed in, then attempt to find an aggregate for * if a basetype is passed in, then attempt to find an aggregate for
* that specific type; else attempt to find an aggregate with a basetype * that specific type; else attempt to find an aggregate with a
* of ANYOID. This means that the aggregate applies to all basetypes * basetype of ANYOID. This means that the aggregate applies to all
* (eg, COUNT). * basetypes (eg, COUNT).
*/ */
if (basetype) if (basetype)
basetypeOid = typenameTypeId(basetype); basetypeOid = typenameTypeId(basetype);
@ -334,7 +334,10 @@ AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change owner"))); errmsg("must be superuser to change owner")));
/* Modify the owner --- okay to scribble on tup because it's a copy */ /*
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
procForm->proowner = newOwnerSysId; procForm->proowner = newOwnerSysId;
simple_heap_update(rel, &tup->t_self, tup); simple_heap_update(rel, &tup->t_self, tup);

Some files were not shown because too many files have changed in this diff Show More