pgindent run. Make it all clean.

This commit is contained in:
Bruce Momjian 2001-03-22 04:01:46 +00:00
parent 6cf8707b82
commit 9e1552607a
555 changed files with 32514 additions and 28110 deletions

View File

@ -20,30 +20,32 @@ unsigned int parse_buffer_pos( void );
extern void cube_flush_scanner_buffer(void); /* defined in cubescan.l */ extern void cube_flush_scanner_buffer(void); /* defined in cubescan.l */
void set_parse_buffer( char* s ) void
set_parse_buffer(char *s)
{ {
PARSE_BUFFER = s; PARSE_BUFFER = s;
PARSE_BUFFER_SIZE = strlen(s); PARSE_BUFFER_SIZE = strlen(s);
if ( PARSE_BUFFER_SIZE == 0 ) { if (PARSE_BUFFER_SIZE == 0)
elog(ERROR, "cube_in: can't parse an empty string"); elog(ERROR, "cube_in: can't parse an empty string");
}
PARSE_BUFFER_PTR = PARSE_BUFFER; PARSE_BUFFER_PTR = PARSE_BUFFER;
SCANNER_POS = 0; SCANNER_POS = 0;
} }
void reset_parse_buffer( void ) void
reset_parse_buffer(void)
{ {
PARSE_BUFFER_PTR = PARSE_BUFFER; PARSE_BUFFER_PTR = PARSE_BUFFER;
SCANNER_POS = 0; SCANNER_POS = 0;
cube_flush_scanner_buffer(); cube_flush_scanner_buffer();
} }
int read_parse_buffer( void ) int
read_parse_buffer(void)
{ {
int c; int c;
/* /*
c = *PARSE_BUFFER_PTR++; * c = *PARSE_BUFFER_PTR++; SCANNER_POS++;
SCANNER_POS++;
*/ */
c = PARSE_BUFFER[SCANNER_POS]; c = PARSE_BUFFER[SCANNER_POS];
if (SCANNER_POS < PARSE_BUFFER_SIZE) if (SCANNER_POS < PARSE_BUFFER_SIZE)
@ -51,29 +53,32 @@ int read_parse_buffer( void )
return c; return c;
} }
char * parse_buffer( void ) char *
parse_buffer(void)
{ {
return PARSE_BUFFER; return PARSE_BUFFER;
} }
unsigned int parse_buffer_curr_char( void ) unsigned int
parse_buffer_curr_char(void)
{ {
return PARSE_BUFFER[SCANNER_POS]; return PARSE_BUFFER[SCANNER_POS];
} }
char * parse_buffer_ptr( void ) char *
parse_buffer_ptr(void)
{ {
return PARSE_BUFFER_PTR; return PARSE_BUFFER_PTR;
} }
unsigned int parse_buffer_pos( void ) unsigned int
parse_buffer_pos(void)
{ {
return SCANNER_POS; return SCANNER_POS;
} }
unsigned int parse_buffer_size( void ) unsigned int
parse_buffer_size(void)
{ {
return PARSE_BUFFER_SIZE; return PARSE_BUFFER_SIZE;
} }

View File

@ -92,9 +92,8 @@ cube_in(char *str)
set_parse_buffer(str); set_parse_buffer(str);
if ( cube_yyparse(&result) != 0 ) { if (cube_yyparse(&result) != 0)
return NULL; return NULL;
}
return ((NDBOX *) result); return ((NDBOX *) result);
} }
@ -121,22 +120,26 @@ cube_out(NDBOX *cube)
p = result = (char *) palloc(100); p = result = (char *) palloc(100);
/* while printing the first (LL) corner, check if it is equal /*
to the scond one */ * while printing the first (LL) corner, check if it is equal to the
* scond one
*/
p += sprintf(p, "("); p += sprintf(p, "(");
for ( i=0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
p += sprintf(p, "%g", cube->x[i]); p += sprintf(p, "%g", cube->x[i]);
p += sprintf(p, ", "); p += sprintf(p, ", ");
if ( cube->x[i] != cube->x[i+dim] ) { if (cube->x[i] != cube->x[i + dim])
equal = 0; equal = 0;
} }
}
p -= 2; /* get rid of the last ", " */ p -= 2; /* get rid of the last ", " */
p += sprintf(p, ")"); p += sprintf(p, ")");
if ( !equal ) { if (!equal)
{
p += sprintf(p, ",("); p += sprintf(p, ",(");
for ( i=dim; i < dim * 2; i++ ) { for (i = dim; i < dim * 2; i++)
{
p += sprintf(p, "%g", cube->x[i]); p += sprintf(p, "%g", cube->x[i]);
p += sprintf(p, ", "); p += sprintf(p, ", ");
} }
@ -163,9 +166,10 @@ g_cube_consistent(GISTENTRY *entry,
NDBOX * query, NDBOX * query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
/* /*
** if entry is not leaf, use g_cube_internal_consistent, * * if entry is not leaf, use g_cube_internal_consistent, * else use
** else use g_cube_leaf_consistent * g_cube_leaf_consistent
*/ */
if (GIST_LEAF(entry)) if (GIST_LEAF(entry))
return (g_cube_leaf_consistent((NDBOX *) (entry->pred), query, strategy)); return (g_cube_leaf_consistent((NDBOX *) (entry->pred), query, strategy));
@ -181,28 +185,35 @@ g_cube_consistent(GISTENTRY *entry,
NDBOX * NDBOX *
g_cube_union(bytea *entryvec, int *sizep) g_cube_union(bytea *entryvec, int *sizep)
{ {
int numranges, i; int numranges,
i;
NDBOX *out = (NDBOX *) NULL; NDBOX *out = (NDBOX *) NULL;
NDBOX *tmp; NDBOX *tmp;
/* /*
fprintf(stderr, "union\n"); * fprintf(stderr, "union\n");
*/ */
numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
tmp = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[0]).pred; tmp = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[0]).pred;
/* /*
* sizep = sizeof(NDBOX); -- NDBOX has variable size * sizep = sizeof(NDBOX); -- NDBOX has variable size
*/ */
*sizep = tmp->size; *sizep = tmp->size;
for (i = 1; i < numranges; i++) { for (i = 1; i < numranges; i++)
{
out = g_cube_binary_union(tmp, (NDBOX *) out = g_cube_binary_union(tmp, (NDBOX *)
(((GISTENTRY *) (VARDATA(entryvec)))[i]).pred, (((GISTENTRY *) (VARDATA(entryvec)))[i]).pred,
sizep); sizep);
/* /*
fprintf(stderr, "\t%s ^ %s -> %s\n", cube_out(tmp), cube_out((NDBOX *)(((GISTENTRY *)(VARDATA(entryvec)))[i]).pred), cube_out(out)); * fprintf(stderr, "\t%s ^ %s -> %s\n", cube_out(tmp),
* cube_out((NDBOX *)(((GISTENTRY
* *)(VARDATA(entryvec)))[i]).pred), cube_out(out));
*/ */
if (i > 1) pfree(tmp); if (i > 1)
pfree(tmp);
tmp = out; tmp = out;
} }
@ -233,16 +244,17 @@ float *
g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result) g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
{ {
Datum ud; Datum ud;
float tmp1, tmp2; float tmp1,
tmp2;
ud = (Datum) cube_union((NDBOX *) (origentry->pred), (NDBOX *) (newentry->pred)); ud = (Datum) cube_union((NDBOX *) (origentry->pred), (NDBOX *) (newentry->pred));
rt_cube_size((NDBOX *) ud, &tmp1); rt_cube_size((NDBOX *) ud, &tmp1);
rt_cube_size((NDBOX *) (origentry->pred), &tmp2); rt_cube_size((NDBOX *) (origentry->pred), &tmp2);
*result = tmp1 - tmp2; *result = tmp1 - tmp2;
pfree((char *) ud); pfree((char *) ud);
/* /*
fprintf(stderr, "penalty\n"); * fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
fprintf(stderr, "\t%g\n", *result);
*/ */
return (result); return (result);
} }
@ -257,22 +269,34 @@ GIST_SPLITVEC *
g_cube_picksplit(bytea *entryvec, g_cube_picksplit(bytea *entryvec,
GIST_SPLITVEC *v) GIST_SPLITVEC *v)
{ {
OffsetNumber i, j; OffsetNumber i,
NDBOX *datum_alpha, *datum_beta; j;
NDBOX *datum_l, *datum_r; NDBOX *datum_alpha,
NDBOX *union_d, *union_dl, *union_dr; *datum_beta;
NDBOX *datum_l,
*datum_r;
NDBOX *union_d,
*union_dl,
*union_dr;
NDBOX *inter_d; NDBOX *inter_d;
bool firsttime; bool firsttime;
float size_alpha, size_beta, size_union, size_inter; float size_alpha,
float size_waste, waste; size_beta,
float size_l, size_r; size_union,
size_inter;
float size_waste,
waste;
float size_l,
size_r;
int nbytes; int nbytes;
OffsetNumber seed_1 = 0, seed_2 = 0; OffsetNumber seed_1 = 0,
OffsetNumber *left, *right; seed_2 = 0;
OffsetNumber *left,
*right;
OffsetNumber maxoff; OffsetNumber maxoff;
/* /*
fprintf(stderr, "picksplit\n"); * fprintf(stderr, "picksplit\n");
*/ */
maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 2; maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 2;
nbytes = (maxoff + 2) * sizeof(OffsetNumber); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
@ -282,9 +306,11 @@ g_cube_picksplit(bytea *entryvec,
firsttime = true; firsttime = true;
waste = 0.0; waste = 0.0;
for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
{
datum_alpha = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[i].pred); datum_alpha = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[i].pred);
for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) { for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
{
datum_beta = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[j].pred); datum_beta = (NDBOX *) (((GISTENTRY *) (VARDATA(entryvec)))[j].pred);
/* compute the wasted space by unioning these guys */ /* compute the wasted space by unioning these guys */
@ -301,11 +327,12 @@ g_cube_picksplit(bytea *entryvec,
pfree(inter_d); pfree(inter_d);
/* /*
* are these a more promising split than what we've * are these a more promising split than what we've already
* already seen? * seen?
*/ */
if (size_waste > waste || firsttime) { if (size_waste > waste || firsttime)
{
waste = size_waste; waste = size_waste;
seed_1 = i; seed_1 = i;
seed_2 = j; seed_2 = j;
@ -328,31 +355,34 @@ g_cube_picksplit(bytea *entryvec,
/* /*
* Now split up the regions between the two seeds. An important * Now split up the regions between the two seeds. An important
* property of this split algorithm is that the split vector v * property of this split algorithm is that the split vector v has the
* has the indices of items to be split in order in its left and * indices of items to be split in order in its left and right
* right vectors. We exploit this property by doing a merge in * vectors. We exploit this property by doing a merge in the code
* the code that actually splits the page. * that actually splits the page.
* *
* For efficiency, we also place the new index tuple in this loop. * For efficiency, we also place the new index tuple in this loop. This
* This is handled at the very end, when we have placed all the * is handled at the very end, when we have placed all the existing
* existing tuples and i == maxoff + 1. * tuples and i == maxoff + 1.
*/ */
maxoff = OffsetNumberNext(maxoff); maxoff = OffsetNumberNext(maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
/* /*
* If we've already decided where to place this item, just * If we've already decided where to place this item, just put it
* put it on the right list. Otherwise, we need to figure * on the right list. Otherwise, we need to figure out which page
* out which page needs the least enlargement in order to * needs the least enlargement in order to store the item.
* store the item.
*/ */
if (i == seed_1) { if (i == seed_1)
{
*left++ = i; *left++ = i;
v->spl_nleft++; v->spl_nleft++;
continue; continue;
} else if (i == seed_2) { }
else if (i == seed_2)
{
*right++ = i; *right++ = i;
v->spl_nright++; v->spl_nright++;
continue; continue;
@ -366,14 +396,17 @@ g_cube_picksplit(bytea *entryvec,
rt_cube_size((NDBOX *) union_dr, &size_beta); rt_cube_size((NDBOX *) union_dr, &size_beta);
/* pick which page to add it to */ /* pick which page to add it to */
if (size_alpha - size_l < size_beta - size_r) { if (size_alpha - size_l < size_beta - size_r)
{
pfree(datum_l); pfree(datum_l);
pfree(union_dr); pfree(union_dr);
datum_l = union_dl; datum_l = union_dl;
size_l = size_alpha; size_l = size_alpha;
*left++ = i; *left++ = i;
v->spl_nleft++; v->spl_nleft++;
} else { }
else
{
pfree(datum_r); pfree(datum_r);
pfree(union_dl); pfree(union_dl);
datum_r = union_dr; datum_r = union_dr;
@ -398,9 +431,11 @@ g_cube_same(NDBOX *b1, NDBOX *b2, bool *result)
{ {
if (cube_same(b1, b2)) if (cube_same(b1, b2))
*result = TRUE; *result = TRUE;
else *result = FALSE; else
*result = FALSE;
/* /*
fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" )); * fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
*/ */
return (result); return (result);
} }
@ -416,9 +451,10 @@ g_cube_leaf_consistent(NDBOX *key,
bool retval; bool retval;
/* /*
fprintf(stderr, "leaf_consistent, %d\n", strategy); * fprintf(stderr, "leaf_consistent, %d\n", strategy);
*/ */
switch(strategy) { switch (strategy)
{
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
retval = (bool) cube_left(key, query); retval = (bool) cube_left(key, query);
break; break;
@ -457,9 +493,10 @@ g_cube_internal_consistent(NDBOX *key,
bool retval; bool retval;
/* /*
fprintf(stderr, "internal_consistent, %d\n", strategy); * fprintf(stderr, "internal_consistent, %d\n", strategy);
*/ */
switch(strategy) { switch (strategy)
{
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
case RTOverLeftStrategyNumber: case RTOverLeftStrategyNumber:
retval = (bool) cube_over_left(key, query); retval = (bool) cube_over_left(key, query);
@ -497,47 +534,56 @@ g_cube_binary_union(NDBOX *r1, NDBOX *r2, int *sizep)
/* cube_union */ /* cube_union */
NDBOX *cube_union(NDBOX *box_a, NDBOX *box_b) NDBOX *
cube_union(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
NDBOX *result; NDBOX *result;
NDBOX *a = swap_corners(box_a); NDBOX *a = swap_corners(box_a);
NDBOX *b = swap_corners(box_b); NDBOX *b = swap_corners(box_b);
if ( a->dim >= b->dim ) { if (a->dim >= b->dim)
{
result = palloc(a->size); result = palloc(a->size);
result->size = a->size; result->size = a->size;
result->dim = a->dim; result->dim = a->dim;
} }
else { else
{
result = palloc(b->size); result = palloc(b->size);
result->size = b->size; result->size = b->size;
result->dim = b->dim; result->dim = b->dim;
} }
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if ( a->dim < b->dim ) { if (a->dim < b->dim)
NDBOX * tmp = b; b = a; a = tmp; {
NDBOX *tmp = b;
b = a;
a = tmp;
} }
/* use the potentially smaller of the two boxes (b) to fill in /*
the result, padding absent dimensions with zeroes*/ * use the potentially smaller of the two boxes (b) to fill in the
for ( i = 0; i < b->dim; i++ ) { * result, padding absent dimensions with zeroes
*/
for (i = 0; i < b->dim; i++)
{
result->x[i] = b->x[i]; result->x[i] = b->x[i];
result->x[i + a->dim] = b->x[i + b->dim]; result->x[i + a->dim] = b->x[i + b->dim];
} }
for ( i = b->dim; i < a->dim; i++ ) { for (i = b->dim; i < a->dim; i++)
{
result->x[i] = 0; result->x[i] = 0;
result->x[i + a->dim] = 0; result->x[i + a->dim] = 0;
} }
/* compute the union */ /* compute the union */
for ( i = 0; i < a->dim; i++ ) { for (i = 0; i < a->dim; i++)
result->x[i] = min(a->x[i], result->x[i]); result->x[i] = min(a->x[i], result->x[i]);
} for (i = a->dim; i < a->dim * 2; i++)
for ( i = a->dim; i < a->dim * 2; i++ ) {
result->x[i] = max(a->x[i], result->x[i]); result->x[i] = max(a->x[i], result->x[i]);
}
pfree(a); pfree(a);
pfree(b); pfree(b);
@ -546,67 +592,80 @@ NDBOX *cube_union(NDBOX *box_a, NDBOX *box_b)
} }
/* cube_inter */ /* cube_inter */
NDBOX *cube_inter(NDBOX *box_a, NDBOX *box_b) NDBOX *
cube_inter(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
NDBOX *result; NDBOX *result;
NDBOX *a = swap_corners(box_a); NDBOX *a = swap_corners(box_a);
NDBOX *b = swap_corners(box_b); NDBOX *b = swap_corners(box_b);
if ( a->dim >= b->dim ) { if (a->dim >= b->dim)
{
result = palloc(a->size); result = palloc(a->size);
result->size = a->size; result->size = a->size;
result->dim = a->dim; result->dim = a->dim;
} }
else { else
{
result = palloc(b->size); result = palloc(b->size);
result->size = b->size; result->size = b->size;
result->dim = b->dim; result->dim = b->dim;
} }
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if ( a->dim < b->dim ) { if (a->dim < b->dim)
NDBOX * tmp = b; b = a; a = tmp; {
NDBOX *tmp = b;
b = a;
a = tmp;
} }
/* use the potentially smaller of the two boxes (b) to fill in /*
the result, padding absent dimensions with zeroes*/ * use the potentially smaller of the two boxes (b) to fill in the
for ( i = 0; i < b->dim; i++ ) { * result, padding absent dimensions with zeroes
*/
for (i = 0; i < b->dim; i++)
{
result->x[i] = b->x[i]; result->x[i] = b->x[i];
result->x[i + a->dim] = b->x[i + b->dim]; result->x[i + a->dim] = b->x[i + b->dim];
} }
for ( i = b->dim; i < a->dim; i++ ) { for (i = b->dim; i < a->dim; i++)
{
result->x[i] = 0; result->x[i] = 0;
result->x[i + a->dim] = 0; result->x[i + a->dim] = 0;
} }
/* compute the intersection */ /* compute the intersection */
for ( i = 0; i < a->dim; i++ ) { for (i = 0; i < a->dim; i++)
result->x[i] = max(a->x[i], result->x[i]); result->x[i] = max(a->x[i], result->x[i]);
} for (i = a->dim; i < a->dim * 2; i++)
for ( i = a->dim; i < a->dim * 2; i++ ) {
result->x[i] = min(a->x[i], result->x[i]); result->x[i] = min(a->x[i], result->x[i]);
}
pfree(a); pfree(a);
pfree(b); pfree(b);
/* Is it OK to return a non-null intersection for non-overlapping boxes? */ /*
* Is it OK to return a non-null intersection for non-overlapping
* boxes?
*/
return (result); return (result);
} }
/* cube_size */ /* cube_size */
float *cube_size(NDBOX *a) float *
cube_size(NDBOX * a)
{ {
int i,j; int i,
j;
float *result; float *result;
result = (float *) palloc(sizeof(float)); result = (float *) palloc(sizeof(float));
*result = 1.0; *result = 1.0;
for ( i = 0, j = a->dim; i < a->dim; i++,j++ ) { for (i = 0, j = a->dim; i < a->dim; i++, j++)
*result = (*result) * abs((a->x[j] - a->x[i])); *result = (*result) * abs((a->x[j] - a->x[i]));
}
return (result); return (result);
} }
@ -614,15 +673,17 @@ float *cube_size(NDBOX *a)
void void
rt_cube_size(NDBOX * a, float *size) rt_cube_size(NDBOX * a, float *size)
{ {
int i,j; int i,
j;
if (a == (NDBOX *) NULL) if (a == (NDBOX *) NULL)
*size = 0.0; *size = 0.0;
else { else
{
*size = 1.0; *size = 1.0;
for ( i = 0, j = a->dim; i < a->dim; i++,j++ ) { for (i = 0, j = a->dim; i < a->dim; i++, j++)
*size = (*size) * abs((a->x[j] - a->x[i])); *size = (*size) * abs((a->x[j] - a->x[i]));
} }
}
return; return;
} }
@ -633,7 +694,8 @@ rt_cube_size(NDBOX *a, float *size)
/* is the right edge of (a) located to the left of /* is the right edge of (a) located to the left of
the right edge of (b)? */ the right edge of (b)? */
bool cube_over_left(NDBOX *box_a, NDBOX *box_b) bool
cube_over_left(NDBOX * box_a, NDBOX * box_b)
{ {
NDBOX *a; NDBOX *a;
NDBOX *b; NDBOX *b;
@ -649,7 +711,8 @@ bool cube_over_left(NDBOX *box_a, NDBOX *box_b)
/* is the left edge of (a) located to the right of /* is the left edge of (a) located to the right of
the left edge of (b)? */ the left edge of (b)? */
bool cube_over_right(NDBOX *box_a, NDBOX *box_b) bool
cube_over_right(NDBOX * box_a, NDBOX * box_b)
{ {
NDBOX *a; NDBOX *a;
NDBOX *b; NDBOX *b;
@ -666,7 +729,8 @@ bool cube_over_right(NDBOX *box_a, NDBOX *box_b)
/* return 'true' if the projection of 'a' is /* return 'true' if the projection of 'a' is
entirely on the left of the projection of 'b' */ entirely on the left of the projection of 'b' */
bool cube_left(NDBOX *box_a, NDBOX *box_b) bool
cube_left(NDBOX * box_a, NDBOX * box_b)
{ {
NDBOX *a; NDBOX *a;
NDBOX *b; NDBOX *b;
@ -682,7 +746,8 @@ bool cube_left(NDBOX *box_a, NDBOX *box_b)
/* return 'true' if the projection of 'a' is /* return 'true' if the projection of 'a' is
entirely on the right of the projection of 'b' */ entirely on the right of the projection of 'b' */
bool cube_right(NDBOX *box_a, NDBOX *box_b) bool
cube_right(NDBOX * box_a, NDBOX * box_b)
{ {
NDBOX *a; NDBOX *a;
NDBOX *b; NDBOX *b;
@ -698,7 +763,8 @@ bool cube_right(NDBOX *box_a, NDBOX *box_b)
/* make up a metric in which one box will be 'lower' than the other /* make up a metric in which one box will be 'lower' than the other
-- this can be useful for srting and to determine uniqueness */ -- this can be useful for srting and to determine uniqueness */
bool cube_lt(NDBOX *box_a, NDBOX *box_b) bool
cube_lt(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
int dim; int dim;
@ -712,24 +778,28 @@ bool cube_lt(NDBOX *box_a, NDBOX *box_b)
b = swap_corners(box_b); b = swap_corners(box_b);
dim = min(a->dim, b->dim); dim = min(a->dim, b->dim);
/* if all common dimensions are equal, the cube with more dimensions wins */ /*
if ( cube_same(a, b) ) { * if all common dimensions are equal, the cube with more dimensions
if (a->dim < b->dim) { * wins
*/
if (cube_same(a, b))
{
if (a->dim < b->dim)
return (TRUE); return (TRUE);
} else
else {
return (FALSE); return (FALSE);
} }
}
/* compare the common dimensions */ /* compare the common dimensions */
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i] > b->x[i]) if (a->x[i] > b->x[i])
return (FALSE); return (FALSE);
if (a->x[i] < b->x[i]) if (a->x[i] < b->x[i])
return (TRUE); return (TRUE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i + a->dim] > b->x[i + b->dim]) if (a->x[i + a->dim] > b->x[i + b->dim])
return (FALSE); return (FALSE);
if (a->x[i + a->dim] < b->x[i + b->dim]) if (a->x[i + a->dim] < b->x[i + b->dim])
@ -737,28 +807,34 @@ bool cube_lt(NDBOX *box_a, NDBOX *box_b)
} }
/* compare extra dimensions to zero */ /* compare extra dimensions to zero */
if ( a->dim > b->dim ) { if (a->dim > b->dim)
for ( i = dim; i < a->dim; i++ ) { {
for (i = dim; i < a->dim; i++)
{
if (a->x[i] > 0) if (a->x[i] > 0)
return (FALSE); return (FALSE);
if (a->x[i] < 0) if (a->x[i] < 0)
return (TRUE); return (TRUE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i + a->dim] > 0) if (a->x[i + a->dim] > 0)
return (FALSE); return (FALSE);
if (a->x[i + a->dim] < 0) if (a->x[i + a->dim] < 0)
return (TRUE); return (TRUE);
} }
} }
if ( a->dim < b->dim ) { if (a->dim < b->dim)
for ( i = dim; i < b->dim; i++ ) { {
for (i = dim; i < b->dim; i++)
{
if (b->x[i] > 0) if (b->x[i] > 0)
return (TRUE); return (TRUE);
if (b->x[i] < 0) if (b->x[i] < 0)
return (FALSE); return (FALSE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (b->x[i + b->dim] > 0) if (b->x[i + b->dim] > 0)
return (TRUE); return (TRUE);
if (b->x[i + b->dim] < 0) if (b->x[i + b->dim] < 0)
@ -770,7 +846,8 @@ bool cube_lt(NDBOX *box_a, NDBOX *box_b)
} }
bool cube_gt(NDBOX *box_a, NDBOX *box_b) bool
cube_gt(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
int dim; int dim;
@ -784,24 +861,28 @@ bool cube_gt(NDBOX *box_a, NDBOX *box_b)
b = swap_corners(box_b); b = swap_corners(box_b);
dim = min(a->dim, b->dim); dim = min(a->dim, b->dim);
/* if all common dimensions are equal, the cube with more dimensions wins */ /*
if ( cube_same(a, b) ) { * if all common dimensions are equal, the cube with more dimensions
if (a->dim > b->dim) { * wins
*/
if (cube_same(a, b))
{
if (a->dim > b->dim)
return (TRUE); return (TRUE);
} else
else {
return (FALSE); return (FALSE);
} }
}
/* compare the common dimensions */ /* compare the common dimensions */
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i] < b->x[i]) if (a->x[i] < b->x[i])
return (FALSE); return (FALSE);
if (a->x[i] > b->x[i]) if (a->x[i] > b->x[i])
return (TRUE); return (TRUE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i + a->dim] < b->x[i + b->dim]) if (a->x[i + a->dim] < b->x[i + b->dim])
return (FALSE); return (FALSE);
if (a->x[i + a->dim] > b->x[i + b->dim]) if (a->x[i + a->dim] > b->x[i + b->dim])
@ -810,28 +891,34 @@ bool cube_gt(NDBOX *box_a, NDBOX *box_b)
/* compare extra dimensions to zero */ /* compare extra dimensions to zero */
if ( a->dim > b->dim ) { if (a->dim > b->dim)
for ( i = dim; i < a->dim; i++ ) { {
for (i = dim; i < a->dim; i++)
{
if (a->x[i] < 0) if (a->x[i] < 0)
return (FALSE); return (FALSE);
if (a->x[i] > 0) if (a->x[i] > 0)
return (TRUE); return (TRUE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (a->x[i + a->dim] < 0) if (a->x[i + a->dim] < 0)
return (FALSE); return (FALSE);
if (a->x[i + a->dim] > 0) if (a->x[i + a->dim] > 0)
return (TRUE); return (TRUE);
} }
} }
if ( a->dim < b->dim ) { if (a->dim < b->dim)
for ( i = dim; i < b->dim; i++ ) { {
for (i = dim; i < b->dim; i++)
{
if (b->x[i] < 0) if (b->x[i] < 0)
return (TRUE); return (TRUE);
if (b->x[i] > 0) if (b->x[i] > 0)
return (FALSE); return (FALSE);
} }
for ( i = 0; i < dim; i++ ) { for (i = 0; i < dim; i++)
{
if (b->x[i + b->dim] < 0) if (b->x[i + b->dim] < 0)
return (TRUE); return (TRUE);
if (b->x[i + b->dim] > 0) if (b->x[i + b->dim] > 0)
@ -844,7 +931,8 @@ bool cube_gt(NDBOX *box_a, NDBOX *box_b)
/* Equal */ /* Equal */
bool cube_same(NDBOX *box_a, NDBOX *box_b) bool
cube_same(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
NDBOX *a; NDBOX *a;
@ -857,20 +945,28 @@ bool cube_same(NDBOX *box_a, NDBOX *box_b)
b = swap_corners(box_b); b = swap_corners(box_b);
/* swap the box pointers if necessary */ /* swap the box pointers if necessary */
if ( a->dim < b->dim ) { if (a->dim < b->dim)
NDBOX * tmp = b; b = a; a = tmp; {
NDBOX *tmp = b;
b = a;
a = tmp;
} }
for ( i = 0; i < b->dim; i++ ) { for (i = 0; i < b->dim; i++)
{
if (a->x[i] != b->x[i]) if (a->x[i] != b->x[i])
return (FALSE); return (FALSE);
if (a->x[i + a->dim] != b->x[i + b->dim]) if (a->x[i + a->dim] != b->x[i + b->dim])
return (FALSE); return (FALSE);
} }
/* all dimensions of (b) are compared to those of (a); /*
instead of those in (a) absent in (b), compare (a) to zero */ * all dimensions of (b) are compared to those of (a); instead of
for ( i = b->dim; i < a->dim; i++ ) { * those in (a) absent in (b), compare (a) to zero
*/
for (i = b->dim; i < a->dim; i++)
{
if (a->x[i] != 0) if (a->x[i] != 0)
return (FALSE); return (FALSE);
if (a->x[i + a->dim] != 0) if (a->x[i + a->dim] != 0)
@ -884,7 +980,8 @@ bool cube_same(NDBOX *box_a, NDBOX *box_b)
} }
/* Different */ /* Different */
bool cube_different(NDBOX *box_a, NDBOX *box_b) bool
cube_different(NDBOX * box_a, NDBOX * box_b)
{ {
return (!cube_same(box_a, box_b)); return (!cube_same(box_a, box_b));
} }
@ -892,7 +989,8 @@ bool cube_different(NDBOX *box_a, NDBOX *box_b)
/* Contains */ /* Contains */
/* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */ /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
bool cube_contains(NDBOX *box_a, NDBOX *box_b) bool
cube_contains(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
NDBOX *a; NDBOX *a;
@ -904,10 +1002,15 @@ bool cube_contains(NDBOX *box_a, NDBOX *box_b)
a = swap_corners(box_a); a = swap_corners(box_a);
b = swap_corners(box_b); b = swap_corners(box_b);
if ( a->dim < b->dim ) { if (a->dim < b->dim)
/* the further comparisons will make sense if the {
excess dimensions of (b) were zeroes */
for ( i = a->dim; i < b->dim; i++ ) { /*
* the further comparisons will make sense if the excess
* dimensions of (b) were zeroes
*/
for (i = a->dim; i < b->dim; i++)
{
if (b->x[i] != 0) if (b->x[i] != 0)
return (FALSE); return (FALSE);
if (b->x[i + b->dim] != 0) if (b->x[i + b->dim] != 0)
@ -916,7 +1019,8 @@ bool cube_contains(NDBOX *box_a, NDBOX *box_b)
} }
/* Can't care less about the excess dimensions of (a), if any */ /* Can't care less about the excess dimensions of (a), if any */
for ( i = 0; i < min(a->dim, b->dim); i++ ) { for (i = 0; i < min(a->dim, b->dim); i++)
{
if (a->x[i] > b->x[i]) if (a->x[i] > b->x[i])
return (FALSE); return (FALSE);
if (a->x[i + a->dim] < b->x[i + b->dim]) if (a->x[i + a->dim] < b->x[i + b->dim])
@ -931,7 +1035,8 @@ bool cube_contains(NDBOX *box_a, NDBOX *box_b)
/* Contained */ /* Contained */
/* Box(A) Contained by Box(B) IFF Box(B) Contains Box(A) */ /* Box(A) Contained by Box(B) IFF Box(B) Contains Box(A) */
bool cube_contained (NDBOX *a, NDBOX *b) bool
cube_contained(NDBOX * a, NDBOX * b)
{ {
if (cube_contains(b, a) == TRUE) if (cube_contains(b, a) == TRUE)
return (TRUE); return (TRUE);
@ -941,15 +1046,16 @@ bool cube_contained (NDBOX *a, NDBOX *b)
/* Overlap */ /* Overlap */
/* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */ /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
bool cube_overlap(NDBOX *box_a, NDBOX *box_b) bool
cube_overlap(NDBOX * box_a, NDBOX * box_b)
{ {
int i; int i;
NDBOX *a; NDBOX *a;
NDBOX *b; NDBOX *b;
/* This *very bad* error was found in the source: /*
if ( (a==NULL) || (b=NULL) ) * This *very bad* error was found in the source: if ( (a==NULL) ||
return(FALSE); * (b=NULL) ) return(FALSE);
*/ */
if ((box_a == NULL) || (box_b == NULL)) if ((box_a == NULL) || (box_b == NULL))
return (FALSE); return (FALSE);
@ -958,12 +1064,17 @@ bool cube_overlap(NDBOX *box_a, NDBOX *box_b)
b = swap_corners(box_b); b = swap_corners(box_b);
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if ( a->dim < b->dim ) { if (a->dim < b->dim)
NDBOX * tmp = b; b = a; a = tmp; {
NDBOX *tmp = b;
b = a;
a = tmp;
} }
/* compare within the dimensions of (b) */ /* compare within the dimensions of (b) */
for ( i = 0; i < b->dim; i++ ) { for (i = 0; i < b->dim; i++)
{
if (a->x[i] > b->x[i + b->dim]) if (a->x[i] > b->x[i + b->dim])
return (FALSE); return (FALSE);
if (a->x[i + a->dim] < b->x[i]) if (a->x[i + a->dim] < b->x[i])
@ -971,7 +1082,8 @@ bool cube_overlap(NDBOX *box_a, NDBOX *box_b)
} }
/* compare to zero those dimensions in (a) absent in (b) */ /* compare to zero those dimensions in (a) absent in (b) */
for ( i = b->dim; i < a->dim; i++ ) { for (i = b->dim; i < a->dim; i++)
{
if (a->x[i] > 0) if (a->x[i] > 0)
return (FALSE); return (FALSE);
if (a->x[i + a->dim] < 0) if (a->x[i + a->dim] < 0)
@ -990,28 +1102,36 @@ bool cube_overlap(NDBOX *box_a, NDBOX *box_b)
between 1D projections of the boxes onto Cartesian axes. Assuming zero between 1D projections of the boxes onto Cartesian axes. Assuming zero
distance between overlapping projections, this metric coincides with the distance between overlapping projections, this metric coincides with the
"common sense" geometric distance */ "common sense" geometric distance */
float *cube_distance(NDBOX *a, NDBOX *b) float *
cube_distance(NDBOX * a, NDBOX * b)
{ {
int i; int i;
double d, distance; double d,
distance;
float *result; float *result;
result = (float *) palloc(sizeof(float)); result = (float *) palloc(sizeof(float));
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if ( a->dim < b->dim ) { if (a->dim < b->dim)
NDBOX * tmp = b; b = a; a = tmp; {
NDBOX *tmp = b;
b = a;
a = tmp;
} }
distance = 0.0; distance = 0.0;
/* compute within the dimensions of (b) */ /* compute within the dimensions of (b) */
for ( i = 0; i < b->dim; i++ ) { for (i = 0; i < b->dim; i++)
{
d = distance_1D(a->x[i], a->x[i + a->dim], b->x[i], b->x[i + b->dim]); d = distance_1D(a->x[i], a->x[i + a->dim], b->x[i], b->x[i + b->dim]);
distance += d * d; distance += d * d;
} }
/* compute distance to zero for those dimensions in (a) absent in (b) */ /* compute distance to zero for those dimensions in (a) absent in (b) */
for ( i = b->dim; i < a->dim; i++ ) { for (i = b->dim; i < a->dim; i++)
{
d = distance_1D(a->x[i], a->x[i + a->dim], 0.0, 0.0); d = distance_1D(a->x[i], a->x[i + a->dim], 0.0, 0.0);
distance += d * d; distance += d * d;
} }
@ -1021,17 +1141,16 @@ float *cube_distance(NDBOX *a, NDBOX *b)
return (result); return (result);
} }
static float distance_1D(float a1, float a2, float b1, float b2) static float
distance_1D(float a1, float a2, float b1, float b2)
{ {
/* interval (a) is entirely on the left of (b) */ /* interval (a) is entirely on the left of (b) */
if( (a1 <= b1) && (a2 <= b1) && (a1 <= b2) && (a2 <= b2) ) { if ((a1 <= b1) && (a2 <= b1) && (a1 <= b2) && (a2 <= b2))
return (min(b1, b2) - max(a1, a2)); return (min(b1, b2) - max(a1, a2));
}
/* interval (a) is entirely on the right of (b) */ /* interval (a) is entirely on the right of (b) */
if( (a1 > b1) && (a2 > b1) && (a1 > b2) && (a2 > b2) ) { if ((a1 > b1) && (a2 > b1) && (a1 > b2) && (a2 > b2))
return (min(a1, a2) - max(b1, b2)); return (min(a1, a2) - max(b1, b2));
}
/* the rest are all sorts of intersections */ /* the rest are all sorts of intersections */
return (0.0); return (0.0);
@ -1040,16 +1159,19 @@ static float distance_1D(float a1, float a2, float b1, float b2)
/* normalize the box's co-ordinates by placing min(xLL,xUR) to LL /* normalize the box's co-ordinates by placing min(xLL,xUR) to LL
and max(xLL,xUR) to UR and max(xLL,xUR) to UR
*/ */
static NDBOX *swap_corners ( NDBOX *a ) static NDBOX *
swap_corners(NDBOX * a)
{ {
int i, j; int i,
j;
NDBOX *result; NDBOX *result;
result = palloc(a->size); result = palloc(a->size);
result->size = a->size; result->size = a->size;
result->dim = a->dim; result->dim = a->dim;
for ( i = 0, j = a->dim; i < a->dim; i++, j++ ) { for (i = 0, j = a->dim; i < a->dim; i++, j++)
{
result->x[i] = min(a->x[i], a->x[j]); result->x[i] = min(a->x[i], a->x[j]);
result->x[j] = max(a->x[i], a->x[j]); result->x[j] = max(a->x[i], a->x[j]);
} }

View File

@ -1,4 +1,5 @@
typedef struct NDBOX { typedef struct NDBOX
{
unsigned int size; /* required to be a Postgres varlena type */ unsigned int size; /* required to be a Postgres varlena type */
unsigned int dim; unsigned int dim;
float x[1]; float x[1];

View File

@ -1,7 +1,7 @@
/* /*
* PostgreSQL type definitions for managed LargeObjects. * PostgreSQL type definitions for managed LargeObjects.
* *
* $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.7 2001/02/10 02:31:25 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.8 2001/03/22 03:59:09 momjian Exp $
* *
*/ */

View File

@ -13,7 +13,8 @@
#include "libpq-fe.h" #include "libpq-fe.h"
/* these are the opts structures for command line params */ /* these are the opts structures for command line params */
struct options { struct options
{
int getdatabase; int getdatabase;
int gettable; int gettable;
int getoid; int getoid;
@ -46,7 +47,8 @@ void sql_exec_searchtable(PGconn *, char *);
void sql_exec_searchoid(PGconn *, int); void sql_exec_searchoid(PGconn *, int);
/* fuction to parse command line options and check for some usage errors. */ /* fuction to parse command line options and check for some usage errors. */
void get_opts(int argc, char **argv, struct options *my_opts) void
get_opts(int argc, char **argv, struct options * my_opts)
{ {
char c; char c;
@ -148,11 +150,11 @@ void get_opts(int argc, char **argv, struct options *my_opts)
case 'h': case 'h':
fprintf(stderr, "\n\ fprintf(stderr, "\n\
Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\ Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\
dafault action display all databases dafault action display all databases\n\
-d database database to oid2name\n\ -d database database to oid2name\n\
-x display system tables\n\ -x display system tables\n\
-t table | -o oid search for table name (-t) or\n\ -t table | -o oid search for table name (-t) or\n\
oid (-o) in -d database oid (-o) in -d database\n\
-H host connect to remote host\n\ -H host connect to remote host\n\
-p port host port to connect to\n\ -p port host port to connect to\n\
-U username username to connect with\n\ -U username username to connect with\n\
@ -165,11 +167,15 @@ Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\
} }
/* establish connection with database. */ /* establish connection with database. */
PGconn *sql_conn(char *dbName, struct options *my_opts) PGconn *
sql_conn(char *dbName, struct options * my_opts)
{ {
char *pghost, *pgport; char *pghost,
char *pgoptions, *pgtty; *pgport;
char *pguser, *pgpass; char *pgoptions,
*pgtty;
char *pguser,
*pgpass;
PGconn *conn; PGconn *conn;
@ -228,7 +234,8 @@ PGconn *sql_conn(char *dbName, struct options *my_opts)
} }
/* If the sql_ command has an error, this function looks up the error number and prints it out. */ /* If the sql_ command has an error, this function looks up the error number and prints it out. */
void sql_exec_error (int error_number) void
sql_exec_error(int error_number)
{ {
fprintf(stderr, "Error number %i.\n", error_number); fprintf(stderr, "Error number %i.\n", error_number);
switch (error_number) switch (error_number)
@ -256,13 +263,15 @@ void sql_exec_error (int error_number)
} }
/* actual code to make call to the database and print the output data */ /* actual code to make call to the database and print the output data */
int sql_exec(PGconn *conn, char *todo, int match) int
sql_exec(PGconn *conn, char *todo, int match)
{ {
PGresult *res; PGresult *res;
int numbfields; int numbfields;
int error_number; int error_number;
int i, len; int i,
len;
/* make the call */ /* make the call */
res = PQexec(conn, todo); res = PQexec(conn, todo);
@ -306,7 +315,8 @@ int sql_exec(PGconn *conn, char *todo, int match)
} }
/* dump all databases know by the system table */ /* dump all databases know by the system table */
void sql_exec_dumpdb(PGconn *conn) void
sql_exec_dumpdb(PGconn *conn)
{ {
char *todo; char *todo;
@ -320,7 +330,8 @@ void sql_exec_dumpdb(PGconn *conn)
/* display all tables in whatever db we are connected to. don't display the /* display all tables in whatever db we are connected to. don't display the
system tables by default */ system tables by default */
void sql_exec_dumptable(PGconn *conn, int systables) void
sql_exec_dumptable(PGconn *conn, int systables)
{ {
char *todo; char *todo;
@ -337,7 +348,8 @@ void sql_exec_dumptable(PGconn *conn, int systables)
/* display the oid for a given tablename for whatever db we are connected /* display the oid for a given tablename for whatever db we are connected
to. do we want to allow %bar% in the search? Not now. */ to. do we want to allow %bar% in the search? Not now. */
void sql_exec_searchtable(PGconn *conn, char *tablename) void
sql_exec_searchtable(PGconn *conn, char *tablename)
{ {
int returnvalue; int returnvalue;
char *todo; char *todo;
@ -351,18 +363,15 @@ void sql_exec_searchtable(PGconn *conn, char *tablename)
/* deal with the return errors */ /* deal with the return errors */
if (returnvalue == -1) if (returnvalue == -1)
{
printf("No tables with that name found\n"); printf("No tables with that name found\n");
}
if (returnvalue == -2) if (returnvalue == -2)
{
printf("VERY scary: more than one table with that name found!!\n"); printf("VERY scary: more than one table with that name found!!\n");
} }
}
/* same as above */ /* same as above */
void sql_exec_searchoid(PGconn *conn, int oid) void
sql_exec_searchoid(PGconn *conn, int oid)
{ {
int returnvalue; int returnvalue;
char *todo; char *todo;
@ -374,17 +383,14 @@ void sql_exec_searchoid(PGconn *conn, int oid)
returnvalue = sql_exec(conn, todo, 1); returnvalue = sql_exec(conn, todo, 1);
if (returnvalue == -1) if (returnvalue == -1)
{
printf("No tables with that oid found\n"); printf("No tables with that oid found\n");
}
if (returnvalue == -2) if (returnvalue == -2)
{
printf("VERY scary: more than one table with that oid found!!\n"); printf("VERY scary: more than one table with that oid found!!\n");
} }
}
int main(int argc, char **argv) int
main(int argc, char **argv)
{ {
struct options *my_opts; struct options *my_opts;
PGconn *pgconn; PGconn *pgconn;

View File

@ -6,7 +6,7 @@
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001; * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD * licence: BSD
* *
* $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.2 2001/03/13 01:17:40 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.3 2001/03/22 03:59:09 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -51,7 +51,8 @@ main()
char ckpttime_str[32]; char ckpttime_str[32];
DataDir = getenv("PGDATA"); DataDir = getenv("PGDATA");
if ( DataDir == NULL ) { if (DataDir == NULL)
{
fprintf(stderr, "PGDATA is not defined\n"); fprintf(stderr, "PGDATA is not defined\n");
exit(1); exit(1);
} }

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.5 2001/01/24 19:42:44 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.6 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -52,25 +52,29 @@ load_lolist( LODumpMaster *pgLO )
" AND c.relkind = 'r' " " AND c.relkind = 'r' "
" AND c.relname NOT LIKE 'pg_%'"); " AND c.relname NOT LIKE 'pg_%'");
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) { if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname, fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn)); PQerrorMessage(pgLO->conn));
exit(RE_ERROR); exit(RE_ERROR);
} }
if ((n = PQntuples(pgLO->res)) == 0) { if ((n = PQntuples(pgLO->res)) == 0)
{
fprintf(stderr, "%s: No OID columns in the database.\n", progname); fprintf(stderr, "%s: No OID columns in the database.\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist)); pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist));
if (!pgLO->lolist) { if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname); fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
for (i = 0, ll = pgLO->lolist; i < n; i++, ll++) { for (i = 0, ll = pgLO->lolist; i < n; i++, ll++)
{
ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0)); ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1)); ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
} }
@ -87,8 +91,10 @@ pglo_export(LODumpMaster *pgLO)
char path[BUFSIZ], char path[BUFSIZ],
Qbuff[QUERY_BUFSIZ]; Qbuff[QUERY_BUFSIZ];
if (pgLO->action != ACTION_SHOW) { if (pgLO->action != ACTION_SHOW)
{
time_t t; time_t t;
time(&t); time(&t);
fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n"); fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n");
fprintf(pgLO->index, "#\tDate: %s", ctime(&t)); fprintf(pgLO->index, "#\tDate: %s", ctime(&t));
@ -100,7 +106,8 @@ pglo_export(LODumpMaster *pgLO)
pgLO->counter = 0; pgLO->counter = 0;
for(ll=pgLO->lolist; ll->lo_table != NULL; ll++) { for (ll = pgLO->lolist; ll->lo_table != NULL; ll++)
{
/* ---------- /* ----------
* Query: find the LOs referenced by this column * Query: find the LOs referenced by this column
@ -113,15 +120,19 @@ pglo_export(LODumpMaster *pgLO)
pgLO->res = PQexec(pgLO->conn, Qbuff); pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) { if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname, fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn)); PQerrorMessage(pgLO->conn));
} }
else if ((tuples = PQntuples(pgLO->res)) == 0) { else if ((tuples = PQntuples(pgLO->res)) == 0)
{
if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR) if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
printf("%s: no large objects in \"%s\".\"%s\"\n", printf("%s: no large objects in \"%s\".\"%s\"\n",
progname, ll->lo_table, ll->lo_attr); progname, ll->lo_table, ll->lo_attr);
} else { }
else
{
int t; int t;
char *val; char *val;
@ -130,13 +141,16 @@ pglo_export(LODumpMaster *pgLO)
* Create DIR/FILE * Create DIR/FILE
* ---------- * ----------
*/ */
if (pgLO->action != ACTION_SHOW) { if (pgLO->action != ACTION_SHOW)
{
sprintf(path, "%s/%s/%s", pgLO->space, pgLO->db, sprintf(path, "%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_table); ll->lo_table);
if (mkdir(path, DIR_UMASK) == -1) { if (mkdir(path, DIR_UMASK) == -1)
if (errno != EEXIST) { {
if (errno != EEXIST)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -145,8 +159,10 @@ pglo_export(LODumpMaster *pgLO)
sprintf(path, "%s/%s/%s/%s", pgLO->space, pgLO->db, sprintf(path, "%s/%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_table, ll->lo_attr); ll->lo_table, ll->lo_attr);
if (mkdir(path, DIR_UMASK) == -1) { if (mkdir(path, DIR_UMASK) == -1)
if (errno != EEXIST) { {
if (errno != EEXIST)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -159,14 +175,16 @@ pglo_export(LODumpMaster *pgLO)
pgLO->counter += tuples; pgLO->counter += tuples;
for(t=0; t<tuples; t++) { for (t = 0; t < tuples; t++)
{
Oid lo; Oid lo;
val = PQgetvalue(pgLO->res, t, 0); val = PQgetvalue(pgLO->res, t, 0);
lo = atooid(val); lo = atooid(val);
if (pgLO->action == ACTION_SHOW) { if (pgLO->action == ACTION_SHOW)
{
printf("%s.%s: %u\n", ll->lo_table, ll->lo_attr, lo); printf("%s.%s: %u\n", ll->lo_table, ll->lo_attr, lo);
continue; continue;
} }

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -29,11 +29,14 @@ pglo_import(LODumpMaster *pgLO)
{ {
LOlist loa; LOlist loa;
Oid new_oid; Oid new_oid;
char tab[MAX_TABLE_NAME], attr[MAX_ATTR_NAME], char tab[MAX_TABLE_NAME],
path[BUFSIZ], lo_path[BUFSIZ], attr[MAX_ATTR_NAME],
path[BUFSIZ],
lo_path[BUFSIZ],
Qbuff[QUERY_BUFSIZ]; Qbuff[QUERY_BUFSIZ];
while(fgets(Qbuff, QUERY_BUFSIZ, pgLO->index)) { while (fgets(Qbuff, QUERY_BUFSIZ, pgLO->index))
{
if (*Qbuff == '#') if (*Qbuff == '#')
continue; continue;
@ -51,7 +54,8 @@ pglo_import(LODumpMaster *pgLO)
* Import LO * Import LO
* ---------- * ----------
*/ */
if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0) { if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0)
{
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn)); fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
@ -60,7 +64,8 @@ pglo_import(LODumpMaster *pgLO)
exit(RE_ERROR); exit(RE_ERROR);
} }
if (pgLO->remove) { if (pgLO->remove)
{
notice(pgLO, FALSE); notice(pgLO, FALSE);
if (lo_unlink(pgLO->conn, loa.lo_oid) < 0) if (lo_unlink(pgLO->conn, loa.lo_oid) < 0)
fprintf(stderr, "%s: can't remove LO %u:\n%s", fprintf(stderr, "%s: can't remove LO %u:\n%s",
@ -85,7 +90,8 @@ pglo_import(LODumpMaster *pgLO)
pgLO->res = PQexec(pgLO->conn, Qbuff); pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_COMMAND_OK) { if (PQresultStatus(pgLO->res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn)); fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
PQclear(pgLO->res); PQclear(pgLO->res);
PQexec(pgLO->conn, "ROLLBACK"); PQexec(pgLO->conn, "ROLLBACK");

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.6 2001/02/10 02:31:25 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.7 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -45,7 +45,8 @@ static void parse_lolist (LODumpMaster *pgLO);
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
LODumpMaster _pgLO, *pgLO = &_pgLO; LODumpMaster _pgLO,
*pgLO = &_pgLO;
char *pwd = NULL; char *pwd = NULL;
pgLO->argv = argv; pgLO->argv = argv;
@ -68,7 +69,8 @@ main(int argc, char **argv)
* Parse ARGV * Parse ARGV
* ---------- * ----------
*/ */
if (argc > 1) { if (argc > 1)
{
int arg; int arg;
extern int optind; extern int optind;
@ -90,11 +92,14 @@ main(int argc, char **argv)
{NULL, 0, 0, 0} {NULL, 0, 0, 0}
}; };
while((arg = getopt_long(argc, argv, "?aehu:p:qd:l:t:irs:w", l_opt, &l_index)) != -1) { while ((arg = getopt_long(argc, argv, "?aehu:p:qd:l:t:irs:w", l_opt, &l_index)) != -1)
{
#else #else
while((arg = getopt(argc, argv, "?aehu:p:qd:l:t:irs:w")) != -1) { while ((arg = getopt(argc, argv, "?aehu:p:qd:l:t:irs:w")) != -1)
{
#endif #endif
switch(arg) { switch (arg)
{
case '?': case '?':
case 'h': case 'h':
usage(); usage();
@ -141,7 +146,9 @@ main(int argc, char **argv)
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
} else { }
else
{
usage(); usage();
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -150,14 +157,17 @@ main(int argc, char **argv)
* Check space * Check space
* ---------- * ----------
*/ */
if (! pgLO->space && ! pgLO->action == ACTION_SHOW) { if (!pgLO->space && !pgLO->action == ACTION_SHOW)
if (!(pgLO->space = getenv("PWD"))) { {
if (!(pgLO->space = getenv("PWD")))
{
fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname); fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
if (!pgLO->action) { if (!pgLO->action)
{
fprintf(stderr, "%s: What do you want - export or import?\n", progname); fprintf(stderr, "%s: What do you want - export or import?\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -169,7 +179,8 @@ main(int argc, char **argv)
pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db, pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db,
pgLO->user, pwd); pgLO->user, pwd);
if (PQstatus(pgLO->conn) == CONNECTION_BAD) { if (PQstatus(pgLO->conn) == CONNECTION_BAD)
{
fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn)); fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn));
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -187,7 +198,8 @@ main(int argc, char **argv)
PQexec(pgLO->conn, "BEGIN"); PQexec(pgLO->conn, "BEGIN");
switch(pgLO->action) { switch (pgLO->action)
{
case ACTION_SHOW: case ACTION_SHOW:
case ACTION_EXPORT_ALL: case ACTION_EXPORT_ALL:
@ -196,7 +208,8 @@ main(int argc, char **argv)
case ACTION_EXPORT_ATTR: case ACTION_EXPORT_ATTR:
pglo_export(pgLO); pglo_export(pgLO);
if (!pgLO->quiet) { if (!pgLO->quiet)
{
if (pgLO->action == ACTION_SHOW) if (pgLO->action == ACTION_SHOW)
printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter); printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter);
else else
@ -230,18 +243,21 @@ parse_lolist (LODumpMaster *pgLO)
pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist)); pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist));
if (! pgLO->lolist) { if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname); fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
for (d = pgLO->argv + pgLO->lolist_start, ll = pgLO->lolist; for (d = pgLO->argv + pgLO->lolist_start, ll = pgLO->lolist;
*d != NULL; *d != NULL;
d++, ll++) { d++, ll++)
{
strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME); strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME);
if ((loc = strchr(buff, '.')) == NULL) { if ((loc = strchr(buff, '.')) == NULL)
{
fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff); fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff);
exit(RE_ERROR); exit(RE_ERROR);
} }

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -36,13 +36,15 @@
* LO struct * LO struct
* ---------- * ----------
*/ */
typedef struct { typedef struct
{
char *lo_table, char *lo_table,
*lo_attr; *lo_attr;
Oid lo_oid; Oid lo_oid;
} LOlist; } LOlist;
typedef struct { typedef struct
{
int action; int action;
LOlist *lolist; LOlist *lolist;
char **argv, char **argv,
@ -60,7 +62,8 @@ typedef struct {
PGconn *conn; PGconn *conn;
} LODumpMaster; } LODumpMaster;
typedef enum { typedef enum
{
ACTION_NONE, ACTION_NONE,
ACTION_SHOW, ACTION_SHOW,
ACTION_EXPORT_ATTR, ACTION_EXPORT_ATTR,

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/utils.c,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/utils.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -39,10 +39,13 @@ index_file(LODumpMaster *pgLO)
sprintf(path, "%s/%s", pgLO->space, pgLO->db); sprintf(path, "%s/%s", pgLO->space, pgLO->db);
if (pgLO->action == ACTION_EXPORT_ATTR || if (pgLO->action == ACTION_EXPORT_ATTR ||
pgLO->action == ACTION_EXPORT_ALL) { pgLO->action == ACTION_EXPORT_ALL)
{
if (mkdir(path, DIR_UMASK) == -1) { if (mkdir(path, DIR_UMASK) == -1)
if (errno != EEXIST) { {
if (errno != EEXIST)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -50,16 +53,20 @@ index_file(LODumpMaster *pgLO)
sprintf(path, "%s/lo_dump.index", path); sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "w")) == NULL) { if ((pgLO->index = fopen(path, "w")) == NULL)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
} else if (pgLO->action != ACTION_NONE ) { }
else if (pgLO->action != ACTION_NONE)
{
sprintf(path, "%s/lo_dump.index", path); sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "r")) == NULL) { if ((pgLO->index = fopen(path, "r")) == NULL)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
@ -67,13 +74,15 @@ index_file(LODumpMaster *pgLO)
} }
static static
void Dummy_NoticeProcessor(void * arg, const char * message) void
Dummy_NoticeProcessor(void *arg, const char *message)
{ {
; ;
} }
static static
void Default_NoticeProcessor(void * arg, const char * message) void
Default_NoticeProcessor(void *arg, const char *message)
{ {
fprintf(stderr, "%s", message); fprintf(stderr, "%s", message);
} }
@ -81,6 +90,8 @@ void Default_NoticeProcessor(void * arg, const char * message)
void void
notice(LODumpMaster * pgLO, int set) notice(LODumpMaster * pgLO, int set)
{ {
if (set)PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL); if (set)
else PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL); PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL);
else
PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL);
} }

View File

@ -13,24 +13,48 @@
#include <syslog.h> #include <syslog.h>
#include <string.h> #include <string.h>
struct { struct
{
const char *tag; const char *tag;
int size; int size;
int priority; int priority;
} tags[] = { } tags[] =
{ "", 0, LOG_NOTICE },
{ "emerg:", sizeof("emerg"), LOG_EMERG }, {
{ "alert:", sizeof("alert"), LOG_ALERT }, {
{ "crit:", sizeof("crit"), LOG_CRIT }, "", 0, LOG_NOTICE
{ "err:", sizeof("err"), LOG_ERR }, },
{ "error:", sizeof("error"), LOG_ERR }, {
{ "warning:", sizeof("warning"), LOG_WARNING }, "emerg:", sizeof("emerg"), LOG_EMERG
{ "notice:", sizeof("notice"), LOG_NOTICE }, },
{ "info:", sizeof("info"), LOG_INFO }, {
{ "debug:", sizeof("debug"), LOG_DEBUG } "alert:", sizeof("alert"), LOG_ALERT
},
{
"crit:", sizeof("crit"), LOG_CRIT
},
{
"err:", sizeof("err"), LOG_ERR
},
{
"error:", sizeof("error"), LOG_ERR
},
{
"warning:", sizeof("warning"), LOG_WARNING
},
{
"notice:", sizeof("notice"), LOG_NOTICE
},
{
"info:", sizeof("info"), LOG_INFO
},
{
"debug:", sizeof("debug"), LOG_DEBUG
}
}; };
int main() int
main()
{ {
char buf[301]; char buf[301];
int c; int c;
@ -40,29 +64,29 @@ int main()
#ifndef DEBUG #ifndef DEBUG
openlog("postgresql", LOG_CONS, LOG_LOCAL1); openlog("postgresql", LOG_CONS, LOG_LOCAL1);
#endif #endif
while ( (c = getchar()) != EOF) { while ((c = getchar()) != EOF)
if (c == '\r') { {
if (c == '\r')
continue; continue;
} if (c == '\n')
if (c == '\n') { {
int level = sizeof(tags) / sizeof(*tags); int level = sizeof(tags) / sizeof(*tags);
char *bol; char *bol;
if (colon == 0 || (size_t)(colon - buf) > sizeof("warning")) { if (colon == 0 || (size_t) (colon - buf) > sizeof("warning"))
level = 1; level = 1;
}
*pos = 0; *pos = 0;
while (--level) { while (--level)
{
if (pos - buf >= tags[level].size if (pos - buf >= tags[level].size
&& strncmp(buf, tags[level].tag, tags[level].size) == 0) { && strncmp(buf, tags[level].tag, tags[level].size) == 0)
break; break;
} }
}
bol = buf + tags[level].size; bol = buf + tags[level].size;
if (bol > buf && *bol == ' ') { if (bol > buf && *bol == ' ')
++bol; ++bol;
} if (pos - bol > 0)
if (pos - bol > 0) { {
#ifndef DEBUG #ifndef DEBUG
syslog(tags[level].priority, "%s", bol); syslog(tags[level].priority, "%s", bol);
#else #else
@ -73,13 +97,10 @@ int main()
colon = (char const *) 0; colon = (char const *) 0;
continue; continue;
} }
if (c == ':' && !colon) { if (c == ':' && !colon)
colon = pos; colon = pos;
} if ((size_t) (pos - buf) < sizeof(buf) - 1)
if ((size_t)(pos - buf) < sizeof(buf)-1) {
*pos++ = c; *pos++ = c;
} }
}
return 0; return 0;
} }

View File

@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.2 2001/03/16 05:08:39 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -110,7 +110,8 @@ static char XLogDir[MAXPGPATH];
static char ControlFilePath[MAXPGPATH]; static char ControlFilePath[MAXPGPATH];
static ControlFileData ControlFile; /* pg_control values */ static ControlFileData ControlFile; /* pg_control values */
static uint32 newXlogId, newXlogSeg; /* ID/Segment of new XLOG segment */ static uint32 newXlogId,
newXlogSeg; /* ID/Segment of new XLOG segment */
static bool guessed = false; /* T if we had to guess at any values */ static bool guessed = false; /* T if we had to guess at any values */
@ -146,10 +147,11 @@ ReadControlFile(void)
if ((fd = open(ControlFilePath, O_RDONLY)) < 0) if ((fd = open(ControlFilePath, O_RDONLY)) < 0)
{ {
/* /*
* If pg_control is not there at all, or we can't read it, * If pg_control is not there at all, or we can't read it, the
* the odds are we've been handed a bad DataDir path, so give up. * odds are we've been handed a bad DataDir path, so give up. User
* User can do "touch pg_control" to force us to proceed. * can do "touch pg_control" to force us to proceed.
*/ */
perror("Failed to open $PGDATA/global/pg_control for reading"); perror("Failed to open $PGDATA/global/pg_control for reading");
if (errno == ENOENT) if (errno == ENOENT)
@ -193,6 +195,7 @@ ReadControlFile(void)
guessed = true; guessed = true;
return true; return true;
} }
/* /*
* Maybe it's a 7.1beta pg_control. * Maybe it's a 7.1beta pg_control.
*/ */
@ -409,6 +412,7 @@ CheckControlVersion0(char *buffer, int len)
(char *) malloc(_INTL_MAXLOGRECSZ)); (char *) malloc(_INTL_MAXLOGRECSZ));
if (record == NULL) if (record == NULL)
{ {
/* /*
* We have to guess at the checkpoint contents. * We have to guess at the checkpoint contents.
*/ */
@ -442,8 +446,8 @@ RecordIsValidV0(XLogRecordV0 *record)
/* /*
* NB: this code is not right for V0 records containing backup blocks, * NB: this code is not right for V0 records containing backup blocks,
* but for now it's only going to be applied to checkpoint records, * but for now it's only going to be applied to checkpoint records, so
* so I'm not going to worry about it... * I'm not going to worry about it...
*/ */
INIT_CRC64V0(crc); INIT_CRC64V0(crc);
COMP_CRC64V0(crc, XLogRecGetData(record), len); COMP_CRC64V0(crc, XLogRecGetData(record), len);
@ -510,10 +514,13 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
if (record->xl_len == 0) if (record->xl_len == 0)
goto next_record_is_invalid; goto next_record_is_invalid;
/* /*
* Compute total length of record including any appended backup blocks. * Compute total length of record including any appended backup
* blocks.
*/ */
total_len = SizeOfXLogRecordV0 + record->xl_len; total_len = SizeOfXLogRecordV0 + record->xl_len;
/* /*
* Make sure it will fit in buffer (currently, it is mechanically * Make sure it will fit in buffer (currently, it is mechanically
* impossible for this test to fail, but it seems like a good idea * impossible for this test to fail, but it seems like a good idea
@ -610,6 +617,7 @@ GuessControlValues(void)
{ {
#ifdef USE_LOCALE #ifdef USE_LOCALE
char *localeptr; char *localeptr;
#endif #endif
/* /*
@ -710,8 +718,8 @@ RewriteControlFile(void)
char buffer[BLCKSZ]; /* need not be aligned */ char buffer[BLCKSZ]; /* need not be aligned */
/* /*
* Adjust fields as needed to force an empty XLOG starting at the * Adjust fields as needed to force an empty XLOG starting at the next
* next available segment. * available segment.
*/ */
newXlogId = ControlFile.logId; newXlogId = ControlFile.logId;
newXlogSeg = ControlFile.logSeg; newXlogSeg = ControlFile.logSeg;
@ -740,11 +748,11 @@ RewriteControlFile(void)
FIN_CRC64(ControlFile.crc); FIN_CRC64(ControlFile.crc);
/* /*
* We write out BLCKSZ bytes into pg_control, zero-padding the * We write out BLCKSZ bytes into pg_control, zero-padding the excess
* excess over sizeof(ControlFileData). This reduces the odds * over sizeof(ControlFileData). This reduces the odds of
* of premature-EOF errors when reading pg_control. We'll still * premature-EOF errors when reading pg_control. We'll still fail
* fail when we check the contents of the file, but hopefully with * when we check the contents of the file, but hopefully with a more
* a more specific error than "couldn't read pg_control". * specific error than "couldn't read pg_control".
*/ */
if (sizeof(ControlFileData) > BLCKSZ) if (sizeof(ControlFileData) > BLCKSZ)
{ {
@ -946,7 +954,8 @@ main(int argc, char ** argv)
/* /*
* Check for a postmaster lock file --- if there is one, refuse to * Check for a postmaster lock file --- if there is one, refuse to
* proceed, on grounds we might be interfering with a live installation. * proceed, on grounds we might be interfering with a live
* installation.
*/ */
snprintf(path, MAXPGPATH, "%s%cpostmaster.pid", DataDir, SEP_CHAR); snprintf(path, MAXPGPATH, "%s%cpostmaster.pid", DataDir, SEP_CHAR);
@ -973,8 +982,8 @@ main(int argc, char ** argv)
GuessControlValues(); GuessControlValues();
/* /*
* If we had to guess anything, and -f was not given, just print * If we had to guess anything, and -f was not given, just print the
* the guessed values and exit. Also print if -n is given. * guessed values and exit. Also print if -n is given.
*/ */
if ((guessed && !force) || noupdate) if ((guessed && !force) || noupdate)
{ {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: encode.c,v 1.3 2001/02/10 02:31:25 tgl Exp $ * $Id: encode.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -56,8 +56,11 @@ encode(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, rlen, rlen0; uint len,
pg_coding *c, cbuf; rlen,
rlen0;
pg_coding *c,
cbuf;
text *res; text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
@ -93,8 +96,11 @@ decode(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, rlen, rlen0; uint len,
pg_coding *c, cbuf; rlen,
rlen0;
pg_coding *c,
cbuf;
text *res; text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
@ -130,7 +136,8 @@ find_coding(pg_coding *dst, text *name, int silent)
uint len; uint len;
len = VARSIZE(name) - VARHDRSZ; len = VARSIZE(name) - VARHDRSZ;
if (len >= NAMEDATALEN) { if (len >= NAMEDATALEN)
{
if (silent) if (silent)
return NULL; return NULL;
elog(ERROR, "Encoding type does not exist (name too long)"); elog(ERROR, "Encoding type does not exist (name too long)");
@ -152,7 +159,9 @@ uint
hex_encode(uint8 *src, uint len, uint8 *dst) hex_encode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *end = src + len; uint8 *end = src + len;
while (src < end) {
while (src < end)
{
*dst++ = hextbl[(*src >> 4) & 0xF]; *dst++ = hextbl[(*src >> 4) & 0xF];
*dst++ = hextbl[*src & 0xF]; *dst++ = hextbl[*src & 0xF];
src++; src++;
@ -181,12 +190,19 @@ get_hex(char c)
uint uint
hex_decode(uint8 *src, uint len, uint8 *dst) hex_decode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *s, *srcend, v1, v2, *p = dst; uint8 *s,
*srcend,
v1,
v2,
*p = dst;
srcend = src + len; srcend = src + len;
s = src; p = dst; s = src;
while (s < srcend) { p = dst;
if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r') { while (s < srcend)
{
if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
{
s++; s++;
continue; continue;
} }
@ -207,19 +223,25 @@ static unsigned char _base64[] =
uint uint
b64_encode(uint8 *src, uint len, uint8 *dst) b64_encode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *s, *p, *end = src + len, *lend = dst + 76; uint8 *s,
*p,
*end = src + len,
*lend = dst + 76;
int pos = 2; int pos = 2;
unsigned long buf = 0; unsigned long buf = 0;
s = src; p = dst; s = src;
p = dst;
while (s < end) { while (s < end)
{
buf |= *s << (pos << 3); buf |= *s << (pos << 3);
pos--; pos--;
s++; s++;
/* write it out */ /* write it out */
if (pos < 0) { if (pos < 0)
{
*p++ = _base64[(buf >> 18) & 0x3f]; *p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f]; *p++ = _base64[(buf >> 12) & 0x3f];
*p++ = _base64[(buf >> 6) & 0x3f]; *p++ = _base64[(buf >> 6) & 0x3f];
@ -228,12 +250,14 @@ b64_encode(uint8 *src, uint len, uint8 *dst)
pos = 2; pos = 2;
buf = 0; buf = 0;
} }
if (p >= lend) { if (p >= lend)
{
*p++ = '\n'; *p++ = '\n';
lend = p + 76; lend = p + 76;
} }
} }
if (pos != 2) { if (pos != 2)
{
*p++ = _base64[(buf >> 18) & 0x3f]; *p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f]; *p++ = _base64[(buf >> 12) & 0x3f];
*p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '='; *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
@ -247,14 +271,17 @@ b64_encode(uint8 *src, uint len, uint8 *dst)
uint uint
b64_decode(uint8 *src, uint len, uint8 *dst) b64_decode(uint8 *src, uint len, uint8 *dst)
{ {
char *srcend = src + len, *s = src; char *srcend = src + len,
*s = src;
uint8 *p = dst; uint8 *p = dst;
char c; char c;
uint b = 0; uint b = 0;
unsigned long buf = 0; unsigned long buf = 0;
int pos = 0, end = 0; int pos = 0,
end = 0;
while (s < srcend) { while (s < srcend)
{
c = *s++; c = *s++;
if (c >= 'A' && c <= 'Z') if (c >= 'A' && c <= 'Z')
b = c - 'A'; b = c - 'A';
@ -266,16 +293,21 @@ b64_decode(uint8 *src, uint len, uint8 *dst)
b = 62; b = 62;
else if (c == '/') else if (c == '/')
b = 63; b = 63;
else if (c == '=') { else if (c == '=')
{
/* end sequence */ /* end sequence */
if (!end) { if (!end)
if (pos == 2) end = 1; {
else if (pos == 3) end = 2; if (pos == 2)
end = 1;
else if (pos == 3)
end = 2;
else else
elog(ERROR, "base64: unexpected '='"); elog(ERROR, "base64: unexpected '='");
} }
b = 0; b = 0;
} else if (c == ' ' || c == '\t' || c == '\n' || c == '\r') }
else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue; continue;
else else
elog(ERROR, "base64: Invalid symbol"); elog(ERROR, "base64: Invalid symbol");
@ -283,7 +315,8 @@ b64_decode(uint8 *src, uint len, uint8 *dst)
/* add it to buffer */ /* add it to buffer */
buf = (buf << 6) + b; buf = (buf << 6) + b;
pos++; pos++;
if (pos == 4) { if (pos == 4)
{
*p++ = (buf >> 16) & 255; *p++ = (buf >> 16) & 255;
if (end == 0 || end > 1) if (end == 0 || end > 1)
*p++ = (buf >> 8) & 255; *p++ = (buf >> 8) & 255;
@ -337,10 +370,11 @@ static pg_coding *
pg_find_coding(pg_coding * res, char *name) pg_find_coding(pg_coding * res, char *name)
{ {
pg_coding *p; pg_coding *p;
for (p = encoding_list; p->name; p++) {
for (p = encoding_list; p->name; p++)
{
if (!strcasecmp(p->name, name)) if (!strcasecmp(p->name, name))
return p; return p;
} }
return NULL; return NULL;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: encode.h,v 1.1 2001/01/24 03:46:16 momjian Exp $ * $Id: encode.h,v 1.2 2001/03/22 03:59:10 momjian Exp $
*/ */
#ifndef __PG_ENCODE_H #ifndef __PG_ENCODE_H
@ -37,7 +37,8 @@ Datum encode(PG_FUNCTION_ARGS);
Datum decode(PG_FUNCTION_ARGS); Datum decode(PG_FUNCTION_ARGS);
typedef struct _pg_coding pg_coding; typedef struct _pg_coding pg_coding;
struct _pg_coding { struct _pg_coding
{
char *name; char *name;
uint (*encode_len) (uint dlen); uint (*encode_len) (uint dlen);
uint (*decode_len) (uint dlen); uint (*decode_len) (uint dlen);
@ -57,4 +58,3 @@ uint b64_enc_len(uint srclen);
uint b64_dec_len(uint srclen); uint b64_dec_len(uint srclen);
#endif /* __PG_ENCODE_H */ #endif /* __PG_ENCODE_H */

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: internal.c,v 1.2 2001/02/10 02:31:25 tgl Exp $ * $Id: internal.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -66,7 +66,8 @@ int_digest_list [] = {
}; };
static uint static uint
pg_md5_len(pg_digest *h) { pg_md5_len(pg_digest * h)
{
return MD5_DIGEST_LENGTH; return MD5_DIGEST_LENGTH;
} }
@ -83,7 +84,8 @@ pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf)
} }
static uint static uint
pg_sha1_len(pg_digest *h) { pg_sha1_len(pg_digest * h)
{
return SHA1_DIGEST_LENGTH; return SHA1_DIGEST_LENGTH;
} }
@ -110,5 +112,3 @@ pg_find_digest(pg_digest *h, char *name)
return p; return p;
return NULL; return NULL;
} }

View File

@ -31,7 +31,7 @@
* It is possible that this works with other SHA1/MD5 * It is possible that this works with other SHA1/MD5
* implementations too. * implementations too.
* *
* $Id: krb.c,v 1.3 2001/02/20 15:34:14 momjian Exp $ * $Id: krb.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -71,7 +71,8 @@ int_digest_list [] = {
}; };
static uint static uint
pg_md5_len(pg_digest *h) { pg_md5_len(pg_digest * h)
{
return MD5_DIGEST_LENGTH; return MD5_DIGEST_LENGTH;
} }
@ -88,7 +89,8 @@ pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf)
} }
static uint static uint
pg_sha1_len(pg_digest *h) { pg_sha1_len(pg_digest * h)
{
return SHA1_DIGEST_LENGTH; return SHA1_DIGEST_LENGTH;
} }
@ -115,5 +117,3 @@ pg_find_digest(pg_digest *h, char *name)
return p; return p;
return NULL; return NULL;
} }

View File

@ -1,4 +1,4 @@
/* $Id: md5.c,v 1.4 2001/02/10 02:31:25 tgl Exp $ */ /* $Id: md5.c,v 1.5 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ /* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */
/* /*
@ -127,7 +127,8 @@ static const uint8 md5_paddat[MD5_BUFLEN] = {
static void md5_calc(uint8 *, md5_ctxt *); static void md5_calc(uint8 *, md5_ctxt *);
void md5_init(ctxt) void
md5_init(ctxt)
md5_ctxt *ctxt; md5_ctxt *ctxt;
{ {
ctxt->md5_n = 0; ctxt->md5_n = 0;
@ -139,46 +140,54 @@ void md5_init(ctxt)
bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf)); bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
} }
void md5_loop(ctxt, input, len) void
md5_loop(ctxt, input, len)
md5_ctxt *ctxt; md5_ctxt *ctxt;
uint8 *input; uint8 *input;
unsigned int len; /* number of bytes */ unsigned int len; /* number of bytes */
{ {
unsigned int gap, i; unsigned int gap,
i;
ctxt->md5_n += len * 8; /* byte to bit */ ctxt->md5_n += len * 8; /* byte to bit */
gap = MD5_BUFLEN - ctxt->md5_i; gap = MD5_BUFLEN - ctxt->md5_i;
if (len >= gap) { if (len >= gap)
{
bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i), bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i),
gap); gap);
md5_calc(ctxt->md5_buf, ctxt); md5_calc(ctxt->md5_buf, ctxt);
for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) { for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN)
md5_calc((uint8 *) (input + i), ctxt); md5_calc((uint8 *) (input + i), ctxt);
}
ctxt->md5_i = len - i; ctxt->md5_i = len - i;
bcopy((void *) (input + i), (void *) ctxt->md5_buf, ctxt->md5_i); bcopy((void *) (input + i), (void *) ctxt->md5_buf, ctxt->md5_i);
} else { }
else
{
bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i), bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i),
len); len);
ctxt->md5_i += len; ctxt->md5_i += len;
} }
} }
void md5_pad(ctxt) void
md5_pad(ctxt)
md5_ctxt *ctxt; md5_ctxt *ctxt;
{ {
unsigned int gap; unsigned int gap;
/* Don't count up padding. Keep md5_n. */ /* Don't count up padding. Keep md5_n. */
gap = MD5_BUFLEN - ctxt->md5_i; gap = MD5_BUFLEN - ctxt->md5_i;
if (gap > 8) { if (gap > 8)
{
bcopy((void *) md5_paddat, bcopy((void *) md5_paddat,
(void *) (ctxt->md5_buf + ctxt->md5_i), (void *) (ctxt->md5_buf + ctxt->md5_i),
gap - sizeof(ctxt->md5_n)); gap - sizeof(ctxt->md5_n));
} else { }
else
{
/* including gap == 8 */ /* including gap == 8 */
bcopy((void *) md5_paddat, (void *) (ctxt->md5_buf + ctxt->md5_i), bcopy((void *) md5_paddat, (void *) (ctxt->md5_buf + ctxt->md5_i),
gap); gap);
@ -206,7 +215,8 @@ void md5_pad(ctxt)
md5_calc(ctxt->md5_buf, ctxt); md5_calc(ctxt->md5_buf, ctxt);
} }
void md5_result(digest, ctxt) void
md5_result(digest, ctxt)
uint8 *digest; uint8 *digest;
md5_ctxt *ctxt; md5_ctxt *ctxt;
{ {
@ -215,22 +225,32 @@ void md5_result(digest, ctxt)
bcopy(&ctxt->md5_st8[0], digest, 16); bcopy(&ctxt->md5_st8[0], digest, 16);
#endif #endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2]; digest[0] = ctxt->md5_st8[3];
digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0]; digest[1] = ctxt->md5_st8[2];
digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6]; digest[2] = ctxt->md5_st8[1];
digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4]; digest[3] = ctxt->md5_st8[0];
digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10]; digest[4] = ctxt->md5_st8[7];
digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8]; digest[5] = ctxt->md5_st8[6];
digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14]; digest[6] = ctxt->md5_st8[5];
digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12]; digest[7] = ctxt->md5_st8[4];
digest[8] = ctxt->md5_st8[11];
digest[9] = ctxt->md5_st8[10];
digest[10] = ctxt->md5_st8[9];
digest[11] = ctxt->md5_st8[8];
digest[12] = ctxt->md5_st8[15];
digest[13] = ctxt->md5_st8[14];
digest[14] = ctxt->md5_st8[13];
digest[15] = ctxt->md5_st8[12];
#endif #endif
} }
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
uint32 X[16]; uint32 X[16];
#endif #endif
static void md5_calc(b64, ctxt) static void
md5_calc(b64, ctxt)
uint8 *b64; uint8 *b64;
md5_ctxt *ctxt; md5_ctxt *ctxt;
{ {
@ -238,66 +258,149 @@ static void md5_calc(b64, ctxt)
uint32 B = ctxt->md5_stb; uint32 B = ctxt->md5_stb;
uint32 C = ctxt->md5_stc; uint32 C = ctxt->md5_stc;
uint32 D = ctxt->md5_std; uint32 D = ctxt->md5_std;
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
uint32 *X = (uint32 *) b64; uint32 *X = (uint32 *) b64;
#endif #endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
/* 4 byte words */ /* 4 byte words */
/* what a brute force but fast! */ /* what a brute force but fast! */
uint8 *y = (uint8 *) X; uint8 *y = (uint8 *) X;
y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4]; y[0] = b64[3];
y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8]; y[1] = b64[2];
y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12]; y[2] = b64[1];
y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16]; y[3] = b64[0];
y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20]; y[4] = b64[7];
y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24]; y[5] = b64[6];
y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28]; y[6] = b64[5];
y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32]; y[7] = b64[4];
y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36]; y[8] = b64[11];
y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40]; y[9] = b64[10];
y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44]; y[10] = b64[9];
y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48]; y[11] = b64[8];
y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52]; y[12] = b64[15];
y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56]; y[13] = b64[14];
y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60]; y[14] = b64[13];
y[15] = b64[12];
y[16] = b64[19];
y[17] = b64[18];
y[18] = b64[17];
y[19] = b64[16];
y[20] = b64[23];
y[21] = b64[22];
y[22] = b64[21];
y[23] = b64[20];
y[24] = b64[27];
y[25] = b64[26];
y[26] = b64[25];
y[27] = b64[24];
y[28] = b64[31];
y[29] = b64[30];
y[30] = b64[29];
y[31] = b64[28];
y[32] = b64[35];
y[33] = b64[34];
y[34] = b64[33];
y[35] = b64[32];
y[36] = b64[39];
y[37] = b64[38];
y[38] = b64[37];
y[39] = b64[36];
y[40] = b64[43];
y[41] = b64[42];
y[42] = b64[41];
y[43] = b64[40];
y[44] = b64[47];
y[45] = b64[46];
y[46] = b64[45];
y[47] = b64[44];
y[48] = b64[51];
y[49] = b64[50];
y[50] = b64[49];
y[51] = b64[48];
y[52] = b64[55];
y[53] = b64[54];
y[54] = b64[53];
y[55] = b64[52];
y[56] = b64[59];
y[57] = b64[58];
y[58] = b64[57];
y[59] = b64[56];
y[60] = b64[63];
y[61] = b64[62];
y[62] = b64[61];
y[63] = b64[60];
#endif #endif
ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2); ROUND1(A, B, C, D, 0, Sa, 1);
ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4); ROUND1(D, A, B, C, 1, Sb, 2);
ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6); ROUND1(C, D, A, B, 2, Sc, 3);
ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8); ROUND1(B, C, D, A, 3, Sd, 4);
ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10); ROUND1(A, B, C, D, 4, Sa, 5);
ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12); ROUND1(D, A, B, C, 5, Sb, 6);
ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14); ROUND1(C, D, A, B, 6, Sc, 7);
ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16); ROUND1(B, C, D, A, 7, Sd, 8);
ROUND1(A, B, C, D, 8, Sa, 9);
ROUND1(D, A, B, C, 9, Sb, 10);
ROUND1(C, D, A, B, 10, Sc, 11);
ROUND1(B, C, D, A, 11, Sd, 12);
ROUND1(A, B, C, D, 12, Sa, 13);
ROUND1(D, A, B, C, 13, Sb, 14);
ROUND1(C, D, A, B, 14, Sc, 15);
ROUND1(B, C, D, A, 15, Sd, 16);
ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18); ROUND2(A, B, C, D, 1, Se, 17);
ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20); ROUND2(D, A, B, C, 6, Sf, 18);
ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22); ROUND2(C, D, A, B, 11, Sg, 19);
ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24); ROUND2(B, C, D, A, 0, Sh, 20);
ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26); ROUND2(A, B, C, D, 5, Se, 21);
ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28); ROUND2(D, A, B, C, 10, Sf, 22);
ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30); ROUND2(C, D, A, B, 15, Sg, 23);
ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32); ROUND2(B, C, D, A, 4, Sh, 24);
ROUND2(A, B, C, D, 9, Se, 25);
ROUND2(D, A, B, C, 14, Sf, 26);
ROUND2(C, D, A, B, 3, Sg, 27);
ROUND2(B, C, D, A, 8, Sh, 28);
ROUND2(A, B, C, D, 13, Se, 29);
ROUND2(D, A, B, C, 2, Sf, 30);
ROUND2(C, D, A, B, 7, Sg, 31);
ROUND2(B, C, D, A, 12, Sh, 32);
ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34); ROUND3(A, B, C, D, 5, Si, 33);
ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36); ROUND3(D, A, B, C, 8, Sj, 34);
ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38); ROUND3(C, D, A, B, 11, Sk, 35);
ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40); ROUND3(B, C, D, A, 14, Sl, 36);
ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42); ROUND3(A, B, C, D, 1, Si, 37);
ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44); ROUND3(D, A, B, C, 4, Sj, 38);
ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46); ROUND3(C, D, A, B, 7, Sk, 39);
ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48); ROUND3(B, C, D, A, 10, Sl, 40);
ROUND3(A, B, C, D, 13, Si, 41);
ROUND3(D, A, B, C, 0, Sj, 42);
ROUND3(C, D, A, B, 3, Sk, 43);
ROUND3(B, C, D, A, 6, Sl, 44);
ROUND3(A, B, C, D, 9, Si, 45);
ROUND3(D, A, B, C, 12, Sj, 46);
ROUND3(C, D, A, B, 15, Sk, 47);
ROUND3(B, C, D, A, 2, Sl, 48);
ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50); ROUND4(A, B, C, D, 0, Sm, 49);
ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52); ROUND4(D, A, B, C, 7, Sn, 50);
ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54); ROUND4(C, D, A, B, 14, So, 51);
ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56); ROUND4(B, C, D, A, 5, Sp, 52);
ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58); ROUND4(A, B, C, D, 12, Sm, 53);
ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60); ROUND4(D, A, B, C, 3, Sn, 54);
ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62); ROUND4(C, D, A, B, 10, So, 55);
ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64); ROUND4(B, C, D, A, 1, Sp, 56);
ROUND4(A, B, C, D, 8, Sm, 57);
ROUND4(D, A, B, C, 15, Sn, 58);
ROUND4(C, D, A, B, 6, So, 59);
ROUND4(B, C, D, A, 13, Sp, 60);
ROUND4(A, B, C, D, 4, Sm, 61);
ROUND4(D, A, B, C, 11, Sn, 62);
ROUND4(C, D, A, B, 2, So, 63);
ROUND4(B, C, D, A, 9, Sp, 64);
ctxt->md5_sta += A; ctxt->md5_sta += A;
ctxt->md5_stb += B; ctxt->md5_stb += B;

View File

@ -1,4 +1,4 @@
/* $Id: md5.h,v 1.3 2001/01/09 16:07:13 momjian Exp $ */ /* $Id: md5.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/* /*
@ -35,8 +35,10 @@
#define MD5_BUFLEN 64 #define MD5_BUFLEN 64
typedef struct { typedef struct
union { {
union
{
uint32 md5_state32[4]; uint32 md5_state32[4];
uint8 md5_state8[16]; uint8 md5_state8[16];
} md5_st; } md5_st;
@ -47,7 +49,8 @@ typedef struct {
#define md5_std md5_st.md5_state32[3] #define md5_std md5_st.md5_state32[3]
#define md5_st8 md5_st.md5_state8 #define md5_st8 md5_st.md5_state8
union { union
{
uint64 md5_count64; uint64 md5_count64;
uint8 md5_count8[8]; uint8 md5_count8[8];
} md5_count; } md5_count;

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: mhash.c,v 1.2 2001/02/10 02:31:26 tgl Exp $ * $Id: mhash.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -37,12 +37,12 @@
static uint static uint
pg_mhash_len(pg_digest * hash); pg_mhash_len(pg_digest * hash);
static uint8 * static uint8 *pg_mhash_digest(pg_digest * hash, uint8 *src,
pg_mhash_digest(pg_digest *hash, uint8 *src,
uint len, uint8 *buf); uint len, uint8 *buf);
static uint static uint
pg_mhash_len(pg_digest *h) { pg_mhash_len(pg_digest * h)
{
return mhash_get_block_size(h->misc.code); return mhash_get_block_size(h->misc.code);
} }
@ -52,6 +52,7 @@ pg_mhash_digest(pg_digest *h, uint8 *src, uint len, uint8 *dst)
uint8 *res; uint8 *res;
MHASH mh = mhash_init(h->misc.code); MHASH mh = mhash_init(h->misc.code);
mhash(mh, src, len); mhash(mh, src, len);
res = mhash_end(mh); res = mhash_end(mh);
@ -64,17 +65,21 @@ pg_mhash_digest(pg_digest *h, uint8 *src, uint len, uint8 *dst)
pg_digest * pg_digest *
pg_find_digest(pg_digest * h, char *name) pg_find_digest(pg_digest * h, char *name)
{ {
size_t hnum, i, b; size_t hnum,
i,
b;
char *mname; char *mname;
hnum = mhash_count(); hnum = mhash_count();
for (i = 0; i <= hnum; i++) { for (i = 0; i <= hnum; i++)
{
mname = mhash_get_hash_name(i); mname = mhash_get_hash_name(i);
if (mname == NULL) if (mname == NULL)
continue; continue;
b = strcasecmp(name, mname); b = strcasecmp(name, mname);
free(mname); free(mname);
if (!b) { if (!b)
{
h->name = mhash_get_hash_name(i); h->name = mhash_get_hash_name(i);
h->length = pg_mhash_len; h->length = pg_mhash_len;
h->digest = pg_mhash_digest; h->digest = pg_mhash_digest;
@ -84,4 +89,3 @@ pg_find_digest(pg_digest *h, char *name)
} }
return NULL; return NULL;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: openssl.c,v 1.2 2001/02/10 02:31:26 tgl Exp $ * $Id: openssl.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -41,7 +41,8 @@ static uint8 *
pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf); pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static uint static uint
pg_ossl_len(pg_digest *h) { pg_ossl_len(pg_digest * h)
{
return EVP_MD_size((EVP_MD *) h->misc.ptr); return EVP_MD_size((EVP_MD *) h->misc.ptr);
} }
@ -65,7 +66,8 @@ pg_find_digest(pg_digest *h, char *name)
{ {
const EVP_MD *md; const EVP_MD *md;
if (!pg_openssl_initialized) { if (!pg_openssl_initialized)
{
OpenSSL_add_all_digests(); OpenSSL_add_all_digests();
pg_openssl_initialized = 1; pg_openssl_initialized = 1;
} }
@ -81,5 +83,3 @@ pg_find_digest(pg_digest *h, char *name)
return h; return h;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.c,v 1.6 2001/02/10 02:31:26 tgl Exp $ * $Id: pgcrypto.c,v 1.7 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -60,8 +60,10 @@ digest(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, hlen; uint len,
pg_digest *h, _hbuf; hlen;
pg_digest *h,
_hbuf;
text *res; text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
@ -93,7 +95,8 @@ Datum
digest_exists(PG_FUNCTION_ARGS) digest_exists(PG_FUNCTION_ARGS)
{ {
text *name; text *name;
pg_digest _hbuf, *res; pg_digest _hbuf,
*res;
if (PG_ARGISNULL(0)) if (PG_ARGISNULL(0))
PG_RETURN_NULL(); PG_RETURN_NULL();
@ -117,7 +120,8 @@ find_digest(pg_digest *hbuf, text *name, int silent)
uint len; uint len;
len = VARSIZE(name) - VARHDRSZ; len = VARSIZE(name) - VARHDRSZ;
if (len >= NAMEDATALEN) { if (len >= NAMEDATALEN)
{
if (silent) if (silent)
return NULL; return NULL;
elog(ERROR, "Hash type does not exist (name too long)"); elog(ERROR, "Hash type does not exist (name too long)");
@ -132,4 +136,3 @@ find_digest(pg_digest *hbuf, text *name, int silent)
elog(ERROR, "Hash type does not exist: '%s'", buf); elog(ERROR, "Hash type does not exist: '%s'", buf);
return p; return p;
} }

View File

@ -26,20 +26,22 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.h,v 1.2 2001/01/09 16:07:13 momjian Exp $ * $Id: pgcrypto.h,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#ifndef _PG_CRYPTO_H #ifndef _PG_CRYPTO_H
#define _PG_CRYPTO_H #define _PG_CRYPTO_H
typedef struct _pg_digest pg_digest; typedef struct _pg_digest pg_digest;
struct _pg_digest { struct _pg_digest
{
char *name; char *name;
uint (*length) (pg_digest * h); uint (*length) (pg_digest * h);
uint8 *(*digest) (pg_digest * h, uint8 *data, uint8 *(*digest) (pg_digest * h, uint8 *data,
uint dlen, uint8 *buf); uint dlen, uint8 *buf);
/* private */ /* private */
union { union
{
uint code; uint code;
const void *ptr; const void *ptr;
} misc; } misc;

View File

@ -1,4 +1,4 @@
/* $Id: sha1.c,v 1.4 2001/02/10 02:31:26 tgl Exp $ */ /* $Id: sha1.c,v 1.5 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/* /*
@ -50,6 +50,7 @@
/* constant table */ /* constant table */
static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
#define K(t) _K[(t) / 20] #define K(t) _K[(t) / 20]
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) #define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
@ -87,74 +88,135 @@ static void
sha1_step(ctxt) sha1_step(ctxt)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
{ {
uint32 a, b, c, d, e; uint32 a,
size_t t, s; b,
c,
d,
e;
size_t t,
s;
uint32 tmp; uint32 tmp;
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
struct sha1_ctxt tctxt; struct sha1_ctxt tctxt;
bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64); bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2]; ctxt->m.b8[0] = tctxt.m.b8[3];
ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0]; ctxt->m.b8[1] = tctxt.m.b8[2];
ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6]; ctxt->m.b8[2] = tctxt.m.b8[1];
ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4]; ctxt->m.b8[3] = tctxt.m.b8[0];
ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10]; ctxt->m.b8[4] = tctxt.m.b8[7];
ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8]; ctxt->m.b8[5] = tctxt.m.b8[6];
ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14]; ctxt->m.b8[6] = tctxt.m.b8[5];
ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12]; ctxt->m.b8[7] = tctxt.m.b8[4];
ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18]; ctxt->m.b8[8] = tctxt.m.b8[11];
ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16]; ctxt->m.b8[9] = tctxt.m.b8[10];
ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22]; ctxt->m.b8[10] = tctxt.m.b8[9];
ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20]; ctxt->m.b8[11] = tctxt.m.b8[8];
ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26]; ctxt->m.b8[12] = tctxt.m.b8[15];
ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24]; ctxt->m.b8[13] = tctxt.m.b8[14];
ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30]; ctxt->m.b8[14] = tctxt.m.b8[13];
ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28]; ctxt->m.b8[15] = tctxt.m.b8[12];
ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34]; ctxt->m.b8[16] = tctxt.m.b8[19];
ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32]; ctxt->m.b8[17] = tctxt.m.b8[18];
ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38]; ctxt->m.b8[18] = tctxt.m.b8[17];
ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36]; ctxt->m.b8[19] = tctxt.m.b8[16];
ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42]; ctxt->m.b8[20] = tctxt.m.b8[23];
ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40]; ctxt->m.b8[21] = tctxt.m.b8[22];
ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46]; ctxt->m.b8[22] = tctxt.m.b8[21];
ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44]; ctxt->m.b8[23] = tctxt.m.b8[20];
ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50]; ctxt->m.b8[24] = tctxt.m.b8[27];
ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48]; ctxt->m.b8[25] = tctxt.m.b8[26];
ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54]; ctxt->m.b8[26] = tctxt.m.b8[25];
ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52]; ctxt->m.b8[27] = tctxt.m.b8[24];
ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58]; ctxt->m.b8[28] = tctxt.m.b8[31];
ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56]; ctxt->m.b8[29] = tctxt.m.b8[30];
ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62]; ctxt->m.b8[30] = tctxt.m.b8[29];
ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60]; ctxt->m.b8[31] = tctxt.m.b8[28];
ctxt->m.b8[32] = tctxt.m.b8[35];
ctxt->m.b8[33] = tctxt.m.b8[34];
ctxt->m.b8[34] = tctxt.m.b8[33];
ctxt->m.b8[35] = tctxt.m.b8[32];
ctxt->m.b8[36] = tctxt.m.b8[39];
ctxt->m.b8[37] = tctxt.m.b8[38];
ctxt->m.b8[38] = tctxt.m.b8[37];
ctxt->m.b8[39] = tctxt.m.b8[36];
ctxt->m.b8[40] = tctxt.m.b8[43];
ctxt->m.b8[41] = tctxt.m.b8[42];
ctxt->m.b8[42] = tctxt.m.b8[41];
ctxt->m.b8[43] = tctxt.m.b8[40];
ctxt->m.b8[44] = tctxt.m.b8[47];
ctxt->m.b8[45] = tctxt.m.b8[46];
ctxt->m.b8[46] = tctxt.m.b8[45];
ctxt->m.b8[47] = tctxt.m.b8[44];
ctxt->m.b8[48] = tctxt.m.b8[51];
ctxt->m.b8[49] = tctxt.m.b8[50];
ctxt->m.b8[50] = tctxt.m.b8[49];
ctxt->m.b8[51] = tctxt.m.b8[48];
ctxt->m.b8[52] = tctxt.m.b8[55];
ctxt->m.b8[53] = tctxt.m.b8[54];
ctxt->m.b8[54] = tctxt.m.b8[53];
ctxt->m.b8[55] = tctxt.m.b8[52];
ctxt->m.b8[56] = tctxt.m.b8[59];
ctxt->m.b8[57] = tctxt.m.b8[58];
ctxt->m.b8[58] = tctxt.m.b8[57];
ctxt->m.b8[59] = tctxt.m.b8[56];
ctxt->m.b8[60] = tctxt.m.b8[63];
ctxt->m.b8[61] = tctxt.m.b8[62];
ctxt->m.b8[62] = tctxt.m.b8[61];
ctxt->m.b8[63] = tctxt.m.b8[60];
#endif #endif
a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); a = H(0);
b = H(1);
c = H(2);
d = H(3);
e = H(4);
for (t = 0; t < 20; t++) { for (t = 0; t < 20; t++)
{
s = t & 0x0f; s = t & 0x0f;
if (t >= 16) { if (t >= 16)
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
}
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 20; t < 40; t++) { for (t = 20; t < 40; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 40; t < 60; t++) { for (t = 40; t < 60; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 60; t < 80; t++) { for (t = 60; t < 80; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
H(0) = H(0) + a; H(0) = H(0) + a;
@ -191,7 +253,8 @@ sha1_pad(ctxt)
padstart = COUNT % 64; padstart = COUNT % 64;
padlen = 64 - padstart; padlen = 64 - padstart;
if (padlen < 8) { if (padlen < 8)
{
bzero(&ctxt->m.b8[padstart], padlen); bzero(&ctxt->m.b8[padstart], padlen);
COUNT += padlen; COUNT += padlen;
COUNT %= 64; COUNT %= 64;
@ -203,15 +266,23 @@ sha1_pad(ctxt)
COUNT += (padlen - 8); COUNT += (padlen - 8);
COUNT %= 64; COUNT %= 64;
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[1]);
PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[2]);
PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[3]);
PUTPAD(ctxt->c.b8[4]);
PUTPAD(ctxt->c.b8[5]);
PUTPAD(ctxt->c.b8[6]);
PUTPAD(ctxt->c.b8[7]);
#else #else
PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[6]);
PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[5]);
PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[4]);
PUTPAD(ctxt->c.b8[3]);
PUTPAD(ctxt->c.b8[2]);
PUTPAD(ctxt->c.b8[1]);
PUTPAD(ctxt->c.b8[0]);
#endif #endif
} }
@ -230,7 +301,8 @@ sha1_loop(ctxt, input0, len)
input = (const uint8 *) input0; input = (const uint8 *) input0;
off = 0; off = 0;
while (off < len) { while (off < len)
{
gapstart = COUNT % 64; gapstart = COUNT % 64;
gaplen = 64 - gapstart; gaplen = 64 - gapstart;
@ -257,16 +329,26 @@ sha1_result(ctxt, digest0)
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
bcopy(&ctxt->h.b8[0], digest, 20); bcopy(&ctxt->h.b8[0], digest, 20);
#else #else
digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2]; digest[0] = ctxt->h.b8[3];
digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0]; digest[1] = ctxt->h.b8[2];
digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6]; digest[2] = ctxt->h.b8[1];
digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4]; digest[3] = ctxt->h.b8[0];
digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10]; digest[4] = ctxt->h.b8[7];
digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8]; digest[5] = ctxt->h.b8[6];
digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14]; digest[6] = ctxt->h.b8[5];
digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12]; digest[7] = ctxt->h.b8[4];
digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18]; digest[8] = ctxt->h.b8[11];
digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16]; digest[9] = ctxt->h.b8[10];
digest[10] = ctxt->h.b8[9];
digest[11] = ctxt->h.b8[8];
digest[12] = ctxt->h.b8[15];
digest[13] = ctxt->h.b8[14];
digest[14] = ctxt->h.b8[13];
digest[15] = ctxt->h.b8[12];
digest[16] = ctxt->h.b8[19];
digest[17] = ctxt->h.b8[18];
digest[18] = ctxt->h.b8[17];
digest[19] = ctxt->h.b8[16];
#endif #endif
} }

View File

@ -1,4 +1,4 @@
/* $Id: sha1.h,v 1.3 2001/01/09 16:07:13 momjian Exp $ */ /* $Id: sha1.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */
/* /*
@ -38,16 +38,20 @@
#ifndef _NETINET6_SHA1_H_ #ifndef _NETINET6_SHA1_H_
#define _NETINET6_SHA1_H_ #define _NETINET6_SHA1_H_
struct sha1_ctxt { struct sha1_ctxt
union { {
union
{
uint8 b8[20]; uint8 b8[20];
uint32 b32[5]; uint32 b32[5];
} h; } h;
union { union
{
uint8 b8[8]; uint8 b8[8];
uint64 b64[1]; uint64 b64[1];
} c; } c;
union { union
{
uint8 b8[64]; uint8 b8[64];
uint32 b32[16]; uint32 b32[16];
} m; } m;
@ -61,6 +65,7 @@ extern void sha1_result (struct sha1_ctxt *, caddr_t);
/* compatibilty with other SHA1 source codes */ /* compatibilty with other SHA1 source codes */
typedef struct sha1_ctxt SHA1_CTX; typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Init(x) sha1_init((x)) #define SHA1Init(x) sha1_init((x))
#define SHA1Update(x, y, z) sha1_loop((x), (y), (z)) #define SHA1Update(x, y, z) sha1_loop((x), (y), (z))
#define SHA1Final(x, y) sha1_result((y), (x)) #define SHA1Final(x, y) sha1_result((y), (x))

View File

@ -19,10 +19,12 @@ PG_FUNCTION_INFO_V1(_rserv_debug_);
Datum _rserv_log_(PG_FUNCTION_ARGS); Datum _rserv_log_(PG_FUNCTION_ARGS);
Datum _rserv_sync_(PG_FUNCTION_ARGS); Datum _rserv_sync_(PG_FUNCTION_ARGS);
Datum _rserv_debug_(PG_FUNCTION_ARGS); Datum _rserv_debug_(PG_FUNCTION_ARGS);
#else #else
HeapTuple _rserv_log_(void); HeapTuple _rserv_log_(void);
int32 _rserv_sync_(int32); int32 _rserv_sync_(int32);
int32 _rserv_debug_(int32); int32 _rserv_debug_(int32);
#endif #endif
static int debug = 0; static int debug = 0;
@ -203,6 +205,7 @@ _rserv_sync_(int32 server)
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 server = PG_GETARG_INT32(0); int32 server = PG_GETARG_INT32(0);
#endif #endif
char sql[8192]; char sql[8192];
char buf[8192]; char buf[8192];
@ -248,6 +251,7 @@ _rserv_debug_(int32 newval)
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 newval = PG_GETARG_INT32(0); int32 newval = PG_GETARG_INT32(0);
#endif #endif
int32 oldval = debug; int32 oldval = debug;
@ -271,21 +275,27 @@ OutputValue(char *key, char *buf, int size)
{ {
switch (*key) switch (*key)
{ {
case '\\': subst ="\\\\"; case '\\':
subst = "\\\\";
slen = 2; slen = 2;
break; break;
case ' ': subst = "\\011"; case ' ':
subst = "\\011";
slen = 4; slen = 4;
break; break;
case '\n': subst = "\\012"; case '\n':
subst = "\\012";
slen = 4; slen = 4;
break; break;
case '\'': subst = "\\047"; case '\'':
subst = "\\047";
slen = 4; slen = 4;
break; break;
case '\0': out[i] = 0; case '\0':
out[i] = 0;
return (out); return (out);
default: slen = 1; default:
slen = 1;
break; break;
} }

View File

@ -20,30 +20,32 @@ unsigned int parse_buffer_pos( void );
extern void seg_flush_scanner_buffer(void); /* defined in segscan.l */ extern void seg_flush_scanner_buffer(void); /* defined in segscan.l */
void set_parse_buffer( char* s ) void
set_parse_buffer(char *s)
{ {
PARSE_BUFFER = s; PARSE_BUFFER = s;
PARSE_BUFFER_SIZE = strlen(s); PARSE_BUFFER_SIZE = strlen(s);
if ( PARSE_BUFFER_SIZE == 0 ) { if (PARSE_BUFFER_SIZE == 0)
elog(ERROR, "seg_in: can't parse an empty string"); elog(ERROR, "seg_in: can't parse an empty string");
}
PARSE_BUFFER_PTR = PARSE_BUFFER; PARSE_BUFFER_PTR = PARSE_BUFFER;
SCANNER_POS = 0; SCANNER_POS = 0;
} }
void reset_parse_buffer( void ) void
reset_parse_buffer(void)
{ {
PARSE_BUFFER_PTR = PARSE_BUFFER; PARSE_BUFFER_PTR = PARSE_BUFFER;
SCANNER_POS = 0; SCANNER_POS = 0;
seg_flush_scanner_buffer(); seg_flush_scanner_buffer();
} }
int read_parse_buffer( void ) int
read_parse_buffer(void)
{ {
int c; int c;
/* /*
c = *PARSE_BUFFER_PTR++; * c = *PARSE_BUFFER_PTR++; SCANNER_POS++;
SCANNER_POS++;
*/ */
c = PARSE_BUFFER[SCANNER_POS]; c = PARSE_BUFFER[SCANNER_POS];
if (SCANNER_POS < PARSE_BUFFER_SIZE) if (SCANNER_POS < PARSE_BUFFER_SIZE)
@ -51,29 +53,32 @@ int read_parse_buffer( void )
return c; return c;
} }
char * parse_buffer( void ) char *
parse_buffer(void)
{ {
return PARSE_BUFFER; return PARSE_BUFFER;
} }
unsigned int parse_buffer_curr_char( void ) unsigned int
parse_buffer_curr_char(void)
{ {
return PARSE_BUFFER[SCANNER_POS]; return PARSE_BUFFER[SCANNER_POS];
} }
char * parse_buffer_ptr( void ) char *
parse_buffer_ptr(void)
{ {
return PARSE_BUFFER_PTR; return PARSE_BUFFER_PTR;
} }
unsigned int parse_buffer_pos( void ) unsigned int
parse_buffer_pos(void)
{ {
return SCANNER_POS; return SCANNER_POS;
} }
unsigned int parse_buffer_size( void ) unsigned int
parse_buffer_size(void)
{ {
return PARSE_BUFFER_SIZE; return PARSE_BUFFER_SIZE;
} }

View File

@ -27,6 +27,7 @@
extern void set_parse_buffer(char *str); extern void set_parse_buffer(char *str);
extern int seg_yyparse(); extern int seg_yyparse();
/* /*
extern int seg_yydebug; extern int seg_yydebug;
*/ */
@ -99,12 +100,14 @@ SEG *
seg_in(char *str) seg_in(char *str)
{ {
SEG *result = palloc(sizeof(SEG)); SEG *result = palloc(sizeof(SEG));
set_parse_buffer(str); set_parse_buffer(str);
/* /*
seg_yydebug = 1; * seg_yydebug = 1;
*/ */
if ( seg_yyparse(result) != 0 ) { if (seg_yyparse(result) != 0)
{
pfree(result); pfree(result);
return NULL; return NULL;
} }
@ -125,31 +128,38 @@ seg_out(SEG *seg)
char *result; char *result;
char *p; char *p;
if (seg == NULL) return(NULL); if (seg == NULL)
return (NULL);
p = result = (char *) palloc(40); p = result = (char *) palloc(40);
if ( seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~' ) { if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~')
p += sprintf(p, "%c", seg->l_ext); p += sprintf(p, "%c", seg->l_ext);
}
if ( seg->lower == seg->upper && seg->l_ext == seg->u_ext ) { if (seg->lower == seg->upper && seg->l_ext == seg->u_ext)
/* indicates that this interval was built by seg_in off a single point */ {
/*
* indicates that this interval was built by seg_in off a single
* point
*/
p += restore(p, seg->lower, seg->l_sigd); p += restore(p, seg->lower, seg->l_sigd);
} }
else { else
if ( seg->l_ext != '-' ) { {
if (seg->l_ext != '-')
{
/* print the lower boudary if exists */ /* print the lower boudary if exists */
p += restore(p, seg->lower, seg->l_sigd); p += restore(p, seg->lower, seg->l_sigd);
p += sprintf(p, " "); p += sprintf(p, " ");
} }
p += sprintf(p, ".."); p += sprintf(p, "..");
if ( seg->u_ext != '-' ) { if (seg->u_ext != '-')
{
/* print the upper boudary if exists */ /* print the upper boudary if exists */
p += sprintf(p, " "); p += sprintf(p, " ");
if ( seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~' ) { if (seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~')
p += sprintf(p, "%c", seg->u_ext); p += sprintf(p, "%c", seg->u_ext);
}
p += restore(p, seg->upper, seg->u_sigd); p += restore(p, seg->upper, seg->u_sigd);
} }
} }
@ -209,9 +219,10 @@ gseg_consistent(GISTENTRY *entry,
SEG * query, SEG * query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
/* /*
** if entry is not leaf, use gseg_internal_consistent, * * if entry is not leaf, use gseg_internal_consistent, * else use
** else use gseg_leaf_consistent * gseg_leaf_consistent
*/ */
if (GIST_LEAF(entry)) if (GIST_LEAF(entry))
return (gseg_leaf_consistent((SEG *) (entry->pred), query, strategy)); return (gseg_leaf_consistent((SEG *) (entry->pred), query, strategy));
@ -226,7 +237,8 @@ gseg_consistent(GISTENTRY *entry,
SEG * SEG *
gseg_union(bytea *entryvec, int *sizep) gseg_union(bytea *entryvec, int *sizep)
{ {
int numranges, i; int numranges,
i;
SEG *out = (SEG *) NULL; SEG *out = (SEG *) NULL;
SEG *tmp; SEG *tmp;
@ -238,17 +250,21 @@ gseg_union(bytea *entryvec, int *sizep)
tmp = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[0]).pred; tmp = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[0]).pred;
*sizep = sizeof(SEG); *sizep = sizeof(SEG);
for (i = 1; i < numranges; i++) { for (i = 1; i < numranges; i++)
{
out = gseg_binary_union(tmp, (SEG *) out = gseg_binary_union(tmp, (SEG *)
(((GISTENTRY *) (VARDATA(entryvec)))[i]).pred, (((GISTENTRY *) (VARDATA(entryvec)))[i]).pred,
sizep); sizep);
#ifdef GIST_DEBUG #ifdef GIST_DEBUG
/* /*
fprintf(stderr, "\t%s ^ %s -> %s\n", seg_out(tmp), seg_out((SEG *)(((GISTENTRY *)(VARDATA(entryvec)))[i]).pred), seg_out(out)); * fprintf(stderr, "\t%s ^ %s -> %s\n", seg_out(tmp), seg_out((SEG
* *)(((GISTENTRY *)(VARDATA(entryvec)))[i]).pred), seg_out(out));
*/ */
#endif #endif
if (i > 1) pfree(tmp); if (i > 1)
pfree(tmp);
tmp = out; tmp = out;
} }
@ -279,7 +295,8 @@ float *
gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result) gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
{ {
Datum ud; Datum ud;
float tmp1, tmp2; float tmp1,
tmp2;
ud = (Datum) seg_union((SEG *) (origentry->pred), (SEG *) (newentry->pred)); ud = (Datum) seg_union((SEG *) (origentry->pred), (SEG *) (newentry->pred));
rt_seg_size((SEG *) ud, &tmp1); rt_seg_size((SEG *) ud, &tmp1);
@ -305,18 +322,30 @@ GIST_SPLITVEC *
gseg_picksplit(bytea *entryvec, gseg_picksplit(bytea *entryvec,
GIST_SPLITVEC *v) GIST_SPLITVEC *v)
{ {
OffsetNumber i, j; OffsetNumber i,
SEG *datum_alpha, *datum_beta; j;
SEG *datum_l, *datum_r; SEG *datum_alpha,
SEG *union_d, *union_dl, *union_dr; *datum_beta;
SEG *datum_l,
*datum_r;
SEG *union_d,
*union_dl,
*union_dr;
SEG *inter_d; SEG *inter_d;
bool firsttime; bool firsttime;
float size_alpha, size_beta, size_union, size_inter; float size_alpha,
float size_waste, waste; size_beta,
float size_l, size_r; size_union,
size_inter;
float size_waste,
waste;
float size_l,
size_r;
int nbytes; int nbytes;
OffsetNumber seed_1 = 0, seed_2 = 0; OffsetNumber seed_1 = 0,
OffsetNumber *left, *right; seed_2 = 0;
OffsetNumber *left,
*right;
OffsetNumber maxoff; OffsetNumber maxoff;
#ifdef GIST_DEBUG #ifdef GIST_DEBUG
@ -331,9 +360,11 @@ gseg_picksplit(bytea *entryvec,
firsttime = true; firsttime = true;
waste = 0.0; waste = 0.0;
for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
{
datum_alpha = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[i].pred); datum_alpha = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[i].pred);
for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) { for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
{
datum_beta = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[j].pred); datum_beta = (SEG *) (((GISTENTRY *) (VARDATA(entryvec)))[j].pred);
/* compute the wasted space by unioning these guys */ /* compute the wasted space by unioning these guys */
@ -350,11 +381,12 @@ gseg_picksplit(bytea *entryvec,
pfree(inter_d); pfree(inter_d);
/* /*
* are these a more promising split that what we've * are these a more promising split that what we've already
* already seen? * seen?
*/ */
if (size_waste > waste || firsttime) { if (size_waste > waste || firsttime)
{
waste = size_waste; waste = size_waste;
seed_1 = i; seed_1 = i;
seed_2 = j; seed_2 = j;
@ -377,31 +409,34 @@ gseg_picksplit(bytea *entryvec,
/* /*
* Now split up the regions between the two seeds. An important * Now split up the regions between the two seeds. An important
* property of this split algorithm is that the split vector v * property of this split algorithm is that the split vector v has the
* has the indices of items to be split in order in its left and * indices of items to be split in order in its left and right
* right vectors. We exploit this property by doing a merge in * vectors. We exploit this property by doing a merge in the code
* the code that actually splits the page. * that actually splits the page.
* *
* For efficiency, we also place the new index tuple in this loop. * For efficiency, we also place the new index tuple in this loop. This
* This is handled at the very end, when we have placed all the * is handled at the very end, when we have placed all the existing
* existing tuples and i == maxoff + 1. * tuples and i == maxoff + 1.
*/ */
maxoff = OffsetNumberNext(maxoff); maxoff = OffsetNumberNext(maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
/* /*
* If we've already decided where to place this item, just * If we've already decided where to place this item, just put it
* put it on the right list. Otherwise, we need to figure * on the right list. Otherwise, we need to figure out which page
* out which page needs the least enlargement in order to * needs the least enlargement in order to store the item.
* store the item.
*/ */
if (i == seed_1) { if (i == seed_1)
{
*left++ = i; *left++ = i;
v->spl_nleft++; v->spl_nleft++;
continue; continue;
} else if (i == seed_2) { }
else if (i == seed_2)
{
*right++ = i; *right++ = i;
v->spl_nright++; v->spl_nright++;
continue; continue;
@ -415,14 +450,17 @@ gseg_picksplit(bytea *entryvec,
rt_seg_size((SEG *) union_dr, &size_beta); rt_seg_size((SEG *) union_dr, &size_beta);
/* pick which page to add it to */ /* pick which page to add it to */
if (size_alpha - size_l < size_beta - size_r) { if (size_alpha - size_l < size_beta - size_r)
{
pfree(datum_l); pfree(datum_l);
pfree(union_dr); pfree(union_dr);
datum_l = union_dl; datum_l = union_dl;
size_l = size_alpha; size_l = size_alpha;
*left++ = i; *left++ = i;
v->spl_nleft++; v->spl_nleft++;
} else { }
else
{
pfree(datum_r); pfree(datum_r);
pfree(union_dl); pfree(union_dl);
datum_r = union_dr; datum_r = union_dr;
@ -447,7 +485,8 @@ gseg_same(SEG *b1, SEG *b2, bool *result)
{ {
if (seg_same(b1, b2)) if (seg_same(b1, b2))
*result = TRUE; *result = TRUE;
else *result = FALSE; else
*result = FALSE;
#ifdef GIST_DEBUG #ifdef GIST_DEBUG
fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE"));
@ -470,7 +509,8 @@ gseg_leaf_consistent(SEG *key,
fprintf(stderr, "leaf_consistent, %d\n", strategy); fprintf(stderr, "leaf_consistent, %d\n", strategy);
#endif #endif
switch(strategy) { switch (strategy)
{
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
retval = (bool) seg_left(key, query); retval = (bool) seg_left(key, query);
break; break;
@ -512,7 +552,8 @@ gseg_internal_consistent(SEG *key,
fprintf(stderr, "internal_consistent, %d\n", strategy); fprintf(stderr, "internal_consistent, %d\n", strategy);
#endif #endif
switch(strategy) { switch (strategy)
{
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
case RTOverLeftStrategyNumber: case RTOverLeftStrategyNumber:
retval = (bool) seg_over_left(key, query); retval = (bool) seg_over_left(key, query);
@ -723,6 +764,7 @@ seg_size(SEG *a)
int32 int32
seg_cmp(SEG * a, SEG * b) seg_cmp(SEG * a, SEG * b)
{ {
/* /*
* First compare on lower boundary position * First compare on lower boundary position
*/ */
@ -730,13 +772,13 @@ seg_cmp(SEG *a, SEG *b)
return -1; return -1;
if (a->lower > b->lower) if (a->lower > b->lower)
return 1; return 1;
/* /*
* 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 * A '-' lower bound is < any other kind (this could only be relevant if
* if -HUGE is used as a regular data value). * -HUGE is used as a regular data value). A '<' lower bound is < any
* A '<' lower bound is < any other kind except '-'. * other kind except '-'. A '>' lower bound is > any other kind.
* A '>' lower bound is > any other kind.
*/ */
if (a->l_ext != b->l_ext) if (a->l_ext != b->l_ext)
{ {
@ -753,13 +795,17 @@ seg_cmp(SEG *a, SEG *b)
if (b->l_ext == '>') if (b->l_ext == '>')
return -1; return -1;
} }
/* /*
* For other boundary types, consider # of significant digits first. * For other boundary types, consider # of significant digits first.
*/ */
if ( a->l_sigd < b->l_sigd ) /* (a) is blurred and is likely to include (b) */ if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include
* (b) */
return -1; return -1;
if ( a->l_sigd > b->l_sigd ) /* (a) is less blurred and is likely to be included in (b) */ if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be
* included in (b) */
return 1; return 1;
/* /*
* For same # of digits, an approximate boundary is more blurred than * For same # of digits, an approximate boundary is more blurred than
* exact. * exact.
@ -784,13 +830,13 @@ seg_cmp(SEG *a, SEG *b)
return -1; return -1;
if (a->upper > b->upper) if (a->upper > b->upper)
return 1; return 1;
/* /*
* 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 * A '-' upper bound is > any other kind (this could only be relevant if
* if HUGE is used as a regular data value). * HUGE is used as a regular data value). A '<' upper bound is < any
* A '<' upper bound is < any other kind. * other kind. A '>' upper bound is > any other kind except '-'.
* A '>' upper bound is > any other kind except '-'.
*/ */
if (a->u_ext != b->u_ext) if (a->u_ext != b->u_ext)
{ {
@ -807,14 +853,18 @@ seg_cmp(SEG *a, SEG *b)
if (b->u_ext == '>') if (b->u_ext == '>')
return -1; return -1;
} }
/* /*
* For other boundary types, consider # of significant digits first. * For other boundary types, consider # of significant digits first.
* Note result here is converse of the lower-boundary case. * Note result here is converse of the lower-boundary case.
*/ */
if ( a->u_sigd < b->u_sigd ) /* (a) is blurred and is likely to include (b) */ if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include
* (b) */
return 1; return 1;
if ( a->u_sigd > b->u_sigd ) /* (a) is less blurred and is likely to be included in (b) */ if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be
* included in (b) */
return -1; return -1;
/* /*
* For same # of digits, an approximate boundary is more blurred than * For same # of digits, an approximate boundary is more blurred than
* exact. Again, result is converse of lower-boundary case. * exact. Again, result is converse of lower-boundary case.
@ -875,7 +925,8 @@ seg_different(SEG *a, SEG *b)
* is similar to %.ng except it prints 8.00 where %.ng would * is similar to %.ng except it prints 8.00 where %.ng would
* print 8 * print 8
*/ */
static int restore ( char * result, float val, int n ) static int
restore(char *result, float val, int n)
{ {
static char efmt[8] = {'%', '-', '1', '5', '.', '#', 'e', 0}; static char efmt[8] = {'%', '-', '1', '5', '.', '#', 'e', 0};
char buf[25] = { char buf[25] = {
@ -888,106 +939,129 @@ static int restore ( char * result, float val, int n )
char *p; char *p;
char *mant; char *mant;
int exp; int exp;
int i, dp, sign; int i,
dp,
sign;
/* put a cap on the number of siugnificant digits to avoid /*
nonsense in the output */ * put a cap on the number of siugnificant digits to avoid nonsense in
* the output
*/
n = min(n, FLT_DIG); n = min(n, FLT_DIG);
/* remember the sign */ /* remember the sign */
sign = (val < 0 ? 1 : 0); sign = (val < 0 ? 1 : 0);
efmt[5] = '0' + (n-1)%10; /* makes %-15.(n-1)e -- this format guarantees that efmt[5] = '0' + (n - 1) % 10; /* makes %-15.(n-1)e -- this
the exponent is always present */ * format guarantees that the
* exponent is always present */
sprintf(result, efmt, val); sprintf(result, efmt, val);
/* trim the spaces left by the %e */ /* trim the spaces left by the %e */
for( p = result; *p != ' '; p++ ); *p = '\0'; for (p = result; *p != ' '; p++);
*p = '\0';
/* get the exponent */ /* get the exponent */
mant = (char *) strtok(strdup(result), "e"); mant = (char *) strtok(strdup(result), "e");
exp = atoi(strtok(NULL, "e")); exp = atoi(strtok(NULL, "e"));
if ( exp == 0 ) { if (exp == 0)
{
/* use the supplied mantyssa with sign */ /* use the supplied mantyssa with sign */
strcpy((char *) index(result, 'e'), ""); strcpy((char *) index(result, 'e'), "");
} }
else { else
if ( abs( exp ) <= 4 ) { {
/* remove the decimal point from the mantyssa and write the digits to the buf array */ if (abs(exp) <= 4)
for( p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++ ) { {
/*
* remove the decimal point from the mantyssa and write the
* digits to the buf array
*/
for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++)
{
buf[i] = *p; buf[i] = *p;
if( *p == '.' ) { if (*p == '.')
{
dp = i--; /* skip the decimal point */ dp = i--; /* skip the decimal point */
} }
} }
if (dp == 0) dp = i--; /* no decimal point was found in the above for() loop */ if (dp == 0)
dp = i--; /* no decimal point was found in the above
* for() loop */
if (exp > 0)
{
if (dp - 10 + exp >= n)
{
if ( exp > 0 ) {
if ( dp - 10 + exp >= n ) {
/* /*
the decimal point is behind the last significant digit; * the decimal point is behind the last significant
the digits in between must be converted to the exponent * digit; the digits in between must be converted to
and the decimal point placed after the first digit * the exponent and the decimal point placed after the
* first digit
*/ */
exp = dp - 10 + exp - n; exp = dp - 10 + exp - n;
buf[10 + n] = '\0'; buf[10 + n] = '\0';
/* insert the decimal point */ /* insert the decimal point */
if ( n > 1 ) { if (n > 1)
{
dp = 11; dp = 11;
for ( i = 23; i > dp; i-- ) { for (i = 23; i > dp; i--)
buf[i] = buf[i - 1]; buf[i] = buf[i - 1];
}
buf[dp] = '.'; buf[dp] = '.';
} }
/* adjust the exponent by the number of digits after the decimal point */ /*
if ( n > 1 ) { * adjust the exponent by the number of digits after
* the decimal point
*/
if (n > 1)
sprintf(&buf[11 + n], "e%d", exp + n - 1); sprintf(&buf[11 + n], "e%d", exp + n - 1);
} else
else {
sprintf(&buf[11], "e%d", exp + n - 1); sprintf(&buf[11], "e%d", exp + n - 1);
}
if ( sign ) { if (sign)
{
buf[9] = '-'; buf[9] = '-';
strcpy(result, &buf[9]); strcpy(result, &buf[9]);
} }
else { else
strcpy(result, &buf[10]); strcpy(result, &buf[10]);
} }
} else
else { /* insert the decimal point */ { /* insert the decimal point */
dp += exp; dp += exp;
for ( i = 23; i > dp; i-- ) { for (i = 23; i > dp; i--)
buf[i] = buf[i - 1]; buf[i] = buf[i - 1];
}
buf[11 + n] = '\0'; buf[11 + n] = '\0';
buf[dp] = '.'; buf[dp] = '.';
if ( sign ) { if (sign)
{
buf[9] = '-'; buf[9] = '-';
strcpy(result, &buf[9]); strcpy(result, &buf[9]);
} }
else { else
strcpy(result, &buf[10]); strcpy(result, &buf[10]);
} }
} }
} else
else { /* exp <= 0 */ { /* exp <= 0 */
dp += exp - 1; dp += exp - 1;
buf[10 + n] = '\0'; buf[10 + n] = '\0';
buf[dp] = '.'; buf[dp] = '.';
if ( sign ) { if (sign)
{
buf[dp - 2] = '-'; buf[dp - 2] = '-';
strcpy(result, &buf[dp - 2]); strcpy(result, &buf[dp - 2]);
} }
else { else
strcpy(result, &buf[dp - 1]); strcpy(result, &buf[dp - 1]);
} }
} }
}
/* do nothing for abs(exp) > 4; %e must be OK */ /* do nothing for abs(exp) > 4; %e must be OK */
/* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */ /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */
@ -1023,27 +1097,36 @@ seg_contains_float8(SEG *a, float8 *b)
/* find out the number of significant digits in a string representing /* find out the number of significant digits in a string representing
* a floating point number * a floating point number
*/ */
int significant_digits ( char* s ) int
significant_digits(char *s)
{ {
char *p = s; char *p = s;
int n, c, zeroes; int n,
c,
zeroes;
zeroes = 1; zeroes = 1;
/* skip leading zeroes and sign */ /* skip leading zeroes and sign */
for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p)); for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p));
/* skip decimal point and following zeroes */ /* skip decimal point and following zeroes */
for ( c = *p; (c == '0' || c == '.' ) && c != 0; c = *(++p) ) { for (c = *p; (c == '0' || c == '.') && c != 0; c = *(++p))
if ( c != '.') zeroes++; {
if (c != '.')
zeroes++;
} }
/* count significant digits (n) */ /* count significant digits (n) */
for ( c = *p, n = 0; c != 0; c = *(++p) ) { for (c = *p, n = 0; c != 0; c = *(++p))
if ( !( (c >= '0' && c <= '9') || (c == '.') ) ) break; {
if ( c != '.') n++; if (!((c >= '0' && c <= '9') || (c == '.')))
break;
if (c != '.')
n++;
} }
if (!n) return ( zeroes ); if (!n)
return (zeroes);
return (n); return (n);
} }

View File

@ -1,4 +1,5 @@
typedef struct SEG { typedef struct SEG
{
float lower; float lower;
float upper; float upper;
char l_sigd; char l_sigd;

View File

@ -1,4 +1,4 @@
/* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.10 2001/02/10 02:31:26 tgl Exp $ */ /* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.11 2001/03/22 03:59:10 momjian Exp $ */
#include "postgres.h" #include "postgres.h"
#include <ctype.h> #include <ctype.h>
@ -42,6 +42,7 @@ text_soundex(PG_FUNCTION_ARGS)
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
static const char *soundex_table = "01230120022455012623010202"; static const char *soundex_table = "01230120022455012623010202";
#define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A'] #define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A']
@ -114,4 +115,5 @@ main (int argc, char *argv[])
return 0; return 0;
} }
} }
#endif /* SOUNDEX_TEST */ #endif /* SOUNDEX_TEST */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.8 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.9 2001/03/22 03:59:11 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -76,6 +76,7 @@ vacuumlo(char *database, int verbose)
return -1; return -1;
} }
PQclear(res); PQclear(res);
/* /*
* Vacuum the temp table so that planner will generate decent plans * Vacuum the temp table so that planner will generate decent plans
* for the DELETEs below. * for the DELETEs below.
@ -96,13 +97,13 @@ vacuumlo(char *database, int verbose)
/* /*
* Now find any candidate tables who have columns of type oid. * Now find any candidate tables who have columns of type oid.
* *
* NOTE: the temp table formed above is ignored, because its real * NOTE: the temp table formed above is ignored, because its real table
* table name will be pg_something. Also, pg_largeobject will be * name will be pg_something. Also, pg_largeobject will be ignored.
* ignored. If either of these were scanned, obviously we'd end up * If either of these were scanned, obviously we'd end up with nothing
* with nothing to delete... * to delete...
* *
* NOTE: the system oid column is ignored, as it has attnum < 1. * NOTE: the system oid column is ignored, as it has attnum < 1. This
* This shouldn't matter for correctness, but it saves time. * shouldn't matter for correctness, but it saves time.
*/ */
buf[0] = '\0'; buf[0] = '\0';
strcat(buf, "SELECT c.relname, a.attname "); strcat(buf, "SELECT c.relname, a.attname ");
@ -135,9 +136,9 @@ vacuumlo(char *database, int verbose)
fprintf(stdout, "Checking %s in %s\n", field, table); fprintf(stdout, "Checking %s in %s\n", field, table);
/* /*
* We use a DELETE with implicit join for efficiency. This * We use a DELETE with implicit join for efficiency. This is a
* is a Postgres-ism and not portable to other DBMSs, but * Postgres-ism and not portable to other DBMSs, but then this
* then this whole program is a Postgres-ism. * whole program is a Postgres-ism.
*/ */
sprintf(buf, "DELETE FROM vacuum_l WHERE lo = \"%s\".\"%s\" ", sprintf(buf, "DELETE FROM vacuum_l WHERE lo = \"%s\".\"%s\" ",
table, field); table, field);
@ -159,8 +160,8 @@ vacuumlo(char *database, int verbose)
/* /*
* Run the actual deletes in a single transaction. Note that this * Run the actual deletes in a single transaction. Note that this
* would be a bad idea in pre-7.1 Postgres releases (since rolling * would be a bad idea in pre-7.1 Postgres releases (since rolling
* back a table delete used to cause problems), but it should * back a table delete used to cause problems), but it should be safe
* be safe now. * now.
*/ */
res = PQexec(conn, "begin"); res = PQexec(conn, "begin");
PQclear(res); PQclear(res);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.69 2001/01/24 19:42:46 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.70 2001/03/22 03:59:11 momjian Exp $
* *
* NOTES * NOTES
* The old interface functions have been converted to macros * The old interface functions have been converted to macros
@ -306,8 +306,8 @@ nocachegetattr(HeapTuple tuple,
int j; int j;
/* /*
* In for(), we test <= and not < because we want to see * In for(), we test <= and not < because we want to see if we
* if we can go past it in initializing offsets. * can go past it in initializing offsets.
*/ */
for (j = 0; j <= attnum; j++) for (j = 0; j <= attnum; j++)
{ {
@ -321,9 +321,9 @@ nocachegetattr(HeapTuple tuple,
} }
/* /*
* If slow is false, and we got here, we know that we have a tuple with * If slow is false, and we got here, we know that we have a tuple
* no nulls or varlenas before the target attribute. If possible, we * with no nulls or varlenas before the target attribute. If possible,
* also want to initialize the remainder of the attribute cached * we also want to initialize the remainder of the attribute cached
* offset values. * offset values.
*/ */
if (!slow) if (!slow)

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.52 2001/02/22 21:48:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.53 2001/03/22 03:59:11 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -45,9 +45,11 @@ index_formtuple(TupleDesc tupleDescriptor,
bool hasnull = false; bool hasnull = false;
uint16 tupmask = 0; uint16 tupmask = 0;
int numberOfAttributes = tupleDescriptor->natts; int numberOfAttributes = tupleDescriptor->natts;
#ifdef TOAST_INDEX_HACK #ifdef TOAST_INDEX_HACK
Datum untoasted_value[INDEX_MAX_KEYS]; Datum untoasted_value[INDEX_MAX_KEYS];
bool untoasted_free[INDEX_MAX_KEYS]; bool untoasted_free[INDEX_MAX_KEYS];
#endif #endif
if (numberOfAttributes > INDEX_MAX_KEYS) if (numberOfAttributes > INDEX_MAX_KEYS)
@ -79,8 +81,8 @@ index_formtuple(TupleDesc tupleDescriptor,
} }
/* /*
* If value is above size target, and is of a compressible datatype, * If value is above size target, and is of a compressible
* try to compress it in-line. * datatype, try to compress it in-line.
*/ */
if (VARATT_SIZE(untoasted_value[i]) > TOAST_INDEX_TARGET && if (VARATT_SIZE(untoasted_value[i]) > TOAST_INDEX_TARGET &&
!VARATT_IS_EXTENDED(untoasted_value[i]) && !VARATT_IS_EXTENDED(untoasted_value[i]) &&
@ -146,8 +148,8 @@ index_formtuple(TupleDesc tupleDescriptor,
/* /*
* We do this because DataFill wants to initialize a "tupmask" which * We do this because DataFill wants to initialize a "tupmask" which
* is used for HeapTuples, but we want an indextuple infomask. The * is used for HeapTuples, but we want an indextuple infomask. The
* only relevant info is the "has variable attributes" field. * only relevant info is the "has variable attributes" field. We have
* We have already set the hasnull bit above. * already set the hasnull bit above.
*/ */
if (tupmask & HEAP_HASVARLENA) if (tupmask & HEAP_HASVARLENA)
@ -315,9 +317,9 @@ nocache_index_getattr(IndexTuple tup,
} }
/* /*
* If slow is false, and we got here, we know that we have a tuple with * If slow is false, and we got here, we know that we have a tuple
* no nulls or varlenas before the target attribute. If possible, we * with no nulls or varlenas before the target attribute. If possible,
* also want to initialize the remainder of the attribute cached * we also want to initialize the remainder of the attribute cached
* offset values. * offset values.
*/ */
if (!slow) if (!slow)
@ -391,10 +393,8 @@ nocache_index_getattr(IndexTuple tup,
usecache = false; usecache = false;
} }
else else
{
off += att[i]->attlen; off += att[i]->attlen;
} }
}
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign); off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.57 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.58 2001/03/22 03:59:11 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -200,9 +200,10 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
continue; continue;
if (OidIsValid(thisState->typoutput)) if (OidIsValid(thisState->typoutput))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to avoid * If we have a toasted datum, forcibly detoast it here to
* memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
*/ */
if (thisState->typisvarlena) if (thisState->typisvarlena)
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr)); attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
@ -308,9 +309,10 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid, if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
&typoutput, &typelem, &typisvarlena)) &typoutput, &typelem, &typisvarlena))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to avoid * If we have a toasted datum, forcibly detoast it here to
* memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
*/ */
if (typisvarlena) if (typisvarlena)
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr)); attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
@ -405,6 +407,7 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
/* send # of bytes, and opaque data */ /* send # of bytes, and opaque data */
if (thisState->typisvarlena) if (thisState->typisvarlena)
{ {
/* /*
* If we have a toasted datum, must detoast before sending. * If we have a toasted datum, must detoast before sending.
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.71 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.72 2001/03/22 03:59:11 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
@ -242,9 +242,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
/* /*
* We do not need to check every single field here, and in fact * We do not need to check every single field here, and in fact
* some fields such as attdispersion probably shouldn't be * some fields such as attdispersion probably shouldn't be
* compared. We can also disregard attnum (it was used to * compared. We can also disregard attnum (it was used to place
* place the row in the attrs array) and everything derived * the row in the attrs array) and everything derived from the
* from the column datatype. * column datatype.
*/ */
if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
return false; return false;
@ -276,8 +276,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
/* /*
* We can't assume that the items are always read from the * We can't assume that the items are always read from the
* system catalogs in the same order; so use the adnum field to * system catalogs in the same order; so use the adnum field
* identify the matching item to compare. * to identify the matching item to compare.
*/ */
for (j = 0; j < n; defval2++, j++) for (j = 0; j < n; defval2++, j++)
{ {
@ -298,9 +298,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
ConstrCheck *check2 = constr2->check; ConstrCheck *check2 = constr2->check;
/* /*
* Similarly, don't assume that the checks are always read * Similarly, don't assume that the checks are always read in
* in the same order; match them up by name and contents. * the same order; match them up by name and contents. (The
* (The name *should* be unique, but...) * name *should* be unique, but...)
*/ */
for (j = 0; j < n; check2++, j++) for (j = 0; j < n; check2++, j++)
{ {

View File

@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.71 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.72 2001/03/22 03:59:12 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -80,6 +80,7 @@ static void gistcentryinit(GISTSTATE *giststate,
#undef GISTDEBUG #undef GISTDEBUG
#ifdef GISTDEBUG #ifdef GISTDEBUG
static void gist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff); static void gist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff);
#endif #endif
/* /*
@ -92,8 +93,10 @@ gistbuild(PG_FUNCTION_ARGS)
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -105,9 +108,11 @@ gistbuild(PG_FUNCTION_ARGS)
int nhtups, int nhtups,
nitups; nitups;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
GISTSTATE giststate; GISTSTATE giststate;
@ -181,6 +186,7 @@ gistbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -262,9 +268,7 @@ gistbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -316,8 +320,10 @@ gistinsert(PG_FUNCTION_ARGS)
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
InsertIndexResult res; InsertIndexResult res;
IndexTuple itup; IndexTuple itup;
@ -409,9 +415,12 @@ static void
gistdoinsert(Relation r, gistdoinsert(Relation r,
IndexTuple itup, IndexTuple itup,
InsertIndexResult *res, InsertIndexResult *res,
GISTSTATE *giststate ) { GISTSTATE *giststate)
{
IndexTuple *instup; IndexTuple *instup;
int i,ret,len = 1; int i,
ret,
len = 1;
instup = (IndexTuple *) palloc(sizeof(IndexTuple)); instup = (IndexTuple *) palloc(sizeof(IndexTuple));
instup[0] = (IndexTuple) palloc(IndexTupleSize(itup)); instup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
@ -431,7 +440,8 @@ gistlayerinsert( Relation r, BlockNumber blkno,
IndexTuple **itup, /* in - out, has compressed entry */ IndexTuple **itup, /* in - out, has compressed entry */
int *len, /* in - out */ int *len, /* in - out */
InsertIndexResult *res, /* out */ InsertIndexResult *res, /* out */
GISTSTATE *giststate ) { GISTSTATE *giststate)
{
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber child; OffsetNumber child;
@ -442,7 +452,8 @@ gistlayerinsert( Relation r, BlockNumber blkno,
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
opaque = (GISTPageOpaque) PageGetSpecialPointer(page); opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
if (!(opaque->flags & F_LEAF)) { if (!(opaque->flags & F_LEAF))
{
/* internal page, so we must walk on tree */ /* internal page, so we must walk on tree */
/* len IS equial 1 */ /* len IS equial 1 */
ItemId iid; ItemId iid;
@ -456,24 +467,26 @@ gistlayerinsert( Relation r, BlockNumber blkno,
nblkno = ItemPointerGetBlockNumber(&(oldtup->t_tid)); nblkno = ItemPointerGetBlockNumber(&(oldtup->t_tid));
/* /*
* After this call: * After this call: 1. if child page was splited, then itup
* 1. if child page was splited, then itup contains * contains keys for each page 2. if child page wasn't splited,
* keys for each page * then itup contains additional for adjustement of current key
* 2. if child page wasn't splited, then itup contains
* additional for adjustement of current key
*/ */
ret = gistlayerinsert(r, nblkno, itup, len, res, giststate); ret = gistlayerinsert(r, nblkno, itup, len, res, giststate);
/* nothing inserted in child */ /* nothing inserted in child */
if ( ! (ret & INSERTED) ) { if (!(ret & INSERTED))
{
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
return 0x00; return 0x00;
} }
/* child does not splited */ /* child does not splited */
if ( ! (ret & SPLITED) ) { if (!(ret & SPLITED))
{
IndexTuple newtup = gistgetadjusted(r, oldtup, (*itup)[0], giststate); IndexTuple newtup = gistgetadjusted(r, oldtup, (*itup)[0], giststate);
if ( ! newtup ) {
if (!newtup)
{
/* not need to update key */ /* not need to update key */
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
return 0x00; return 0x00;
@ -492,7 +505,8 @@ gistlayerinsert( Relation r, BlockNumber blkno,
ret = INSERTED; ret = INSERTED;
if ( gistnospace(page, (*itup), *len) ) { if (gistnospace(page, (*itup), *len))
{
/* no space for insertion */ /* no space for insertion */
IndexTuple *itvec; IndexTuple *itvec;
int tlen; int tlen;
@ -502,13 +516,17 @@ gistlayerinsert( Relation r, BlockNumber blkno,
itvec = gistjoinvector(itvec, &tlen, (*itup), *len); itvec = gistjoinvector(itvec, &tlen, (*itup), *len);
pfree((*itup)); pfree((*itup));
(*itup) = gistSplit(r, buffer, itvec, &tlen, giststate, (*itup) = gistSplit(r, buffer, itvec, &tlen, giststate,
(opaque->flags & F_LEAF) ? res : NULL ); /*res only for inserting in leaf*/ (opaque->flags & F_LEAF) ? res : NULL); /* res only for
* inserting in leaf */
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
pfree(itvec); pfree(itvec);
*len = tlen; /* now tlen >= 2 */ *len = tlen; /* now tlen >= 2 */
} else { }
else
{
/* enogth space */ /* enogth space */
OffsetNumber off, l; OffsetNumber off,
l;
off = (PageIsEmpty(page)) ? off = (PageIsEmpty(page)) ?
FirstOffsetNumber FirstOffsetNumber
@ -517,16 +535,22 @@ gistlayerinsert( Relation r, BlockNumber blkno,
l = gistwritebuffer(r, page, (*itup), *len, off, giststate); l = gistwritebuffer(r, page, (*itup), *len, off, giststate);
WriteBuffer(buffer); WriteBuffer(buffer);
/* set res if insert into leaf page, in /*
this case, len = 1 always */ * set res if insert into leaf page, in this case, len = 1 always
*/
if (res && (opaque->flags & F_LEAF)) if (res && (opaque->flags & F_LEAF))
ItemPointerSet(&((*res)->pointerData), blkno, l); ItemPointerSet(&((*res)->pointerData), blkno, l);
if ( *len > 1 ) { /* previos insert ret & SPLITED != 0 */ if (*len > 1)
{ /* previos insert ret & SPLITED != 0 */
int i; int i;
/* child was splited, so we must form union
* for insertion in parent */ /*
* child was splited, so we must form union for insertion in
* parent
*/
IndexTuple newtup = gistunion(r, (*itup), *len, giststate); IndexTuple newtup = gistunion(r, (*itup), *len, giststate);
for (i = 0; i < *len; i++) for (i = 0; i < *len; i++)
pfree((*itup)[i]); pfree((*itup)[i]);
(*itup)[0] = newtup; (*itup)[0] = newtup;
@ -542,13 +566,15 @@ gistlayerinsert( Relation r, BlockNumber blkno,
*/ */
static OffsetNumber static OffsetNumber
gistwritebuffer(Relation r, Page page, IndexTuple *itup, gistwritebuffer(Relation r, Page page, IndexTuple *itup,
int len, OffsetNumber off, GISTSTATE *giststate) { int len, OffsetNumber off, GISTSTATE *giststate)
{
OffsetNumber l = InvalidOffsetNumber; OffsetNumber l = InvalidOffsetNumber;
int i; int i;
GISTENTRY tmpdentry; GISTENTRY tmpdentry;
IndexTuple newtup; IndexTuple newtup;
for(i=0; i<len; i++) { for (i = 0; i < len; i++)
{
l = gistPageAddItem(giststate, r, page, l = gistPageAddItem(giststate, r, page,
(Item) itup[i], IndexTupleSize(itup[i]), (Item) itup[i], IndexTupleSize(itup[i]),
off, LP_USED, &tmpdentry, &newtup); off, LP_USED, &tmpdentry, &newtup);
@ -565,9 +591,11 @@ gistwritebuffer( Relation r, Page page, IndexTuple *itup,
* Check space for itup vector on page * Check space for itup vector on page
*/ */
static int static int
gistnospace( Page page, IndexTuple *itvec, int len ) { gistnospace(Page page, IndexTuple *itvec, int len)
{
int size = 0; int size = 0;
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
size += IndexTupleSize(itvec[i]) + 4; /* ??? */ size += IndexTupleSize(itvec[i]) + 4; /* ??? */
@ -578,8 +606,10 @@ gistnospace( Page page, IndexTuple *itvec, int len ) {
* Read buffer into itup vector * Read buffer into itup vector
*/ */
static IndexTuple * static IndexTuple *
gistreadbuffer( Relation r, Buffer buffer, int *len /*out*/) { gistreadbuffer(Relation r, Buffer buffer, int *len /* out */ )
OffsetNumber i, maxoff; {
OffsetNumber i,
maxoff;
IndexTuple *itvec; IndexTuple *itvec;
Page p = (Page) BufferGetPage(buffer); Page p = (Page) BufferGetPage(buffer);
@ -596,7 +626,8 @@ gistreadbuffer( Relation r, Buffer buffer, int *len /*out*/) {
* join two vectors into one * join two vectors into one
*/ */
static IndexTuple * static IndexTuple *
gistjoinvector( IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen ) { gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
{
itvec = (IndexTuple *) repalloc((void *) itvec, sizeof(IndexTuple) * ((*len) + addlen)); itvec = (IndexTuple *) repalloc((void *) itvec, sizeof(IndexTuple) * ((*len) + addlen));
memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen); memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
*len += addlen; *len += addlen;
@ -607,10 +638,12 @@ gistjoinvector( IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen )
* return union of itup vector * return union of itup vector
*/ */
static IndexTuple static IndexTuple
gistunion( Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate ) { gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
{
bytea *evec; bytea *evec;
char *datum; char *datum;
int datumsize, i; int datumsize,
i;
GISTENTRY centry; GISTENTRY centry;
char isnull; char isnull;
IndexTuple newtup; IndexTuple newtup;
@ -653,13 +686,16 @@ gistunion( Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate ) {
* Forms union of oldtup and addtup, if union == oldtup then return NULL * Forms union of oldtup and addtup, if union == oldtup then return NULL
*/ */
static IndexTuple static IndexTuple
gistgetadjusted( Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate ) { gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
{
bytea *evec; bytea *evec;
char *datum; char *datum;
int datumsize; int datumsize;
bool result; bool result;
char isnull; char isnull;
GISTENTRY centry, *ev0p, *ev1p; GISTENTRY centry,
*ev0p,
*ev1p;
IndexTuple newtup = NULL; IndexTuple newtup = NULL;
evec = (bytea *) palloc(2 * sizeof(GISTENTRY) + VARHDRSZ); evec = (bytea *) palloc(2 * sizeof(GISTENTRY) + VARHDRSZ);
@ -682,19 +718,23 @@ gistgetadjusted( Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gi
PointerGetDatum(evec), PointerGetDatum(evec),
PointerGetDatum(&datumsize))); PointerGetDatum(&datumsize)));
if ( ! ( ev0p->pred && ev1p->pred ) ) { if (!(ev0p->pred && ev1p->pred))
result = (ev0p->pred == NULL && ev1p->pred == NULL); result = (ev0p->pred == NULL && ev1p->pred == NULL);
} else { else
{
FunctionCall3(&giststate->equalFn, FunctionCall3(&giststate->equalFn,
PointerGetDatum(ev0p->pred), PointerGetDatum(ev0p->pred),
PointerGetDatum(datum), PointerGetDatum(datum),
PointerGetDatum(&result)); PointerGetDatum(&result));
} }
if ( result ) { if (result)
{
/* not need to update key */ /* not need to update key */
pfree(datum); pfree(datum);
} else { }
else
{
gistcentryinit(giststate, &centry, datum, ev0p->rel, ev0p->page, gistcentryinit(giststate, &centry, datum, ev0p->rel, ev0p->page,
ev0p->offset, datumsize, FALSE); ev0p->offset, datumsize, FALSE);
@ -728,19 +768,27 @@ gistSplit(Relation r,
InsertIndexResult *res) InsertIndexResult *res)
{ {
Page p; Page p;
Buffer leftbuf, rightbuf; Buffer leftbuf,
Page left, right; rightbuf;
OffsetNumber *spl_left, *spl_right; Page left,
IndexTuple *lvectup, *rvectup, *newtup; right;
int leftoff, rightoff; OffsetNumber *spl_left,
BlockNumber lbknum, rbknum; *spl_right;
IndexTuple *lvectup,
*rvectup,
*newtup;
int leftoff,
rightoff;
BlockNumber lbknum,
rbknum;
GISTPageOpaque opaque; GISTPageOpaque opaque;
char isnull; char isnull;
GIST_SPLITVEC v; GIST_SPLITVEC v;
bytea *entryvec; bytea *entryvec;
bool *decompvec; bool *decompvec;
GISTENTRY tmpentry; GISTENTRY tmpentry;
int i, nlen; int i,
nlen;
p = (Page) BufferGetPage(buffer); p = (Page) BufferGetPage(buffer);
opaque = (GISTPageOpaque) PageGetSpecialPointer(p); opaque = (GISTPageOpaque) PageGetSpecialPointer(p);
@ -801,29 +849,37 @@ gistSplit(Relation r,
pfree(entryvec); pfree(entryvec);
pfree(decompvec); pfree(decompvec);
spl_left = v.spl_left; spl_right = v.spl_right; spl_left = v.spl_left;
spl_right = v.spl_right;
/* form left and right vector */ /* form left and right vector */
lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * v.spl_nleft); lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * v.spl_nleft);
rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * v.spl_nright); rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * v.spl_nright);
leftoff = rightoff = 0; leftoff = rightoff = 0;
for( i=1; i <= *len; i++ ) { for (i = 1; i <= *len; i++)
if (i == *(spl_left) || ( i==*len && *(spl_left) != FirstOffsetNumber ) ) { {
if (i == *(spl_left) || (i == *len && *(spl_left) != FirstOffsetNumber))
{
lvectup[leftoff++] = itup[i - 1]; lvectup[leftoff++] = itup[i - 1];
spl_left++; spl_left++;
} else { }
else
{
rvectup[rightoff++] = itup[i - 1]; rvectup[rightoff++] = itup[i - 1];
spl_right++; spl_right++;
} }
} }
/* write on disk (may be need another split) */ /* write on disk (may be need another split) */
if ( gistnospace(right, rvectup, v.spl_nright) ) { if (gistnospace(right, rvectup, v.spl_nright))
{
nlen = v.spl_nright; nlen = v.spl_nright;
newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate, newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate,
(res && rvectup[nlen - 1] == itup[*len - 1]) ? res : NULL); (res && rvectup[nlen - 1] == itup[*len - 1]) ? res : NULL);
ReleaseBuffer(rightbuf); ReleaseBuffer(rightbuf);
} else { }
else
{
OffsetNumber l; OffsetNumber l;
l = gistwritebuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber, giststate); l = gistwritebuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber, giststate);
@ -845,7 +901,8 @@ gistSplit(Relation r,
ItemPointerSet(&(newtup[0]->t_tid), rbknum, 1); ItemPointerSet(&(newtup[0]->t_tid), rbknum, 1);
} }
if ( gistnospace(left, lvectup, v.spl_nleft) ) { if (gistnospace(left, lvectup, v.spl_nleft))
{
int llen = v.spl_nleft; int llen = v.spl_nleft;
IndexTuple *lntup; IndexTuple *lntup;
@ -855,7 +912,9 @@ gistSplit(Relation r,
newtup = gistjoinvector(newtup, &nlen, lntup, llen); newtup = gistjoinvector(newtup, &nlen, lntup, llen);
pfree(lntup); pfree(lntup);
} else { }
else
{
OffsetNumber l; OffsetNumber l;
l = gistwritebuffer(r, left, lvectup, v.spl_nleft, FirstOffsetNumber, giststate); l = gistwritebuffer(r, left, lvectup, v.spl_nleft, FirstOffsetNumber, giststate);
@ -1182,7 +1241,8 @@ gist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff)
GISTPageOpaque opaque; GISTPageOpaque opaque;
IndexTuple which; IndexTuple which;
ItemId iid; ItemId iid;
OffsetNumber i,maxoff; OffsetNumber i,
maxoff;
BlockNumber cblk; BlockNumber cblk;
char *pred; char *pred;
@ -1198,7 +1258,8 @@ gist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff)
elog(NOTICE, "%sPage: %d %s blk: %d maxoff: %d free: %d", pred, coff, (opaque->flags & F_LEAF) ? "LEAF" : "INTE", (int) blk, (int) maxoff, PageGetFreeSpace(page)); elog(NOTICE, "%sPage: %d %s blk: %d maxoff: %d free: %d", pred, coff, (opaque->flags & F_LEAF) ? "LEAF" : "INTE", (int) blk, (int) maxoff, PageGetFreeSpace(page));
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
iid = PageGetItemId(page, i); iid = PageGetItemId(page, i);
which = (IndexTuple) PageGetItem(page, iid); which = (IndexTuple) PageGetItem(page, iid);
cblk = ItemPointerGetBlockNumber(&(which->t_tid)); cblk = ItemPointerGetBlockNumber(&(which->t_tid));
@ -1206,13 +1267,13 @@ gist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff)
elog(NOTICE, "%s Tuple. blk: %d size: %d", pred, (int) cblk, IndexTupleSize(which)); elog(NOTICE, "%s Tuple. blk: %d size: %d", pred, (int) cblk, IndexTupleSize(which));
#endif #endif
if ( ! ( opaque->flags & F_LEAF ) ) { if (!(opaque->flags & F_LEAF))
gist_dumptree(r, level + 1, cblk, i); gist_dumptree(r, level + 1, cblk, i);
} }
}
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
pfree(pred); pfree(pred);
} }
#endif /* defined GISTDEBUG */ #endif /* defined GISTDEBUG */
void void
@ -1231,4 +1292,3 @@ void
gist_desc(char *buf, uint8 xl_info, char *rec) gist_desc(char *buf, uint8 xl_info, char *rec)
{ {
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.49 2001/02/22 21:48:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.50 2001/03/22 03:59:12 momjian Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -45,8 +45,10 @@ hashbuild(PG_FUNCTION_ARGS)
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -59,9 +61,11 @@ hashbuild(PG_FUNCTION_ARGS)
nitups; nitups;
HashItem hitem; HashItem hitem;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -117,6 +121,7 @@ hashbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -191,9 +196,7 @@ hashbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -245,8 +248,10 @@ hashinsert(PG_FUNCTION_ARGS)
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
InsertIndexResult res; InsertIndexResult res;
HashItem hitem; HashItem hitem;
@ -327,8 +332,10 @@ Datum
hashrescan(PG_FUNCTION_ARGS) hashrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.29 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.30 2001/03/22 03:59:13 momjian Exp $
* *
* NOTES * NOTES
* These functions are stored in pg_amproc. For each operator class * These functions are stored in pg_amproc. For each operator class

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.110 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.111 2001/03/22 03:59:13 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -564,6 +564,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
) )
); );
} }
#endif /* defined(DISABLE_COMPLEX_MACRO) */ #endif /* defined(DISABLE_COMPLEX_MACRO) */
@ -791,8 +792,8 @@ heap_beginscan(Relation relation,
scan->rs_nkeys = (short) nkeys; scan->rs_nkeys = (short) nkeys;
/* /*
* we do this here instead of in initscan() because heap_rescan * we do this here instead of in initscan() because heap_rescan also
* also calls initscan() and we don't want to allocate memory again * calls initscan() and we don't want to allocate memory again
*/ */
if (nkeys) if (nkeys)
scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
@ -1411,10 +1412,10 @@ heap_insert(Relation relation, HeapTuple tup)
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If tuple is cachable, mark it for rollback from the caches * If tuple is cachable, mark it for rollback from the caches in case
* in case we abort. Note it is OK to do this after WriteBuffer * we abort. Note it is OK to do this after WriteBuffer releases the
* releases the buffer, because the "tup" data structure is all * buffer, because the "tup" data structure is all in local memory,
* in local memory, not in the shared buffer. * not in the shared buffer.
*/ */
RelationMark4RollbackHeapTuple(relation, tup); RelationMark4RollbackHeapTuple(relation, tup);
@ -1551,9 +1552,10 @@ l1:
#endif #endif
/* /*
* Mark tuple for invalidation from system caches at next command boundary. * Mark tuple for invalidation from system caches at next command
* We have to do this before WriteBuffer because we need to look at the * boundary. We have to do this before WriteBuffer because we need to
* contents of the tuple, so we need to hold our refcount on the buffer. * look at the contents of the tuple, so we need to hold our refcount
* on the buffer.
*/ */
RelationInvalidateHeapTuple(relation, &tp); RelationInvalidateHeapTuple(relation, &tp);
@ -1636,6 +1638,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp); oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
oldtup.t_len = ItemIdGetLength(lp); oldtup.t_len = ItemIdGetLength(lp);
oldtup.t_self = *otid; oldtup.t_self = *otid;
/* /*
* Note: beyond this point, use oldtup not otid to refer to old tuple. * Note: beyond this point, use oldtup not otid to refer to old tuple.
* otid may very well point at newtup->t_self, which we will overwrite * otid may very well point at newtup->t_self, which we will overwrite
@ -1701,18 +1704,19 @@ l2:
/* /*
* If the toaster needs to be activated, OR if the new tuple will not * If the toaster needs to be activated, OR if the new tuple will not
* fit on the same page as the old, then we need to release the context * fit on the same page as the old, then we need to release the
* lock (but not the pin!) on the old tuple's buffer while we are off * context lock (but not the pin!) on the old tuple's buffer while we
* doing TOAST and/or table-file-extension work. We must mark the old * are off doing TOAST and/or table-file-extension work. We must mark
* tuple to show that it's already being updated, else other processes * the old tuple to show that it's already being updated, else other
* may try to update it themselves. To avoid second XLOG log record, * processes may try to update it themselves. To avoid second XLOG log
* we use xact mgr hook to unlock old tuple without reading log if xact * record, we use xact mgr hook to unlock old tuple without reading
* will abort before update is logged. In the event of crash prio logging, * log if xact will abort before update is logged. In the event of
* TQUAL routines will see HEAP_XMAX_UNLOGGED flag... * crash prio logging, TQUAL routines will see HEAP_XMAX_UNLOGGED
* flag...
* *
* NOTE: this trick is useless currently but saved for future * NOTE: this trick is useless currently but saved for future when we'll
* when we'll implement UNDO and will re-use transaction IDs * implement UNDO and will re-use transaction IDs after postmaster
* after postmaster startup. * startup.
* *
* We need to invoke the toaster if there are already any toasted values * We need to invoke the toaster if there are already any toasted values
* present, or if the new tuple is over-threshold. * present, or if the new tuple is over-threshold.
@ -1814,10 +1818,10 @@ l2:
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If new tuple is cachable, mark it for rollback from the caches * If new tuple is cachable, mark it for rollback from the caches in
* in case we abort. Note it is OK to do this after WriteBuffer * case we abort. Note it is OK to do this after WriteBuffer releases
* releases the buffer, because the "newtup" data structure is all * the buffer, because the "newtup" data structure is all in local
* in local memory, not in the shared buffer. * memory, not in the shared buffer.
*/ */
RelationMark4RollbackHeapTuple(relation, newtup); RelationMark4RollbackHeapTuple(relation, newtup);
@ -2320,7 +2324,8 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
return; return;
} }
} }
else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_delete_undo: bad page LSN"); elog(STOP, "heap_delete_undo: bad page LSN");
offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid)); offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));
@ -2420,7 +2425,8 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
} }
/* undo insert */ /* undo insert */
if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_insert_undo: bad page LSN"); elog(STOP, "heap_insert_undo: bad page LSN");
elog(STOP, "heap_insert_undo: unimplemented"); elog(STOP, "heap_insert_undo: unimplemented");
@ -2470,7 +2476,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
goto newt; goto newt;
} }
} }
else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_update_undo: bad old tuple page LSN"); elog(STOP, "heap_update_undo: bad old tuple page LSN");
offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid)); offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));
@ -2596,7 +2603,8 @@ newsame:;
} }
/* undo */ /* undo */
if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_update_undo: bad new tuple page LSN"); elog(STOP, "heap_update_undo: bad new tuple page LSN");
elog(STOP, "heap_update_undo: unimplemented"); elog(STOP, "heap_update_undo: unimplemented");
@ -2645,7 +2653,8 @@ _heap_unlock_tuple(void *data)
return; return;
} }
void heap_redo(XLogRecPtr lsn, XLogRecord *record) void
heap_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
@ -2664,7 +2673,8 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record)
elog(STOP, "heap_redo: unknown op code %u", info); elog(STOP, "heap_redo: unknown op code %u", info);
} }
void heap_undo(XLogRecPtr lsn, XLogRecord *record) void
heap_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
@ -2701,18 +2711,21 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
if (info == XLOG_HEAP_INSERT) if (info == XLOG_HEAP_INSERT)
{ {
xl_heap_insert *xlrec = (xl_heap_insert *) rec; xl_heap_insert *xlrec = (xl_heap_insert *) rec;
strcat(buf, "insert: "); strcat(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_DELETE) else if (info == XLOG_HEAP_DELETE)
{ {
xl_heap_delete *xlrec = (xl_heap_delete *) rec; xl_heap_delete *xlrec = (xl_heap_delete *) rec;
strcat(buf, "delete: "); strcat(buf, "delete: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE) else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE)
{ {
xl_heap_update *xlrec = (xl_heap_update *) rec; xl_heap_update *xlrec = (xl_heap_update *) rec;
if (info == XLOG_HEAP_UPDATE) if (info == XLOG_HEAP_UPDATE)
strcat(buf, "update: "); strcat(buf, "update: ");
else else
@ -2725,6 +2738,7 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
else if (info == XLOG_HEAP_CLEAN) else if (info == XLOG_HEAP_CLEAN)
{ {
xl_heap_clean *xlrec = (xl_heap_clean *) rec; xl_heap_clean *xlrec = (xl_heap_clean *) rec;
sprintf(buf + strlen(buf), "clean: node %u/%u; blk %u", sprintf(buf + strlen(buf), "clean: node %u/%u; blk %u",
xlrec->node.tblNode, xlrec->node.relNode, xlrec->block); xlrec->node.tblNode, xlrec->node.relNode, xlrec->block);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Id: hio.c,v 1.35 2001/01/24 19:42:48 momjian Exp $ * $Id: hio.c,v 1.36 2001/03/22 03:59:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.17 2001/02/15 20:57:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.18 2001/03/22 03:59:13 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -448,7 +448,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* incompressible data, ignore on subsequent compression passes */
/*
* incompressible data, ignore on subsequent compression
* passes
*/
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
} }
@ -565,7 +569,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* incompressible data, ignore on subsequent compression passes */
/*
* incompressible data, ignore on subsequent compression
* passes
*/
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.48 2001/01/24 19:42:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.49 2001/03/22 03:59:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -263,6 +263,7 @@ StrategyTermEvaluate(StrategyTerm term,
return result; return result;
} }
#endif #endif
/* ---------------- /* ----------------
@ -465,6 +466,7 @@ RelationInvokeStrategy(Relation relation,
} }
#endif #endif
/* ---------------- /* ----------------
@ -597,9 +599,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
} }
if (cachesearch) if (cachesearch)
{
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
}
else else
{ {
heap_endscan(scan); heap_endscan(scan);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.40 2001/01/24 19:42:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.41 2001/03/22 03:59:14 momjian Exp $
* *
* NOTES * NOTES
* *
@ -236,9 +236,10 @@ bttextcmp(PG_FUNCTION_ARGS)
if (res == 0 && VARSIZE(a) != VARSIZE(b)) if (res == 0 && VARSIZE(a) != VARSIZE(b))
{ {
/* /*
* The two strings are the same in the first len bytes, * The two strings are the same in the first len bytes, and they
* and they are of different lengths. * are of different lengths.
*/ */
if (VARSIZE(a) < VARSIZE(b)) if (VARSIZE(a) < VARSIZE(b))
res = -1; res = -1;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.81 2001/02/07 23:35:33 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.82 2001/03/22 03:59:14 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -114,8 +114,8 @@ top:
buf = _bt_moveright(rel, buf, natts, itup_scankey, BT_WRITE); buf = _bt_moveright(rel, buf, natts, itup_scankey, BT_WRITE);
/* /*
* If we're not allowing duplicates, make sure the key isn't * If we're not allowing duplicates, make sure the key isn't already
* already in the index. XXX this belongs somewhere else, likely * in the index. XXX this belongs somewhere else, likely
*/ */
if (index_is_unique) if (index_is_unique)
{ {
@ -171,8 +171,8 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
/* /*
* Find first item >= proposed new item. Note we could also get * Find first item >= proposed new item. Note we could also get a
* a pointer to end-of-page here. * pointer to end-of-page here.
*/ */
offset = _bt_binsrch(rel, buf, natts, itup_scankey); offset = _bt_binsrch(rel, buf, natts, itup_scankey);
@ -187,13 +187,13 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
BlockNumber nblkno; BlockNumber nblkno;
/* /*
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's * _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's how we
* how we handling NULLs - and so we must not use _bt_compare * handling NULLs - and so we must not use _bt_compare in real
* in real comparison, but only for ordering/finding items on * comparison, but only for ordering/finding items on pages. -
* pages. - vadim 03/24/97 * vadim 03/24/97
* *
* make sure the offset points to an actual key * make sure the offset points to an actual key before trying to
* before trying to compare it... * compare it...
*/ */
if (offset <= maxoff) if (offset <= maxoff)
{ {
@ -201,10 +201,10 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
break; /* we're past all the equal tuples */ break; /* we're past all the equal tuples */
/* /*
* Have to check is inserted heap tuple deleted one (i.e. * Have to check is inserted heap tuple deleted one (i.e. just
* just moved to another place by vacuum)! We only need to * moved to another place by vacuum)! We only need to do this
* do this once, but don't want to do it at all unless * once, but don't want to do it at all unless we see equal
* we see equal tuples, so as not to slow down unequal case. * tuples, so as not to slow down unequal case.
*/ */
if (chtup) if (chtup)
{ {
@ -238,6 +238,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
/* Tell _bt_doinsert to wait... */ /* Tell _bt_doinsert to wait... */
return xwait; return xwait;
} }
/* /*
* Otherwise we have a definite conflict. * Otherwise we have a definite conflict.
*/ */
@ -365,9 +366,7 @@ _bt_insertonpg(Relation rel,
* Determine exactly where new item will go. * Determine exactly where new item will go.
*/ */
if (afteritem > 0) if (afteritem > 0)
{
newitemoff = afteritem + 1; newitemoff = afteritem + 1;
}
else else
{ {
/*---------- /*----------
@ -404,10 +403,11 @@ _bt_insertonpg(Relation rel,
lpageop = (BTPageOpaque) PageGetSpecialPointer(page); lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
movedright = true; movedright = true;
} }
/* /*
* Now we are on the right page, so find the insert position. * Now we are on the right page, so find the insert position. If
* If we moved right at all, we know we should insert at the * we moved right at all, we know we should insert at the start of
* start of the page, else must find the position by searching. * the page, else must find the position by searching.
*/ */
if (movedright) if (movedright)
newitemoff = P_FIRSTDATAKEY(lpageop); newitemoff = P_FIRSTDATAKEY(lpageop);
@ -418,9 +418,9 @@ _bt_insertonpg(Relation rel,
/* /*
* Do we need to split the page to fit the item on it? * Do we need to split the page to fit the item on it?
* *
* Note: PageGetFreeSpace() subtracts sizeof(ItemIdData) from its * Note: PageGetFreeSpace() subtracts sizeof(ItemIdData) from its result,
* result, so this comparison is correct even though we appear to * so this comparison is correct even though we appear to be
* be accounting only for the item and not for its line pointer. * accounting only for the item and not for its line pointer.
*/ */
if (PageGetFreeSpace(page) < itemsz) if (PageGetFreeSpace(page) < itemsz)
{ {
@ -489,10 +489,11 @@ _bt_insertonpg(Relation rel,
if (stack == (BTStack) NULL) if (stack == (BTStack) NULL)
{ {
elog(DEBUG, "btree: concurrent ROOT page split"); elog(DEBUG, "btree: concurrent ROOT page split");
/* /*
* If root page splitter failed to create new root page * If root page splitter failed to create new root page
* then old root' btpo_parent still points to metapage. * then old root' btpo_parent still points to metapage. We
* We have to fix root page in this case. * have to fix root page in this case.
*/ */
if (BTreeInvalidParent(lpageop)) if (BTreeInvalidParent(lpageop))
{ {
@ -531,9 +532,9 @@ _bt_insertonpg(Relation rel,
* item! We want to find parent pointing to where we are, * item! We want to find parent pointing to where we are,
* right ? - vadim 05/27/97 * right ? - vadim 05/27/97
* *
* Interestingly, this means we didn't *really* need to stack * Interestingly, this means we didn't *really* need to stack the
* the parent key at all; all we really care about is the * parent key at all; all we really care about is the saved
* saved block and offset as a starting point for our search... * block and offset as a starting point for our search...
*/ */
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid), ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
bknum, P_HIKEY); bknum, P_HIKEY);
@ -598,6 +599,7 @@ _bt_insertuple(Relation rel, Buffer buf,
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
BTItemData truncitem; BTItemData truncitem;
xlrec.target.node = rel->rd_node; xlrec.target.node = rel->rd_node;
ItemPointerSet(&(xlrec.target.tid), BufferGetBlockNumber(buf), newitemoff); ItemPointerSet(&(xlrec.target.tid), BufferGetBlockNumber(buf), newitemoff);
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
@ -700,8 +702,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
/* /*
* If the page we're splitting is not the rightmost page at its level * If the page we're splitting is not the rightmost page at its level
* in the tree, then the first entry on the page is the high key * in the tree, then the first entry on the page is the high key for
* for the page. We need to copy that to the right half. Otherwise * the page. We need to copy that to the right half. Otherwise
* (meaning the rightmost page case), all the items on the right half * (meaning the rightmost page case), all the items on the right half
* will be user data. * will be user data.
*/ */
@ -812,11 +814,11 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
} }
/* /*
* We have to grab the right sibling (if any) and fix the prev * We have to grab the right sibling (if any) and fix the prev pointer
* pointer there. We are guaranteed that this is deadlock-free * there. We are guaranteed that this is deadlock-free since no other
* since no other writer will be holding a lock on that page * writer will be holding a lock on that page and trying to move left,
* and trying to move left, and all readers release locks on a page * and all readers release locks on a page before trying to fetch its
* before trying to fetch its neighbors. * neighbors.
*/ */
if (!P_RIGHTMOST(ropaque)) if (!P_RIGHTMOST(ropaque))
@ -856,6 +858,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
BlockIdSet(&(xlrec.parentblk), lopaque->btpo_parent); BlockIdSet(&(xlrec.parentblk), lopaque->btpo_parent);
BlockIdSet(&(xlrec.leftblk), lopaque->btpo_prev); BlockIdSet(&(xlrec.leftblk), lopaque->btpo_prev);
BlockIdSet(&(xlrec.rightblk), ropaque->btpo_next); BlockIdSet(&(xlrec.rightblk), ropaque->btpo_next);
/* /*
* Dirrect access to page is not good but faster - we should * Dirrect access to page is not good but faster - we should
* implement some new func in page API. * implement some new func in page API.
@ -881,6 +884,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
if (!P_RIGHTMOST(ropaque)) if (!P_RIGHTMOST(ropaque))
{ {
BTPageOpaque sopaque = (BTPageOpaque) PageGetSpecialPointer(spage); BTPageOpaque sopaque = (BTPageOpaque) PageGetSpecialPointer(spage);
sopaque->btpo_prev = BufferGetBlockNumber(rbuf); sopaque->btpo_prev = BufferGetBlockNumber(rbuf);
rdata[2].next = &(rdata[3]); rdata[2].next = &(rdata[3]);
@ -978,13 +982,13 @@ _bt_findsplitloc(Relation rel,
+sizeof(ItemIdData); +sizeof(ItemIdData);
/* /*
* Finding the best possible split would require checking all the possible * Finding the best possible split would require checking all the
* split points, because of the high-key and left-key special cases. * possible split points, because of the high-key and left-key special
* That's probably more work than it's worth; instead, stop as soon as * cases. That's probably more work than it's worth; instead, stop as
* we find a "good-enough" split, where good-enough is defined as an * soon as we find a "good-enough" split, where good-enough is defined
* imbalance in free space of no more than pagesize/16 (arbitrary...) * as an imbalance in free space of no more than pagesize/16
* This should let us stop near the middle on most pages, instead of * (arbitrary...) This should let us stop near the middle on most
* plowing to the end. * pages, instead of plowing to the end.
*/ */
goodenough = leftspace / 16; goodenough = leftspace / 16;
@ -1024,6 +1028,7 @@ _bt_findsplitloc(Relation rel,
*/ */
leftfree = leftspace - dataitemstoleft - (int) itemsz; leftfree = leftspace - dataitemstoleft - (int) itemsz;
rightfree = rightspace - (dataitemtotal - dataitemstoleft); rightfree = rightspace - (dataitemtotal - dataitemstoleft);
/* /*
* Will the new item go to left or right of split? * Will the new item go to left or right of split?
*/ */
@ -1051,8 +1056,8 @@ _bt_findsplitloc(Relation rel,
} }
/* /*
* I believe it is not possible to fail to find a feasible split, * I believe it is not possible to fail to find a feasible split, but
* but just in case ... * just in case ...
*/ */
if (!state.have_split) if (!state.have_split)
elog(FATAL, "_bt_findsplitloc: can't find a feasible split point for %s", elog(FATAL, "_bt_findsplitloc: can't find a feasible split point for %s",
@ -1071,6 +1076,7 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
int leftfree, int rightfree, int leftfree, int rightfree,
bool newitemonleft, Size firstrightitemsz) bool newitemonleft, Size firstrightitemsz)
{ {
/* /*
* Account for the new item on whichever side it is to be put. * Account for the new item on whichever side it is to be put.
*/ */
@ -1078,13 +1084,15 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
leftfree -= (int) state->newitemsz; leftfree -= (int) state->newitemsz;
else else
rightfree -= (int) state->newitemsz; rightfree -= (int) state->newitemsz;
/* /*
* If we are not on the leaf level, we will be able to discard the * If we are not on the leaf level, we will be able to discard the key
* key data from the first item that winds up on the right page. * data from the first item that winds up on the right page.
*/ */
if (state->non_leaf) if (state->non_leaf)
rightfree += (int) firstrightitemsz - rightfree += (int) firstrightitemsz -
(int) (MAXALIGN(sizeof(BTItemData)) + sizeof(ItemIdData)); (int) (MAXALIGN(sizeof(BTItemData)) + sizeof(ItemIdData));
/* /*
* If feasible split point, remember best delta. * If feasible split point, remember best delta.
*/ */
@ -1134,10 +1142,11 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
start = stack->bts_offset; start = stack->bts_offset;
/* /*
* _bt_insertonpg set bts_offset to InvalidOffsetNumber in the * _bt_insertonpg set bts_offset to InvalidOffsetNumber in the case of
* case of concurrent ROOT page split. Also, watch out for * concurrent ROOT page split. Also, watch out for possibility that
* possibility that page has a high key now when it didn't before. * page has a high key now when it didn't before.
*/ */
if (start < P_FIRSTDATAKEY(opaque)) if (start < P_FIRSTDATAKEY(opaque))
start = P_FIRSTDATAKEY(opaque); start = P_FIRSTDATAKEY(opaque);
@ -1159,7 +1168,11 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
return buf; return buf;
} }
} }
/* by here, the item we're looking for moved right at least one page */
/*
* by here, the item we're looking for moved right at least one
* page
*/
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
{ {
_bt_relbuf(rel, buf, access); _bt_relbuf(rel, buf, access);
@ -1236,9 +1249,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
rpage = BufferGetPage(rbuf); rpage = BufferGetPage(rbuf);
/* /*
* Make sure pages in old root level have valid parent links --- we will * Make sure pages in old root level have valid parent links --- we
* need this in _bt_insertonpg() if a concurrent root split happens (see * will need this in _bt_insertonpg() if a concurrent root split
* README). * happens (see README).
*/ */
((BTPageOpaque) PageGetSpecialPointer(lpage))->btpo_parent = ((BTPageOpaque) PageGetSpecialPointer(lpage))->btpo_parent =
((BTPageOpaque) PageGetSpecialPointer(rpage))->btpo_parent = ((BTPageOpaque) PageGetSpecialPointer(rpage))->btpo_parent =
@ -1264,8 +1277,8 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
pfree(new_item); pfree(new_item);
/* /*
* Create downlink item for right page. The key for it is obtained from * Create downlink item for right page. The key for it is obtained
* the "high key" position in the left page. * from the "high key" position in the left page.
*/ */
itemid = PageGetItemId(lpage, P_HIKEY); itemid = PageGetItemId(lpage, P_HIKEY);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
@ -1346,11 +1359,18 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
Page oldrootpage = BufferGetPage(oldrootbuf); Page oldrootpage = BufferGetPage(oldrootbuf);
BTPageOpaque oldrootopaque = (BTPageOpaque) BTPageOpaque oldrootopaque = (BTPageOpaque)
PageGetSpecialPointer(oldrootpage); PageGetSpecialPointer(oldrootpage);
Buffer buf, leftbuf, rightbuf; Buffer buf,
Page page, leftpage, rightpage; leftbuf,
BTPageOpaque opaque, leftopaque, rightopaque; rightbuf;
Page page,
leftpage,
rightpage;
BTPageOpaque opaque,
leftopaque,
rightopaque;
OffsetNumber newitemoff; OffsetNumber newitemoff;
BTItem btitem, ritem; BTItem btitem,
ritem;
Size itemsz; Size itemsz;
if (!P_LEFTMOST(oldrootopaque) || P_RIGHTMOST(oldrootopaque)) if (!P_LEFTMOST(oldrootopaque) || P_RIGHTMOST(oldrootopaque))
@ -1377,13 +1397,13 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
* *
* If concurrent process will split one of pages on this level then it * If concurrent process will split one of pages on this level then it
* will see either btpo_parent == metablock or btpo_parent == rootblk. * will see either btpo_parent == metablock or btpo_parent == rootblk.
* In first case it will give up its locks and walk to the leftmost page * In first case it will give up its locks and walk to the leftmost
* (oldrootbuf) in _bt_fixup() - ie it will wait for us and let us * page (oldrootbuf) in _bt_fixup() - ie it will wait for us and let
* continue. In second case it will try to lock rootbuf keeping its locks * us continue. In second case it will try to lock rootbuf keeping its
* on buffers we already passed, also waiting for us. If we'll have to * locks on buffers we already passed, also waiting for us. If we'll
* unlock rootbuf (split it) and that process will have to split page * have to unlock rootbuf (split it) and that process will have to
* of new level we created (level of rootbuf) then it will wait while * split page of new level we created (level of rootbuf) then it will
* we create upper level. Etc. * wait while we create upper level. Etc.
*/ */
while (!P_RIGHTMOST(leftopaque)) while (!P_RIGHTMOST(leftopaque))
{ {
@ -1392,11 +1412,11 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
rightopaque = (BTPageOpaque) PageGetSpecialPointer(rightpage); rightopaque = (BTPageOpaque) PageGetSpecialPointer(rightpage);
/* /*
* Update LSN & StartUpID of child page buffer to ensure that * Update LSN & StartUpID of child page buffer to ensure that it
* it will be written on disk after flushing log record for new * will be written on disk after flushing log record for new root
* root creation. Unfortunately, for the moment (?) we do not * creation. Unfortunately, for the moment (?) we do not log this
* log this operation and so possibly break our rule to log entire * operation and so possibly break our rule to log entire page
* page content on first after checkpoint modification. * content on first after checkpoint modification.
*/ */
HOLD_INTERRUPTS(); HOLD_INTERRUPTS();
rightopaque->btpo_parent = rootblk; rightopaque->btpo_parent = rootblk;
@ -1450,10 +1470,10 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
/* /*
* Here we hold locks on old root buffer, new root buffer we've * Here we hold locks on old root buffer, new root buffer we've
* created with _bt_newroot() - rootbuf, - and buf we've used * created with _bt_newroot() - rootbuf, - and buf we've used for last
* for last insert ops - buf. If rootbuf != buf then we have to * insert ops - buf. If rootbuf != buf then we have to create at least
* create at least one more level. And if "release" is TRUE * one more level. And if "release" is TRUE then we give up
* then we give up oldrootbuf. * oldrootbuf.
*/ */
if (release) if (release)
_bt_wrtbuf(rel, oldrootbuf); _bt_wrtbuf(rel, oldrootbuf);
@ -1543,7 +1563,8 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
Page cpage[3]; Page cpage[3];
BTPageOpaque copaque[3]; BTPageOpaque copaque[3];
BTItem btitem; BTItem btitem;
int cidx, i; int cidx,
i;
bool goodbye = false; bool goodbye = false;
char tbuf[BLCKSZ]; char tbuf[BLCKSZ];
@ -1572,9 +1593,10 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
for (;;) for (;;)
{ {
/* /*
* Read up to 2 more child pages and look for pointers * Read up to 2 more child pages and look for pointers to them in
* to them in *saved* parent page * *saved* parent page
*/ */
coff[1] = coff[2] = InvalidOffsetNumber; coff[1] = coff[2] = InvalidOffsetNumber;
for (cidx = 0; cidx < 2;) for (cidx = 0; cidx < 2;)
@ -1766,7 +1788,8 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
BlockNumber blkno = true_stack->bts_blkno; BlockNumber blkno = true_stack->bts_blkno;
BTStackData stack; BTStackData stack;
BTPageOpaque opaque; BTPageOpaque opaque;
Buffer buf, rbuf; Buffer buf,
rbuf;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
@ -1779,8 +1802,8 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
_bt_fixlevel(rel, buf, rblkno); _bt_fixlevel(rel, buf, rblkno);
/* /*
* Here parent level should have pointers for both * Here parent level should have pointers for both lblkno and
* lblkno and rblkno and we have to find them. * rblkno and we have to find them.
*/ */
stack.bts_parent = NULL; stack.bts_parent = NULL;
stack.bts_blkno = blkno; stack.bts_blkno = blkno;
@ -1829,10 +1852,10 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
} }
/* /*
* Well, we are on the level that was root or unexistent when * Well, we are on the level that was root or unexistent when we
* we started traversing tree down. If btpo_parent is updated * started traversing tree down. If btpo_parent is updated then
* then we'll use it to continue, else we'll fix/restore upper * we'll use it to continue, else we'll fix/restore upper levels
* levels entirely. * entirely.
*/ */
if (!BTreeInvalidParent(opaque)) if (!BTreeInvalidParent(opaque))
{ {
@ -1882,10 +1905,10 @@ _bt_fixup(Relation rel, Buffer buf)
{ {
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* If someone else already created parent pages * If someone else already created parent pages then it's time for
* then it's time for _bt_fixtree() to check upper * _bt_fixtree() to check upper levels and fix them, if required.
* levels and fix them, if required.
*/ */
if (!BTreeInvalidParent(opaque)) if (!BTreeInvalidParent(opaque))
{ {
@ -1904,9 +1927,8 @@ _bt_fixup(Relation rel, Buffer buf)
} }
/* /*
* Ok, we are on the leftmost page, it's write locked * Ok, we are on the leftmost page, it's write locked by us and its
* by us and its btpo_parent points to meta page - time * btpo_parent points to meta page - time for _bt_fixroot().
* for _bt_fixroot().
*/ */
elog(NOTICE, "bt_fixup[%s]: fixing root page", RelationGetRelationName(rel)); elog(NOTICE, "bt_fixup[%s]: fixing root page", RelationGetRelationName(rel));
buf = _bt_fixroot(rel, buf, true); buf = _bt_fixroot(rel, buf, true);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.50 2001/02/07 23:35:33 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.51 2001/03/22 03:59:14 momjian Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -212,6 +212,7 @@ _bt_getroot(Relation rel, int access)
} }
else else
{ {
/* /*
* Metadata initialized by someone else. In order to * Metadata initialized by someone else. In order to
* guarantee no deadlocks, we have to release the metadata * guarantee no deadlocks, we have to release the metadata
@ -239,10 +240,11 @@ _bt_getroot(Relation rel, int access)
if (!P_ISROOT(rootopaque)) if (!P_ISROOT(rootopaque))
{ {
/* /*
* It happened, but if root page splitter failed to create * It happened, but if root page splitter failed to create new
* new root page then we'll go in loop trying to call * root page then we'll go in loop trying to call _bt_getroot
* _bt_getroot again and again. * again and again.
*/ */
if (FixBTree) if (FixBTree)
{ {
@ -270,16 +272,18 @@ check_parent:;
/* rootbuf is read locked */ /* rootbuf is read locked */
goto check_parent; goto check_parent;
} }
else /* someone else already fixed root */ else
/* someone else already fixed root */
{ {
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK); LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_READ); LockBuffer(rootbuf, BT_READ);
} }
} }
/* /*
* Ok, here we have old root page with btpo_parent pointing * Ok, here we have old root page with btpo_parent pointing to
* to upper level - check parent page because of there is * upper level - check parent page because of there is good
* good chance that parent is root page. * chance that parent is root page.
*/ */
newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ); newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ);
_bt_relbuf(rel, rootbuf, BT_READ); _bt_relbuf(rel, rootbuf, BT_READ);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.78 2001/02/07 23:35:33 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.79 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -30,6 +30,7 @@
bool BuildingBtree = false; /* see comment in btbuild() */ bool BuildingBtree = false; /* see comment in btbuild() */
bool FastBuild = true; /* use sort/build instead */ bool FastBuild = true; /* use sort/build instead */
/* of insertion build */ /* of insertion build */
@ -56,8 +57,10 @@ btbuild(PG_FUNCTION_ARGS)
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -69,9 +72,11 @@ btbuild(PG_FUNCTION_ARGS)
int nhtups, int nhtups,
nitups; nitups;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -80,10 +85,11 @@ btbuild(PG_FUNCTION_ARGS)
bool usefast; bool usefast;
Snapshot snapshot; Snapshot snapshot;
TransactionId XmaxRecent; TransactionId XmaxRecent;
/* /*
* spool2 is needed only when the index is an unique index. * spool2 is needed only when the index is an unique index. Dead
* Dead tuples are put into spool2 instead of spool in * tuples are put into spool2 instead of spool in order to avoid
* order to avoid uniqueness check. * uniqueness check.
*/ */
BTSpool *spool2 = NULL; BTSpool *spool2 = NULL;
bool tupleIsAlive; bool tupleIsAlive;
@ -155,9 +161,9 @@ btbuild(PG_FUNCTION_ARGS)
if (usefast) if (usefast)
{ {
spool = _bt_spoolinit(index, indexInfo->ii_Unique); spool = _bt_spoolinit(index, indexInfo->ii_Unique);
/* /*
* Different from spool,the uniqueness isn't checked * Different from spool,the uniqueness isn't checked for spool2.
* for spool2.
*/ */
if (indexInfo->ii_Unique) if (indexInfo->ii_Unique)
spool2 = _bt_spoolinit(index, false); spool2 = _bt_spoolinit(index, false);
@ -193,6 +199,7 @@ btbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -253,8 +260,7 @@ btbuild(PG_FUNCTION_ARGS)
* btree pages - NULLs greater NOT_NULLs and NULL = NULL is TRUE. * btree pages - NULLs greater NOT_NULLs and NULL = NULL is TRUE.
* Sure, it's just rule for placing/finding items and no more - * Sure, it's just rule for placing/finding items and no more -
* keytest'll return FALSE for a = 5 for items having 'a' isNULL. * keytest'll return FALSE for a = 5 for items having 'a' isNULL.
* Look at _bt_compare for how it works. * Look at _bt_compare for how it works. - vadim 03/23/97
* - vadim 03/23/97
* *
* if (itup->t_info & INDEX_NULL_MASK) { pfree(itup); continue; } * if (itup->t_info & INDEX_NULL_MASK) { pfree(itup); continue; }
*/ */
@ -271,7 +277,8 @@ btbuild(PG_FUNCTION_ARGS)
{ {
if (tupleIsAlive || !spool2) if (tupleIsAlive || !spool2)
_bt_spool(btitem, spool); _bt_spool(btitem, spool);
else /* dead tuples are put into spool2 */ else
/* dead tuples are put into spool2 */
{ {
dead_count++; dead_count++;
_bt_spool(btitem, spool2); _bt_spool(btitem, spool2);
@ -296,9 +303,7 @@ btbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -408,10 +413,11 @@ btgettuple(PG_FUNCTION_ARGS)
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(scan->currentItemData)))
{ {
/* /*
* Restore scan position using heap TID returned by previous call * Restore scan position using heap TID returned by previous call
* to btgettuple(). _bt_restscan() re-grabs the read lock on * to btgettuple(). _bt_restscan() re-grabs the read lock on the
* the buffer, too. * buffer, too.
*/ */
_bt_restscan(scan); _bt_restscan(scan);
res = _bt_next(scan, dir); res = _bt_next(scan, dir);
@ -421,8 +427,8 @@ btgettuple(PG_FUNCTION_ARGS)
/* /*
* Save heap TID to use it in _bt_restscan. Then release the read * Save heap TID to use it in _bt_restscan. Then release the read
* lock on the buffer so that we aren't blocking other backends. * lock on the buffer so that we aren't blocking other backends. NOTE:
* NOTE: we do keep the pin on the buffer! * we do keep the pin on the buffer!
*/ */
if (res) if (res)
{ {
@ -462,8 +468,10 @@ Datum
btrescan(PG_FUNCTION_ARGS) btrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;
@ -671,8 +679,8 @@ _bt_restscan(IndexScanDesc scan)
BlockNumber blkno; BlockNumber blkno;
/* /*
* Get back the read lock we were holding on the buffer. * Get back the read lock we were holding on the buffer. (We still
* (We still have a reference-count pin on it, though.) * have a reference-count pin on it, though.)
*/ */
LockBuffer(buf, BT_READ); LockBuffer(buf, BT_READ);
@ -694,8 +702,8 @@ _bt_restscan(IndexScanDesc scan)
} }
/* /*
* The item we were on may have moved right due to insertions. * The item we were on may have moved right due to insertions. Find it
* Find it again. * again.
*/ */
for (;;) for (;;)
{ {
@ -717,7 +725,8 @@ _bt_restscan(IndexScanDesc scan)
} }
/* /*
* By here, the item we're looking for moved right at least one page * By here, the item we're looking for moved right at least one
* page
*/ */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!" elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!"
@ -898,7 +907,8 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
} }
else /* undo */ else
/* undo */
{ {
if (XLByteLT(PageGetLSN(page), lsn)) if (XLByteLT(PageGetLSN(page), lsn))
elog(STOP, "btree_split_undo: bad left sibling LSN"); elog(STOP, "btree_split_undo: bad left sibling LSN");
@ -936,7 +946,8 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
} }
else /* undo */ else
/* undo */
{ {
if (XLByteLT(PageGetLSN(page), lsn)) if (XLByteLT(PageGetLSN(page), lsn))
elog(STOP, "btree_split_undo: bad right sibling LSN"); elog(STOP, "btree_split_undo: bad right sibling LSN");
@ -1092,18 +1103,21 @@ btree_desc(char *buf, uint8 xl_info, char* rec)
if (info == XLOG_BTREE_INSERT) if (info == XLOG_BTREE_INSERT)
{ {
xl_btree_insert *xlrec = (xl_btree_insert *) rec; xl_btree_insert *xlrec = (xl_btree_insert *) rec;
strcat(buf, "insert: "); strcat(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_BTREE_DELETE) else if (info == XLOG_BTREE_DELETE)
{ {
xl_btree_delete *xlrec = (xl_btree_delete *) rec; xl_btree_delete *xlrec = (xl_btree_delete *) rec;
strcat(buf, "delete: "); strcat(buf, "delete: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_BTREE_SPLIT || info == XLOG_BTREE_SPLEFT) else if (info == XLOG_BTREE_SPLIT || info == XLOG_BTREE_SPLEFT)
{ {
xl_btree_split *xlrec = (xl_btree_split *) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
sprintf(buf + strlen(buf), "split(%s): ", sprintf(buf + strlen(buf), "split(%s): ",
(info == XLOG_BTREE_SPLIT) ? "right" : "left"); (info == XLOG_BTREE_SPLIT) ? "right" : "left");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
@ -1114,6 +1128,7 @@ btree_desc(char *buf, uint8 xl_info, char* rec)
else if (info == XLOG_BTREE_NEWROOT) else if (info == XLOG_BTREE_NEWROOT)
{ {
xl_btree_newroot *xlrec = (xl_btree_newroot *) rec; xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
sprintf(buf + strlen(buf), "root: node %u/%u; blk %u", sprintf(buf + strlen(buf), "root: node %u/%u; blk %u",
xlrec->node.tblNode, xlrec->node.relNode, xlrec->node.tblNode, xlrec->node.relNode,
BlockIdGetBlockNumber(&xlrec->rootblk)); BlockIdGetBlockNumber(&xlrec->rootblk));

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
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.63 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.64 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -79,13 +79,13 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
par_blkno = BufferGetBlockNumber(*bufP); par_blkno = BufferGetBlockNumber(*bufP);
/* /*
* We need to save the bit image of the index entry we chose in the * We need to save the bit image of the index entry we chose in
* parent page on a stack. In case we split the tree, we'll use this * the parent page on a stack. In case we split the tree, we'll
* bit image to figure out what our real parent page is, in case the * use this bit image to figure out what our real parent page is,
* parent splits while we're working lower in the tree. See the paper * in case the parent splits while we're working lower in the
* by Lehman and Yao for how this is detected and handled. (We use the * tree. See the paper by Lehman and Yao for how this is detected
* child link to disambiguate duplicate keys in the index -- Lehman * and handled. (We use the child link to disambiguate duplicate
* and Yao disallow duplicate keys.) * keys in the index -- Lehman and Yao disallow duplicate keys.)
*/ */
new_stack = (BTStack) palloc(sizeof(BTStackData)); new_stack = (BTStack) palloc(sizeof(BTStackData));
new_stack->bts_blkno = par_blkno; new_stack->bts_blkno = par_blkno;
@ -98,9 +98,9 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
/* /*
* Race -- the page we just grabbed may have split since we read its * Race -- the page we just grabbed may have split since we read
* pointer in the parent. If it has, we may need to move right to its * its pointer in the parent. If it has, we may need to move
* new sibling. Do that. * right to its new sibling. Do that.
*/ */
*bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ); *bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ);
@ -458,8 +458,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
_bt_orderkeys(rel, so); _bt_orderkeys(rel, so);
/* /*
* Quit now if _bt_orderkeys() discovered that the scan keys can * Quit now if _bt_orderkeys() discovered that the scan keys can never
* never be satisfied (eg, x == 1 AND x > 2). * be satisfied (eg, x == 1 AND x > 2).
*/ */
if (!so->qual_ok) if (!so->qual_ok)
return (RetrieveIndexResult) NULL; return (RetrieveIndexResult) NULL;
@ -484,17 +484,16 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
strat = _bt_getstrat(rel, attno, strat = _bt_getstrat(rel, attno,
so->keyData[i].sk_procedure); so->keyData[i].sk_procedure);
/* /*
* Can we use this key as a starting boundary for this attr? * Can we use this key as a starting boundary for this attr?
* *
* We can use multiple keys if they look like, say, = >= = * We can use multiple keys if they look like, say, = >= = but we
* but we have to stop after accepting a > or < boundary. * have to stop after accepting a > or < boundary.
*/ */
if (strat == strat_total || if (strat == strat_total ||
strat == BTEqualStrategyNumber) strat == BTEqualStrategyNumber)
{
nKeyIs[keysCount++] = i; nKeyIs[keysCount++] = i;
}
else if (ScanDirectionIsBackward(dir) && else if (ScanDirectionIsBackward(dir) &&
(strat == BTLessStrategyNumber || (strat == BTLessStrategyNumber ||
strat == BTLessEqualStrategyNumber)) strat == BTLessEqualStrategyNumber))
@ -536,7 +535,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
for (i = 0; i < keysCount; i++) for (i = 0; i < keysCount; i++)
{ {
j = nKeyIs[i]; j = nKeyIs[i];
/* _bt_orderkeys disallows it, but it's place to add some code later */
/*
* _bt_orderkeys disallows it, but it's place to add some code
* later
*/
if (so->keyData[j].sk_flags & SK_ISNULL) if (so->keyData[j].sk_flags & SK_ISNULL)
{ {
pfree(nKeyIs); pfree(nKeyIs);
@ -601,6 +604,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
switch (strat_total) switch (strat_total)
{ {
case BTLessStrategyNumber: case BTLessStrategyNumber:
/* /*
* Back up one to arrive at last item < scankey * Back up one to arrive at last item < scankey
*/ */
@ -612,6 +616,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTLessEqualStrategyNumber: case BTLessEqualStrategyNumber:
/* /*
* We need to find the last item <= scankey, so step forward * We need to find the last item <= scankey, so step forward
* till we find one > scankey, then step back one. * till we find one > scankey, then step back one.
@ -645,9 +650,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTEqualStrategyNumber: case BTEqualStrategyNumber:
/* /*
* Make sure we are on the first equal item; might have to step * Make sure we are on the first equal item; might have to
* forward if currently at end of page. * step forward if currently at end of page.
*/ */
if (offnum > PageGetMaxOffsetNumber(page)) if (offnum > PageGetMaxOffsetNumber(page))
{ {
@ -662,6 +668,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
result = _bt_compare(rel, keysCount, scankeys, page, offnum); result = _bt_compare(rel, keysCount, scankeys, page, offnum);
if (result != 0) if (result != 0)
goto nomatches; /* no equal items! */ goto nomatches; /* no equal items! */
/* /*
* 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.
@ -685,6 +692,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTGreaterEqualStrategyNumber: case BTGreaterEqualStrategyNumber:
/* /*
* We want the first item >= scankey, which is where we are... * We want the first item >= scankey, which is where we are...
* unless we're not anywhere at all... * unless we're not anywhere at all...
@ -700,9 +708,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTGreaterStrategyNumber: case BTGreaterStrategyNumber:
/* /*
* We want the first item > scankey, so make sure we are on * We want the first item > scankey, so make sure we are on an
* an item and then step over any equal items. * item and then step over any equal items.
*/ */
if (offnum > PageGetMaxOffsetNumber(page)) if (offnum > PageGetMaxOffsetNumber(page))
{ {
@ -850,11 +859,12 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP); page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* If the adjacent page just split, then we have to walk * If the adjacent page just split, then we have to walk
* right to find the block that's now adjacent to where * right to find the block that's now adjacent to where we
* we were. Because pages only split right, we don't have * were. Because pages only split right, we don't have to
* to worry about this failing to terminate. * worry about this failing to terminate.
*/ */
while (opaque->btpo_next != obknum) while (opaque->btpo_next != obknum)
{ {
@ -981,7 +991,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
Assert(P_RIGHTMOST(opaque)); Assert(P_RIGHTMOST(opaque));
start = PageGetMaxOffsetNumber(page); start = PageGetMaxOffsetNumber(page);
if (start < P_FIRSTDATAKEY(opaque)) /* watch out for empty page */ if (start < P_FIRSTDATAKEY(opaque)) /* watch out for empty
* page */
start = P_FIRSTDATAKEY(opaque); start = P_FIRSTDATAKEY(opaque);
} }
else else
@ -995,8 +1006,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
so->btso_curbuf = buf; so->btso_curbuf = buf;
/* /*
* Left/rightmost page could be empty due to deletions, * Left/rightmost page could be empty due to deletions, if so step
* if so step till we find a nonempty page. * till we find a nonempty page.
*/ */
if (start > maxoff) if (start > maxoff)
{ {

View File

@ -35,7 +35,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.59 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.60 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -73,10 +73,12 @@ typedef struct BTPageState
{ {
Buffer btps_buf; /* current buffer & page */ Buffer btps_buf; /* current buffer & page */
Page btps_page; Page btps_page;
BTItem btps_minkey; /* copy of minimum key (first item) on page */ BTItem btps_minkey; /* copy of minimum key (first item) on
* page */
OffsetNumber btps_lastoff; /* last item offset loaded */ OffsetNumber btps_lastoff; /* last item offset loaded */
int btps_level; /* tree level (0 = leaf) */ int btps_level; /* tree level (0 = leaf) */
Size btps_full; /* "full" if less than this much free space */ Size btps_full; /* "full" if less than this much free
* space */
struct BTPageState *btps_next; /* link to parent level, if any */ struct BTPageState *btps_next; /* link to parent level, if any */
} BTPageState; } BTPageState;
@ -352,6 +354,7 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
if (pgspc < btisz || pgspc < state->btps_full) if (pgspc < btisz || pgspc < state->btps_full)
{ {
/* /*
* Item won't fit on this page, or we feel the page is full enough * Item won't fit on this page, or we feel the page is full enough
* already. Finish off the page and write it out. * already. Finish off the page and write it out.
@ -388,9 +391,9 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
((PageHeader) opage)->pd_lower -= sizeof(ItemIdData); ((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
/* /*
* Link the old buffer into its parent, using its minimum key. * Link the old buffer into its parent, using its minimum key. If
* If we don't have a parent, we have to create one; * we don't have a parent, we have to create one; this adds a new
* this adds a new btree level. * btree level.
*/ */
if (state->btps_next == (BTPageState *) NULL) if (state->btps_next == (BTPageState *) NULL)
{ {
@ -405,8 +408,8 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
/* /*
* Save a copy of the minimum key for the new page. We have to * Save a copy of the minimum key for the new page. We have to
* copy it off the old page, not the new one, in case we are * copy it off the old page, not the new one, in case we are not
* not at leaf level. * at leaf level.
*/ */
state->btps_minkey = _bt_formitem(&(obti->bti_itup)); state->btps_minkey = _bt_formitem(&(obti->bti_itup));
@ -414,13 +417,13 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
* Set the sibling links for both pages, and parent links too. * Set the sibling links for both pages, and parent links too.
* *
* It's not necessary to set the parent link at all, because it's * It's not necessary to set the parent link at all, because it's
* only used for handling concurrent root splits, but we may as well * only used for handling concurrent root splits, but we may as
* do it as a debugging aid. Note we set new page's link as well * well do it as a debugging aid. Note we set new page's link as
* as old's, because if the new page turns out to be the last of * well as old's, because if the new page turns out to be the last
* the level, _bt_uppershutdown won't change it. The links may be * of the level, _bt_uppershutdown won't change it. The links may
* out of date by the time the build finishes, but that's OK; they * be out of date by the time the build finishes, but that's OK;
* need only point to a left-sibling of the true parent. See the * they need only point to a left-sibling of the true parent. See
* README file for more info. * the README file for more info.
*/ */
{ {
BTPageOpaque oopaque = (BTPageOpaque) PageGetSpecialPointer(opage); BTPageOpaque oopaque = (BTPageOpaque) PageGetSpecialPointer(opage);
@ -449,8 +452,8 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
/* /*
* If the new item is the first for its page, stash a copy for later. * If the new item is the first for its page, stash a copy for later.
* Note this will only happen for the first item on a level; on later * Note this will only happen for the first item on a level; on later
* pages, the first item for a page is copied from the prior page * pages, the first item for a page is copied from the prior page in
* in the code above. * the code above.
*/ */
if (last_off == P_HIKEY) if (last_off == P_HIKEY)
{ {
@ -493,8 +496,8 @@ _bt_uppershutdown(Relation index, BTPageState *state)
* *
* If we're at the top, it's the root, so attach it to the metapage. * If we're at the top, it's the root, so attach it to the metapage.
* Otherwise, add an entry for it to its parent using its minimum * Otherwise, add an entry for it to its parent using its minimum
* key. This may cause the last page of the parent level to split, * key. This may cause the last page of the parent level to
* but that's not a problem -- we haven't gotten to it yet. * split, but that's not a problem -- we haven't gotten to it yet.
*/ */
if (s->btps_next == (BTPageState *) NULL) if (s->btps_next == (BTPageState *) NULL)
{ {
@ -529,21 +532,28 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
{ {
BTPageState *state = NULL; BTPageState *state = NULL;
bool merge = (btspool2 != NULL); bool merge = (btspool2 != NULL);
BTItem bti, bti2 = NULL; BTItem bti,
bool should_free, should_free2, load1; bti2 = NULL;
bool should_free,
should_free2,
load1;
TupleDesc tupdes = RelationGetDescr(index); TupleDesc tupdes = RelationGetDescr(index);
int i, keysz = RelationGetNumberOfAttributes(index); int i,
keysz = RelationGetNumberOfAttributes(index);
ScanKey indexScanKey = NULL; ScanKey indexScanKey = NULL;
if (merge) if (merge)
{ {
/* /*
* Another BTSpool for dead tuples exists. * Another BTSpool for dead tuples exists. Now we have to merge
* Now we have to merge btspool and btspool2. * btspool and btspool2.
*/ */
ScanKey entry; ScanKey entry;
Datum attrDatum1, attrDatum2; Datum attrDatum1,
bool isFirstNull, isSecondNull; attrDatum2;
bool isFirstNull,
isSecondNull;
int32 compare; int32 compare;
/* the preparation of merge */ /* the preparation of merge */
@ -613,7 +623,8 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
} }
_bt_freeskey(indexScanKey); _bt_freeskey(indexScanKey);
} }
else /* merge is unnecessary */ else
/* merge is unnecessary */
{ {
while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL) while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.42 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.43 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -240,8 +240,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
/* /*
* Initialize for processing of keys for attr 1. * Initialize for processing of keys for attr 1.
* *
* xform[i] holds a copy of the current scan key of strategy type i+1, * xform[i] holds a copy of the current scan key of strategy type i+1, if
* if any; init[i] is TRUE if we have found such a key for this attr. * any; init[i] is TRUE if we have found such a key for this attr.
*/ */
attno = 1; attno = 1;
map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
@ -263,7 +263,9 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (cur->sk_flags & SK_ISNULL) if (cur->sk_flags & SK_ISNULL)
{ {
so->qual_ok = false; so->qual_ok = false;
/* Quit processing so we don't try to invoke comparison
/*
* Quit processing so we don't try to invoke comparison
* routines on NULLs. * routines on NULLs.
*/ */
return; return;
@ -271,8 +273,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
} }
/* /*
* If we are at the end of the keys for a particular attr, * If we are at the end of the keys for a particular attr, finish
* finish up processing and emit the cleaned-up keys. * up processing and emit the cleaned-up keys.
*/ */
if (i == numberOfKeys || cur->sk_attno != attno) if (i == numberOfKeys || cur->sk_attno != attno)
{ {
@ -313,6 +315,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
} }
else else
{ {
/* /*
* No "=" for this key, so we're done with required keys * No "=" for this key, so we're done with required keys
*/ */
@ -355,8 +358,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
* Emit the cleaned-up keys back into the key[] array in the * Emit the cleaned-up keys back into the key[] array in the
* correct order. Note we are overwriting our input here! * correct order. Note we are overwriting our input here!
* It's OK because (a) xform[] is a physical copy of the keys * It's OK because (a) xform[] is a physical copy of the keys
* we want, (b) we cannot emit more keys than we input, so * we want, (b) we cannot emit more keys than we input, so we
* we won't overwrite as-yet-unprocessed keys. * won't overwrite as-yet-unprocessed keys.
*/ */
for (j = BTMaxStrategyNumber; --j >= 0;) for (j = BTMaxStrategyNumber; --j >= 0;)
{ {
@ -409,7 +412,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (DatumGetBool(test)) if (DatumGetBool(test))
xform[j].sk_argument = cur->sk_argument; xform[j].sk_argument = cur->sk_argument;
else if (j == (BTEqualStrategyNumber - 1)) else if (j == (BTEqualStrategyNumber - 1))
so->qual_ok = false; /* key == a && key == b, but a != b */ so->qual_ok = false; /* key == a && key == b, but a !=
* b */
} }
else else
{ {
@ -473,16 +477,18 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
if (isNull) if (isNull)
{ {
/* /*
* Since NULLs are sorted after non-NULLs, we know we have * Since NULLs are sorted after non-NULLs, we know we have
* reached the upper limit of the range of values for this * reached the upper limit of the range of values for this
* index attr. On a forward scan, we can stop if this qual * index attr. On a forward scan, we can stop if this qual is
* is one of the "must match" subset. On a backward scan, * one of the "must match" subset. On a backward scan,
* however, we should keep going. * however, we should keep going.
*/ */
if (keysok < so->numberOfRequiredKeys && if (keysok < so->numberOfRequiredKeys &&
ScanDirectionIsForward(dir)) ScanDirectionIsForward(dir))
*continuescan = false; *continuescan = false;
/* /*
* In any case, this indextuple doesn't match the qual. * In any case, this indextuple doesn't match the qual.
*/ */
@ -498,9 +504,10 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE)) if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE))
{ {
/* /*
* Tuple fails this qual. If it's a required qual, then * Tuple fails this qual. If it's a required qual, then we
* we can conclude no further tuples will pass, either. * can conclude no further tuples will pass, either.
*/ */
if (keysok < so->numberOfRequiredKeys) if (keysok < so->numberOfRequiredKeys)
*continuescan = false; *continuescan = false;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.24 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.25 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.31 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.32 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -70,6 +70,7 @@ Datum
rt_box_size(PG_FUNCTION_ARGS) rt_box_size(PG_FUNCTION_ARGS)
{ {
BOX *a = PG_GETARG_BOX_P(0); BOX *a = PG_GETARG_BOX_P(0);
/* NB: size is an output argument */ /* NB: size is an output argument */
float *size = (float *) PG_GETARG_POINTER(1); float *size = (float *) PG_GETARG_POINTER(1);
@ -155,13 +156,15 @@ Datum
rt_poly_size(PG_FUNCTION_ARGS) rt_poly_size(PG_FUNCTION_ARGS)
{ {
Pointer aptr = PG_GETARG_POINTER(0); Pointer aptr = PG_GETARG_POINTER(0);
/* NB: size is an output argument */ /* NB: size is an output argument */
float *size = (float *) PG_GETARG_POINTER(1); float *size = (float *) PG_GETARG_POINTER(1);
POLYGON *a; POLYGON *a;
double xdim, double xdim,
ydim; ydim;
/* Can't just use GETARG because of possibility that input is NULL; /*
* Can't just use GETARG because of possibility that input is NULL;
* since POLYGON is toastable, GETARG will try to inspect its value * since POLYGON is toastable, GETARG will try to inspect its value
*/ */
if (aptr == NULL) if (aptr == NULL)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.60 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.61 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -88,8 +88,10 @@ rtbuild(PG_FUNCTION_ARGS)
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -101,9 +103,11 @@ rtbuild(PG_FUNCTION_ARGS)
int nhtups, int nhtups,
nitups; nitups;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -171,6 +175,7 @@ rtbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -232,9 +237,7 @@ rtbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -282,8 +285,10 @@ rtinsert(PG_FUNCTION_ARGS)
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
InsertIndexResult res; InsertIndexResult res;
IndexTuple itup; IndexTuple itup;
@ -665,10 +670,10 @@ rtintinsert(Relation r,
old = (IndexTuple) PageGetItem(p, PageGetItemId(p, stk->rts_child)); old = (IndexTuple) PageGetItem(p, PageGetItemId(p, stk->rts_child));
/* /*
* This is a hack. Right now, we force rtree internal keys to be constant * This is a hack. Right now, we force rtree internal keys to be
* size. To fix this, need delete the old key and add both left and * constant size. To fix this, need delete the old key and add both
* right for the two new pages. The insertion of left may force a * left and right for the two new pages. The insertion of left may
* split if the new left key is bigger than the old key. * force a split if the new left key is bigger than the old key.
*/ */
if (IndexTupleSize(old) != IndexTupleSize(ltup)) if (IndexTupleSize(old) != IndexTupleSize(ltup))
@ -794,9 +799,10 @@ rtpicksplit(Relation r,
right_avail_space; right_avail_space;
/* /*
* First, make sure the new item is not so large that we can't possibly * First, make sure the new item is not so large that we can't
* fit it on a page, even by itself. (It's sufficient to make this test * possibly fit it on a page, even by itself. (It's sufficient to
* here, since any oversize tuple must lead to a page split attempt.) * make this test here, since any oversize tuple must lead to a page
* split attempt.)
*/ */
newitemsz = IndexTupleTotalSize(itup); newitemsz = IndexTupleTotalSize(itup);
if (newitemsz > RTPageAvailSpace) if (newitemsz > RTPageAvailSpace)
@ -804,7 +810,8 @@ rtpicksplit(Relation r,
(unsigned long) newitemsz, (unsigned long) RTPageAvailSpace); (unsigned long) newitemsz, (unsigned long) RTPageAvailSpace);
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
newitemoff = OffsetNumberNext(maxoff); /* phony index for new item */ newitemoff = OffsetNumberNext(maxoff); /* phony index for new
* item */
/* Make arrays big enough for worst case, including sentinel */ /* Make arrays big enough for worst case, including sentinel */
nbytes = (maxoff + 2) * sizeof(OffsetNumber); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
@ -827,8 +834,8 @@ rtpicksplit(Relation r,
item_2_sz = IndexTupleTotalSize(item_2); item_2_sz = IndexTupleTotalSize(item_2);
/* /*
* Ignore seed pairs that don't leave room for the new item * Ignore seed pairs that don't leave room for the new item on
* on either split page. * either split page.
*/ */
if (newitemsz + item_1_sz > RTPageAvailSpace && if (newitemsz + item_1_sz > RTPageAvailSpace &&
newitemsz + item_2_sz > RTPageAvailSpace) newitemsz + item_2_sz > RTPageAvailSpace)
@ -841,8 +848,10 @@ rtpicksplit(Relation r,
PointerGetDatum(&size_union)); PointerGetDatum(&size_union));
inter_d = FunctionCall2(&rtstate->interFn, inter_d = FunctionCall2(&rtstate->interFn,
datum_alpha, datum_beta); datum_alpha, datum_beta);
/* The interFn may return a NULL pointer (not an SQL null!)
* to indicate no intersection. sizeFn must cope with this. /*
* The interFn may return a NULL pointer (not an SQL null!) to
* indicate no intersection. sizeFn must cope with this.
*/ */
FunctionCall2(&rtstate->sizeFn, inter_d, FunctionCall2(&rtstate->sizeFn, inter_d,
PointerGetDatum(&size_inter)); PointerGetDatum(&size_inter));
@ -869,6 +878,7 @@ rtpicksplit(Relation r,
if (firsttime) if (firsttime)
{ {
/* /*
* There is no possible split except to put the new item on its * There is no possible split except to put the new item on its
* own page. Since we still have to compute the union rectangles, * own page. Since we still have to compute the union rectangles,
@ -922,8 +932,8 @@ rtpicksplit(Relation r,
/* /*
* If we've already decided where to place this item, just put it * If we've already decided where to place this item, just put it
* on the correct list. Otherwise, we need to figure out which page * on the correct list. Otherwise, we need to figure out which
* needs the least enlargement in order to store the item. * page needs the least enlargement in order to store the item.
*/ */
if (i == seed_1) if (i == seed_1)
@ -961,12 +971,13 @@ rtpicksplit(Relation r,
PointerGetDatum(&size_beta)); PointerGetDatum(&size_beta));
/* /*
* We prefer the page that shows smaller enlargement of its union area * We prefer the page that shows smaller enlargement of its union
* (Guttman's algorithm), but we must take care that at least one page * area (Guttman's algorithm), but we must take care that at least
* will still have room for the new item after this one is added. * one page will still have room for the new item after this one
* is added.
* *
* (We know that all the old items together can fit on one page, * (We know that all the old items together can fit on one page, so
* so we need not worry about any other problem than failing to fit * we need not worry about any other problem than failing to fit
* the new item.) * the new item.)
*/ */
left_feasible = (left_avail_space >= item_1_sz && left_feasible = (left_avail_space >= item_1_sz &&

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.35 2001/01/24 19:42:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.36 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.41 2001/03/18 20:18:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.42 2001/03/22 03:59:17 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

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.28 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.29 2001/03/22 03:59:17 momjian Exp $
* *
* NOTES * NOTES
* This file contains support functions for the high * This file contains support functions for the high

View File

@ -6,7 +6,7 @@
* Copyright (c) 2000, PostgreSQL Global Development Group * Copyright (c) 2000, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.37 2001/03/18 20:18:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.38 2001/03/22 03:59:17 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -32,9 +32,10 @@ VariableCache ShmemVariableCache = NULL;
void void
GetNewTransactionId(TransactionId *xid) GetNewTransactionId(TransactionId *xid)
{ {
/* /*
* During bootstrap initialization, we return the special * During bootstrap initialization, we return the special bootstrap
* bootstrap transaction id. * transaction id.
*/ */
if (AMI_OVERRIDE) if (AMI_OVERRIDE)
{ {
@ -60,9 +61,10 @@ GetNewTransactionId(TransactionId *xid)
void void
ReadNewTransactionId(TransactionId *xid) ReadNewTransactionId(TransactionId *xid)
{ {
/* /*
* During bootstrap initialization, we return the special * During bootstrap initialization, we return the special bootstrap
* bootstrap transaction id. * transaction id.
*/ */
if (AMI_OVERRIDE) if (AMI_OVERRIDE)
{ {
@ -130,10 +132,9 @@ CheckMaxObjectId(Oid assigned_oid)
} }
/* /*
* We have exceeded the logged oid range. * We have exceeded the logged oid range. We should lock the database
* We should lock the database and kill all other backends * and kill all other backends but we are loading oid's that we can
* but we are loading oid's that we can not guarantee are unique * not guarantee are unique anyway, so we must rely on the user.
* anyway, so we must rely on the user.
*/ */
XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH); XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.99 2001/03/13 01:17:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.100 2001/03/22 03:59:18 momjian Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
@ -222,7 +222,8 @@ int DefaultXactIsoLevel = XACT_READ_COMMITTED;
int XactIsoLevel; int XactIsoLevel;
int CommitDelay = 0; /* precommit delay in microseconds */ int CommitDelay = 0; /* precommit delay in microseconds */
int CommitSiblings = 5; /* number of concurrent xacts needed to sleep */ int CommitSiblings = 5; /* number of concurrent xacts needed to
* sleep */
static void (*_RollbackFunc) (void *) = NULL; static void (*_RollbackFunc) (void *) = NULL;
static void *_RollbackData = NULL; static void *_RollbackData = NULL;
@ -679,20 +680,21 @@ RecordTransactionCommit()
rdata.next = NULL; rdata.next = NULL;
START_CRIT_SECTION(); START_CRIT_SECTION();
/* /*
* SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
*/ */
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata); recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
/* /*
* Sleep before commit! So we can flush more than one * Sleep before commit! So we can flush more than one commit
* commit records per single fsync. (The idea is some other * records per single fsync. (The idea is some other backend may
* backend may do the XLogFlush while we're sleeping. This * do the XLogFlush while we're sleeping. This needs work still,
* needs work still, because on most Unixen, the minimum * because on most Unixen, the minimum select() delay is 10msec or
* select() delay is 10msec or more, which is way too long.) * more, which is way too long.)
* *
* We do not sleep if enableFsync is not turned on, nor if there * We do not sleep if enableFsync is not turned on, nor if there are
* are fewer than CommitSiblings other backends with active * fewer than CommitSiblings other backends with active
* transactions. * transactions.
*/ */
if (CommitDelay > 0 && enableFsync && if (CommitDelay > 0 && enableFsync &&
@ -896,10 +898,8 @@ AtAbort_Memory(void)
MemoryContextResetAndDeleteChildren(TransactionCommandContext); MemoryContextResetAndDeleteChildren(TransactionCommandContext);
} }
else else
{
MemoryContextSwitchTo(TopMemoryContext); MemoryContextSwitchTo(TopMemoryContext);
} }
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -1021,6 +1021,7 @@ CurrentXactInProgress(void)
{ {
return CurrentTransactionState->state == TRANS_INPROGRESS; return CurrentTransactionState->state == TRANS_INPROGRESS;
} }
#endif #endif
/* -------------------------------- /* --------------------------------
@ -1143,15 +1144,16 @@ AbortTransaction(void)
/* /*
* Release any spinlocks or buffer context locks we might be holding * Release any spinlocks or buffer context locks we might be holding
* as quickly as possible. (Real locks, however, must be held till * as quickly as possible. (Real locks, however, must be held till we
* we finish aborting.) Releasing spinlocks is critical since we * finish aborting.) Releasing spinlocks is critical since we might
* might try to grab them again while cleaning up! * try to grab them again while cleaning up!
*/ */
ProcReleaseSpins(NULL); ProcReleaseSpins(NULL);
UnlockBuffers(); UnlockBuffers();
/* /*
* Also clean up any open wait for lock, since the lock manager * Also clean up any open wait for lock, since the lock manager will
* will choke if we try to wait for another lock before doing this. * choke if we try to wait for another lock before doing this.
*/ */
LockWaitCancel(); LockWaitCancel();
@ -1327,8 +1329,8 @@ StartTransactionCommand(void)
} }
/* /*
* We must switch to TransactionCommandContext before returning. * We must switch to TransactionCommandContext before returning. This
* This is already done if we called StartTransaction, otherwise not. * is already done if we called StartTransaction, otherwise not.
*/ */
Assert(TransactionCommandContext != NULL); Assert(TransactionCommandContext != NULL);
MemoryContextSwitchTo(TransactionCommandContext); MemoryContextSwitchTo(TransactionCommandContext);
@ -1765,9 +1767,7 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
/* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */ /* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */
} }
else if (info == XLOG_XACT_ABORT) else if (info == XLOG_XACT_ABORT)
{
TransactionIdAbort(record->xl_xid); TransactionIdAbort(record->xl_xid);
}
else else
elog(STOP, "xact_redo: unknown op code %u", info); elog(STOP, "xact_redo: unknown op code %u", info);
} }

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: xid.c,v 1.29 2001/01/24 19:42:51 momjian Exp $ * $Id: xid.c,v 1.30 2001/03/22 03:59:18 momjian Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* XXX WARNING * XXX WARNING
@ -49,6 +49,7 @@ Datum
xidout(PG_FUNCTION_ARGS) xidout(PG_FUNCTION_ARGS)
{ {
TransactionId transactionId = PG_GETARG_TRANSACTIONID(0); TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
/* maximum 32 bit unsigned integer representation takes 10 chars */ /* maximum 32 bit unsigned integer representation takes 10 chars */
char *representation = palloc(11); char *representation = palloc(11);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.62 2001/03/18 20:18:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.63 2001/03/22 03:59:18 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -50,7 +50,8 @@
*/ */
#define SYNC_METHOD_FSYNC 0 #define SYNC_METHOD_FSYNC 0
#define SYNC_METHOD_FDATASYNC 1 #define SYNC_METHOD_FDATASYNC 1
#define SYNC_METHOD_OPEN 2 /* used for both O_SYNC and O_DSYNC */ #define SYNC_METHOD_OPEN 2 /* used for both O_SYNC and
* O_DSYNC */
#if defined(O_SYNC) #if defined(O_SYNC)
#define OPEN_SYNC_FLAG O_SYNC #define OPEN_SYNC_FLAG O_SYNC
@ -91,11 +92,13 @@
/* User-settable parameters */ /* User-settable parameters */
int CheckPointSegments = 3; int CheckPointSegments = 3;
int XLOGbuffers = 8; int XLOGbuffers = 8;
int XLOGfiles = 0; /* how many files to pre-allocate during ckpt */ int XLOGfiles = 0; /* how many files to pre-allocate during
* ckpt */
int XLOG_DEBUG = 0; int XLOG_DEBUG = 0;
char *XLOG_sync_method = NULL; char *XLOG_sync_method = NULL;
const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR; const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;
char XLOG_archive_dir[MAXPGPATH]; /* null string means delete 'em */ char XLOG_archive_dir[MAXPGPATH]; /* null string means
* delete 'em */
/* these are derived from XLOG_sync_method by assign_xlog_sync_method */ /* these are derived from XLOG_sync_method by assign_xlog_sync_method */
static int sync_method = DEFAULT_SYNC_METHOD; static int sync_method = DEFAULT_SYNC_METHOD;
@ -229,6 +232,7 @@ typedef struct XLogCtlData
XLogwrtResult LogwrtResult; XLogwrtResult LogwrtResult;
/* Protected by logwrt_lck: */ /* Protected by logwrt_lck: */
XLogCtlWrite Write; XLogCtlWrite Write;
/* /*
* These values do not change after startup, although the pointed-to * These values do not change after startup, although the pointed-to
* pages and xlblocks values certainly do. Permission to read/write * pages and xlblocks values certainly do. Permission to read/write
@ -384,8 +388,10 @@ static int readFile = -1;
static uint32 readId = 0; static uint32 readId = 0;
static uint32 readSeg = 0; static uint32 readSeg = 0;
static uint32 readOff = 0; static uint32 readOff = 0;
/* Buffer for currently read page (BLCKSZ bytes) */ /* Buffer for currently read page (BLCKSZ bytes) */
static char *readBuf = NULL; static char *readBuf = NULL;
/* State information for XLOG reading */ /* State information for XLOG reading */
static XLogRecPtr ReadRecPtr; static XLogRecPtr ReadRecPtr;
static XLogRecPtr EndRecPtr; static XLogRecPtr EndRecPtr;
@ -463,8 +469,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
} }
/* /*
* In bootstrap mode, we don't actually log anything but XLOG resources; * In bootstrap mode, we don't actually log anything but XLOG
* return a phony record pointer. * resources; return a phony record pointer.
*/ */
if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID) if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
{ {
@ -479,16 +485,17 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
* header isn't added into the CRC yet since we don't know the final * header isn't added into the CRC yet since we don't know the final
* length or info bits quite yet. * length or info bits quite yet.
* *
* We may have to loop back to here if a race condition is detected below. * We may have to loop back to here if a race condition is detected
* We could prevent the race by doing all this work while holding the * below. We could prevent the race by doing all this work while
* insert spinlock, but it seems better to avoid doing CRC calculations * holding the insert spinlock, but it seems better to avoid doing CRC
* while holding the lock. This means we have to be careful about * calculations while holding the lock. This means we have to be
* modifying the rdata list until we know we aren't going to loop back * careful about modifying the rdata list until we know we aren't
* again. The only change we allow ourselves to make earlier is to set * going to loop back again. The only change we allow ourselves to
* rdt->data = NULL in list items we have decided we will have to back * make earlier is to set rdt->data = NULL in list items we have
* up the whole buffer for. This is OK because we will certainly decide * decided we will have to back up the whole buffer for. This is OK
* the same thing again for those items if we do it over; doing it here * because we will certainly decide the same thing again for those
* saves an extra pass over the list later. * items if we do it over; doing it here saves an extra pass over the
* list later.
*/ */
begin:; begin:;
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++) for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
@ -528,6 +535,7 @@ begin:;
{ {
/* OK, put it in this slot */ /* OK, put it in this slot */
dtbuf[i] = rdt->buffer; dtbuf[i] = rdt->buffer;
/* /*
* XXX We assume page LSN is first data on page * XXX We assume page LSN is first data on page
*/ */
@ -596,9 +604,9 @@ begin:;
S_UNLOCK(&(XLogCtl->info_lck)); S_UNLOCK(&(XLogCtl->info_lck));
/* /*
* If cache is half filled then try to acquire logwrt lock * If cache is half filled then try to acquire logwrt lock and
* and do LOGWRT work, but only once per XLogInsert call. * do LOGWRT work, but only once per XLogInsert call. Ignore
* Ignore any fractional blocks in performing this check. * any fractional blocks in performing this check.
*/ */
LogwrtRqst.Write.xrecoff -= LogwrtRqst.Write.xrecoff % BLCKSZ; LogwrtRqst.Write.xrecoff -= LogwrtRqst.Write.xrecoff % BLCKSZ;
if (do_logwrt && if (do_logwrt &&
@ -625,8 +633,9 @@ begin:;
/* /*
* Check to see if my RedoRecPtr is out of date. If so, may have to * Check to see if my RedoRecPtr is out of date. If so, may have to
* go back and recompute everything. This can only happen just after a * go back and recompute everything. This can only happen just after
* checkpoint, so it's better to be slow in this case and fast otherwise. * a checkpoint, so it's better to be slow in this case and fast
* otherwise.
*/ */
if (!XLByteEQ(RedoRecPtr, Insert->RedoRecPtr)) if (!XLByteEQ(RedoRecPtr, Insert->RedoRecPtr))
{ {
@ -640,9 +649,10 @@ begin:;
if (dtbuf_bkp[i] == false && if (dtbuf_bkp[i] == false &&
XLByteLE(dtbuf_lsn[i], RedoRecPtr)) XLByteLE(dtbuf_lsn[i], RedoRecPtr))
{ {
/* /*
* Oops, this buffer now needs to be backed up, but we didn't * Oops, this buffer now needs to be backed up, but we
* think so above. Start over. * didn't think so above. Start over.
*/ */
S_UNLOCK(&(XLogCtl->insert_lck)); S_UNLOCK(&(XLogCtl->insert_lck));
END_CRIT_SECTION(); END_CRIT_SECTION();
@ -658,8 +668,9 @@ begin:;
* this loop, write_len includes the backup block data. * this loop, write_len includes the backup block data.
* *
* Also set the appropriate info bits to show which buffers were backed * Also set the appropriate info bits to show which buffers were backed
* up. The i'th XLR_SET_BKP_BLOCK bit corresponds to the i'th distinct * up. The i'th XLR_SET_BKP_BLOCK bit corresponds to the i'th
* buffer value (ignoring InvalidBuffer) appearing in the rdata list. * distinct buffer value (ignoring InvalidBuffer) appearing in the
* rdata list.
*/ */
write_len = len; write_len = len;
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++) for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
@ -795,14 +806,15 @@ begin:;
freespace = INSERT_FREESPACE(Insert); freespace = INSERT_FREESPACE(Insert);
/* /*
* The recptr I return is the beginning of the *next* record. * The recptr I return is the beginning of the *next* record. This
* This will be stored as LSN for changed data pages... * will be stored as LSN for changed data pages...
*/ */
INSERT_RECPTR(RecPtr, Insert, curridx); INSERT_RECPTR(RecPtr, Insert, curridx);
/* Need to update shared LogwrtRqst if some block was filled up */ /* Need to update shared LogwrtRqst if some block was filled up */
if (freespace < SizeOfXLogRecord) if (freespace < SizeOfXLogRecord)
updrqst = true; /* curridx is filled and available for writing out */ updrqst = true; /* curridx is filled and available for
* writing out */
else else
curridx = PrevBufIdx(curridx); curridx = PrevBufIdx(curridx);
WriteRqst = XLogCtl->xlblocks[curridx]; WriteRqst = XLogCtl->xlblocks[curridx];
@ -850,9 +862,9 @@ AdvanceXLInsertBuffer(void)
LogwrtResult = Insert->LogwrtResult; LogwrtResult = Insert->LogwrtResult;
/* /*
* Get ending-offset of the buffer page we need to replace (this may be * Get ending-offset of the buffer page we need to replace (this may
* zero if the buffer hasn't been used yet). Fall through if it's already * be zero if the buffer hasn't been used yet). Fall through if it's
* written out. * already written out.
*/ */
OldPageRqstPtr = XLogCtl->xlblocks[nextidx]; OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
if (!XLByteLE(OldPageRqstPtr, LogwrtResult.Write)) if (!XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
@ -883,8 +895,8 @@ AdvanceXLInsertBuffer(void)
} }
/* /*
* LogwrtResult lock is busy or we know the page is still dirty. * LogwrtResult lock is busy or we know the page is still
* Try to acquire logwrt lock and write full blocks. * dirty. Try to acquire logwrt lock and write full blocks.
*/ */
if (!TAS(&(XLogCtl->logwrt_lck))) if (!TAS(&(XLogCtl->logwrt_lck)))
{ {
@ -896,9 +908,10 @@ AdvanceXLInsertBuffer(void)
Insert->LogwrtResult = LogwrtResult; Insert->LogwrtResult = LogwrtResult;
break; break;
} }
/* /*
* Have to write buffers while holding insert lock. * Have to write buffers while holding insert lock. This
* This is not good, so only write as much as we absolutely * is not good, so only write as much as we absolutely
* must. * must.
*/ */
WriteRqst.Write = OldPageRqstPtr; WriteRqst.Write = OldPageRqstPtr;
@ -934,9 +947,10 @@ AdvanceXLInsertBuffer(void)
Insert->curridx = nextidx; Insert->curridx = nextidx;
Insert->currpage = (XLogPageHeader) (XLogCtl->pages + nextidx * BLCKSZ); Insert->currpage = (XLogPageHeader) (XLogCtl->pages + nextidx * BLCKSZ);
Insert->currpos = ((char *) Insert->currpage) + SizeOfXLogPHD; Insert->currpos = ((char *) Insert->currpage) + SizeOfXLogPHD;
/* /*
* Be sure to re-zero the buffer so that bytes beyond what we've written * Be sure to re-zero the buffer so that bytes beyond what we've
* will look like zeroes and not valid XLOG records... * written will look like zeroes and not valid XLOG records...
*/ */
MemSet((char *) Insert->currpage, 0, BLCKSZ); MemSet((char *) Insert->currpage, 0, BLCKSZ);
Insert->currpage->xlp_magic = XLOG_PAGE_MAGIC; Insert->currpage->xlp_magic = XLOG_PAGE_MAGIC;
@ -959,11 +973,15 @@ XLogWrite(XLogwrtRqst WriteRqst)
bool ispartialpage; bool ispartialpage;
bool use_existent; bool use_existent;
/* Update local LogwrtResult (caller probably did this already, but...) */ /*
* Update local LogwrtResult (caller probably did this already,
* but...)
*/
LogwrtResult = Write->LogwrtResult; LogwrtResult = Write->LogwrtResult;
while (XLByteLT(LogwrtResult.Write, WriteRqst.Write)) while (XLByteLT(LogwrtResult.Write, WriteRqst.Write))
{ {
/* /*
* Make sure we're not ahead of the insert process. This could * Make sure we're not ahead of the insert process. This could
* happen if we're passed a bogus WriteRqst.Write that is past the * happen if we're passed a bogus WriteRqst.Write that is past the
@ -979,6 +997,7 @@ XLogWrite(XLogwrtRqst WriteRqst)
if (!XLByteInPrevSeg(LogwrtResult.Write, openLogId, openLogSeg)) if (!XLByteInPrevSeg(LogwrtResult.Write, openLogId, openLogSeg))
{ {
/* /*
* Switch to new logfile segment. * Switch to new logfile segment.
*/ */
@ -1011,11 +1030,12 @@ XLogWrite(XLogwrtRqst WriteRqst)
ControlFile->logSeg = openLogSeg + 1; ControlFile->logSeg = openLogSeg + 1;
ControlFile->time = time(NULL); ControlFile->time = time(NULL);
UpdateControlFile(); UpdateControlFile();
/* /*
* Signal postmaster to start a checkpoint if it's been too * Signal postmaster to start a checkpoint if it's been
* long since the last one. (We look at local copy of * too long since the last one. (We look at local copy of
* RedoRecPtr which might be a little out of date, but should * RedoRecPtr which might be a little out of date, but
* be close enough for this purpose.) * should be close enough for this purpose.)
*/ */
if (IsUnderPostmaster && if (IsUnderPostmaster &&
(openLogId != RedoRecPtr.xlogid || (openLogId != RedoRecPtr.xlogid ||
@ -1056,9 +1076,9 @@ XLogWrite(XLogwrtRqst WriteRqst)
/* /*
* If we just wrote the whole last page of a logfile segment, * If we just wrote the whole last page of a logfile segment,
* fsync the segment immediately. This avoids having to go back * fsync the segment immediately. This avoids having to go back
* and re-open prior segments when an fsync request comes along later. * and re-open prior segments when an fsync request comes along
* Doing it here ensures that one and only one backend will perform * later. Doing it here ensures that one and only one backend will
* this fsync. * perform this fsync.
*/ */
if (openLogOff >= XLogSegSize && !ispartialpage) if (openLogOff >= XLogSegSize && !ispartialpage)
{ {
@ -1081,10 +1101,11 @@ XLogWrite(XLogwrtRqst WriteRqst)
if (XLByteLT(LogwrtResult.Flush, WriteRqst.Flush) && if (XLByteLT(LogwrtResult.Flush, WriteRqst.Flush) &&
XLByteLT(LogwrtResult.Flush, LogwrtResult.Write)) XLByteLT(LogwrtResult.Flush, LogwrtResult.Write))
{ {
/* /*
* Could get here without iterating above loop, in which case * Could get here without iterating above loop, in which case we
* we might have no open file or the wrong one. However, we do * might have no open file or the wrong one. However, we do not
* not need to fsync more than one file. * need to fsync more than one file.
*/ */
if (sync_method != SYNC_METHOD_OPEN) if (sync_method != SYNC_METHOD_OPEN)
{ {
@ -1110,8 +1131,8 @@ XLogWrite(XLogwrtRqst WriteRqst)
/* /*
* Update shared-memory status * Update shared-memory status
* *
* We make sure that the shared 'request' values do not fall behind * We make sure that the shared 'request' values do not fall behind the
* the 'result' values. This is not absolutely essential, but it saves * 'result' values. This is not absolutely essential, but it saves
* some code in a couple of places. * some code in a couple of places.
*/ */
S_LOCK(&(XLogCtl->info_lck)); S_LOCK(&(XLogCtl->info_lck));
@ -1163,8 +1184,9 @@ XLogFlush(XLogRecPtr record)
* Since fsync is usually a horribly expensive operation, we try to * Since fsync is usually a horribly expensive operation, we try to
* piggyback as much data as we can on each fsync: if we see any more * piggyback as much data as we can on each fsync: if we see any more
* data entered into the xlog buffer, we'll write and fsync that too, * data entered into the xlog buffer, we'll write and fsync that too,
* so that the final value of LogwrtResult.Flush is as large as possible. * so that the final value of LogwrtResult.Flush is as large as
* This gives us some chance of avoiding another fsync immediately after. * possible. This gives us some chance of avoiding another fsync
* immediately after.
*/ */
/* initialize to given target; may increase below */ /* initialize to given target; may increase below */
@ -1192,9 +1214,7 @@ XLogFlush(XLogRecPtr record)
uint32 freespace = INSERT_FREESPACE(Insert); uint32 freespace = INSERT_FREESPACE(Insert);
if (freespace < SizeOfXLogRecord) /* buffer is full */ if (freespace < SizeOfXLogRecord) /* buffer is full */
{
WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx]; WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx];
}
else else
{ {
WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx]; WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx];
@ -1257,7 +1277,8 @@ XLogFileInit(uint32 log, uint32 seg,
XLogFileName(path, log, seg); XLogFileName(path, log, seg);
/* /*
* Try to use existent file (checkpoint maker may have created it already) * Try to use existent file (checkpoint maker may have created it
* already)
*/ */
if (*use_existent) if (*use_existent)
{ {
@ -1274,10 +1295,10 @@ XLogFileInit(uint32 log, uint32 seg,
} }
/* /*
* Initialize an empty (all zeroes) segment. NOTE: it is possible that * Initialize an empty (all zeroes) segment. NOTE: it is possible
* another process is doing the same thing. If so, we will end up * that another process is doing the same thing. If so, we will end
* pre-creating an extra log segment. That seems OK, and better than * up pre-creating an extra log segment. That seems OK, and better
* holding the spinlock throughout this lengthy process. * than holding the spinlock throughout this lengthy process.
*/ */
snprintf(tmppath, MAXPGPATH, "%s%cxlogtemp.%d", snprintf(tmppath, MAXPGPATH, "%s%cxlogtemp.%d",
XLogDir, SEP_CHAR, (int) getpid()); XLogDir, SEP_CHAR, (int) getpid());
@ -1306,7 +1327,10 @@ XLogFileInit(uint32 log, uint32 seg,
{ {
int save_errno = errno; int save_errno = errno;
/* If we fail to make the file, delete it to release disk space */ /*
* If we fail to make the file, delete it to release disk
* space
*/
unlink(tmppath); unlink(tmppath);
errno = save_errno; errno = save_errno;
@ -1337,9 +1361,7 @@ XLogFileInit(uint32 log, uint32 seg,
strcpy(targpath, path); strcpy(targpath, path);
if (!*use_existent) if (!*use_existent)
{
unlink(targpath); unlink(targpath);
}
else else
{ {
while ((fd = BasicOpenFile(targpath, O_RDWR | PG_BINARY, while ((fd = BasicOpenFile(targpath, O_RDWR | PG_BINARY,
@ -1569,7 +1591,8 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
COMP_CRC64(crc, blk + sizeof(crc64), COMP_CRC64(crc, blk + sizeof(crc64),
sizeof(BkpBlock) - sizeof(crc64)); sizeof(BkpBlock) - sizeof(crc64));
FIN_CRC64(crc); FIN_CRC64(crc);
memcpy((char*)&cbuf, blk, sizeof(crc64)); /* don't assume alignment */ memcpy((char *) &cbuf, blk, sizeof(crc64)); /* don't assume
* alignment */
if (!EQ_CRC64(cbuf, crc)) if (!EQ_CRC64(cbuf, crc))
{ {
@ -1609,13 +1632,14 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
if (readBuf == NULL) if (readBuf == NULL)
{ {
/* /*
* First time through, permanently allocate readBuf. We do it * First time through, permanently allocate readBuf. We do it
* this way, rather than just making a static array, for two * this way, rather than just making a static array, for two
* reasons: (1) no need to waste the storage in most instantiations * reasons: (1) no need to waste the storage in most
* of the backend; (2) a static char array isn't guaranteed to * instantiations of the backend; (2) a static char array isn't
* have any particular alignment, whereas malloc() will provide * guaranteed to have any particular alignment, whereas malloc()
* MAXALIGN'd storage. * will provide MAXALIGN'd storage.
*/ */
readBuf = (char *) malloc(BLCKSZ); readBuf = (char *) malloc(BLCKSZ);
Assert(readBuf != NULL); Assert(readBuf != NULL);
@ -1688,9 +1712,10 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
record = (XLogRecord *) ((char *) readBuf + RecPtr->xrecoff % BLCKSZ); record = (XLogRecord *) ((char *) readBuf + RecPtr->xrecoff % BLCKSZ);
got_record:; got_record:;
/* /*
* Currently, xl_len == 0 must be bad data, but that might not be * Currently, xl_len == 0 must be bad data, but that might not be true
* true forever. See note in XLogInsert. * forever. See note in XLogInsert.
*/ */
if (record->xl_len == 0) if (record->xl_len == 0)
{ {
@ -1698,8 +1723,10 @@ got_record:;
RecPtr->xlogid, RecPtr->xrecoff); RecPtr->xlogid, RecPtr->xrecoff);
goto next_record_is_invalid; goto next_record_is_invalid;
} }
/* /*
* Compute total length of record including any appended backup blocks. * Compute total length of record including any appended backup
* blocks.
*/ */
total_len = SizeOfXLogRecord + record->xl_len; total_len = SizeOfXLogRecord + record->xl_len;
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++) for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
@ -1708,6 +1735,7 @@ got_record:;
continue; continue;
total_len += sizeof(BkpBlock) + BLCKSZ; total_len += sizeof(BkpBlock) + BLCKSZ;
} }
/* /*
* Make sure it will fit in buffer (currently, it is mechanically * Make sure it will fit in buffer (currently, it is mechanically
* impossible for this test to fail, but it seems like a good idea * impossible for this test to fail, but it seems like a good idea
@ -1839,14 +1867,16 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI)
hdr->xlp_info, readId, readSeg, readOff); hdr->xlp_info, readId, readSeg, readOff);
return false; return false;
} }
/* /*
* We disbelieve a SUI less than the previous page's SUI, or more * We disbelieve a SUI less than the previous page's SUI, or more than
* than a few counts greater. In theory as many as 512 shutdown * a few counts greater. In theory as many as 512 shutdown checkpoint
* checkpoint records could appear on a 32K-sized xlog page, so * records could appear on a 32K-sized xlog page, so that's the most
* that's the most differential there could legitimately be. * differential there could legitimately be.
* *
* Note this check can only be applied when we are reading the next page * Note this check can only be applied when we are reading the next page
* in sequence, so ReadRecord passes a flag indicating whether to check. * in sequence, so ReadRecord passes a flag indicating whether to
* check.
*/ */
if (checkSUI) if (checkSUI)
{ {
@ -1891,8 +1921,10 @@ WriteControlFile(void)
{ {
int fd; int fd;
char buffer[BLCKSZ]; /* need not be aligned */ char buffer[BLCKSZ]; /* need not be aligned */
#ifdef USE_LOCALE #ifdef USE_LOCALE
char *localeptr; char *localeptr;
#endif #endif
/* /*
@ -1911,10 +1943,11 @@ WriteControlFile(void)
if (!localeptr) if (!localeptr)
elog(STOP, "Invalid LC_CTYPE setting"); elog(STOP, "Invalid LC_CTYPE setting");
StrNCpy(ControlFile->lc_ctype, localeptr, LOCALE_NAME_BUFLEN); StrNCpy(ControlFile->lc_ctype, localeptr, LOCALE_NAME_BUFLEN);
/* /*
* Issue warning notice if initdb'ing in a locale that will not permit * Issue warning notice if initdb'ing in a locale that will not permit
* LIKE index optimization. This is not a clean place to do it, but * LIKE index optimization. This is not a clean place to do it, but I
* I don't see a better place either... * don't see a better place either...
*/ */
if (!locale_is_like_safe()) if (!locale_is_like_safe())
elog(NOTICE, "Initializing database with %s collation order." elog(NOTICE, "Initializing database with %s collation order."
@ -1936,11 +1969,11 @@ WriteControlFile(void)
FIN_CRC64(ControlFile->crc); FIN_CRC64(ControlFile->crc);
/* /*
* We write out BLCKSZ bytes into pg_control, zero-padding the * We write out BLCKSZ bytes into pg_control, zero-padding the excess
* excess over sizeof(ControlFileData). This reduces the odds * over sizeof(ControlFileData). This reduces the odds of
* of premature-EOF errors when reading pg_control. We'll still * premature-EOF errors when reading pg_control. We'll still fail
* fail when we check the contents of the file, but hopefully with * when we check the contents of the file, but hopefully with a more
* a more specific error than "couldn't read pg_control". * specific error than "couldn't read pg_control".
*/ */
if (sizeof(ControlFileData) > BLCKSZ) if (sizeof(ControlFileData) > BLCKSZ)
elog(STOP, "sizeof(ControlFileData) is too large ... fix xlog.c"); elog(STOP, "sizeof(ControlFileData) is too large ... fix xlog.c");
@ -2002,10 +2035,11 @@ ReadControlFile(void)
elog(STOP, "Invalid CRC in control file"); elog(STOP, "Invalid CRC in control file");
/* /*
* Do compatibility checking immediately. We do this here for 2 reasons: * Do compatibility checking immediately. We do this here for 2
* reasons:
* *
* (1) if the database isn't compatible with the backend executable, * (1) if the database isn't compatible with the backend executable, we
* we want to abort before we can possibly do any damage; * want to abort before we can possibly do any damage;
* *
* (2) this code is executed in the postmaster, so the setlocale() will * (2) this code is executed in the postmaster, so the setlocale() will
* propagate to forked backends, which aren't going to read this file * propagate to forked backends, which aren't going to read this file
@ -2096,6 +2130,7 @@ XLOGShmemInit(void)
Assert(!found); Assert(!found);
memset(XLogCtl, 0, sizeof(XLogCtlData)); memset(XLogCtl, 0, sizeof(XLogCtlData));
/* /*
* Since XLogCtlData contains XLogRecPtr fields, its sizeof should be * Since XLogCtlData contains XLogRecPtr fields, its sizeof should be
* a multiple of the alignment for same, so no extra alignment padding * a multiple of the alignment for same, so no extra alignment padding
@ -2104,9 +2139,10 @@ XLOGShmemInit(void)
XLogCtl->xlblocks = (XLogRecPtr *) XLogCtl->xlblocks = (XLogRecPtr *)
(((char *) XLogCtl) + sizeof(XLogCtlData)); (((char *) XLogCtl) + sizeof(XLogCtlData));
memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers); memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers);
/* /*
* Here, on the other hand, we must MAXALIGN to ensure the page buffers * Here, on the other hand, we must MAXALIGN to ensure the page
* have worst-case alignment. * buffers have worst-case alignment.
*/ */
XLogCtl->pages = XLogCtl->pages =
((char *) XLogCtl) + MAXALIGN(sizeof(XLogCtlData) + ((char *) XLogCtl) + MAXALIGN(sizeof(XLogCtlData) +
@ -2114,8 +2150,8 @@ XLOGShmemInit(void)
memset(XLogCtl->pages, 0, BLCKSZ * XLOGbuffers); memset(XLogCtl->pages, 0, BLCKSZ * XLOGbuffers);
/* /*
* Do basic initialization of XLogCtl shared data. * Do basic initialization of XLogCtl shared data. (StartupXLOG will
* (StartupXLOG will fill in additional info.) * fill in additional info.)
*/ */
XLogCtl->XLogCacheByte = BLCKSZ * XLOGbuffers; XLogCtl->XLogCacheByte = BLCKSZ * XLOGbuffers;
XLogCtl->XLogCacheBlck = XLOGbuffers - 1; XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
@ -2246,8 +2282,8 @@ StartupXLOG(void)
/* /*
* Read control file and check XLOG status looks valid. * Read control file and check XLOG status looks valid.
* *
* Note: in most control paths, *ControlFile is already valid and we * Note: in most control paths, *ControlFile is already valid and we need
* need not do ReadControlFile() here, but might as well do it to be sure. * not do ReadControlFile() here, but might as well do it to be sure.
*/ */
ReadControlFile(); ReadControlFile();
@ -2297,10 +2333,8 @@ StartupXLOG(void)
InRecovery = true; /* force recovery even if SHUTDOWNED */ InRecovery = true; /* force recovery even if SHUTDOWNED */
} }
else else
{
elog(STOP, "Unable to locate a valid CheckPoint record"); elog(STOP, "Unable to locate a valid CheckPoint record");
} }
}
LastRec = RecPtr = checkPointLoc; LastRec = RecPtr = checkPointLoc;
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN); wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN);
@ -2336,9 +2370,7 @@ StartupXLOG(void)
InRecovery = true; InRecovery = true;
} }
else if (ControlFile->state != DB_SHUTDOWNED) else if (ControlFile->state != DB_SHUTDOWNED)
{
InRecovery = true; InRecovery = true;
}
/* REDO */ /* REDO */
if (InRecovery) if (InRecovery)
@ -2355,7 +2387,8 @@ StartupXLOG(void)
/* Is REDO required ? */ /* Is REDO required ? */
if (XLByteLT(checkPoint.redo, RecPtr)) if (XLByteLT(checkPoint.redo, RecPtr))
record = ReadRecord(&(checkPoint.redo), STOP, buffer); record = ReadRecord(&(checkPoint.redo), STOP, buffer);
else /* read past CheckPoint record */ else
/* read past CheckPoint record */
record = ReadRecord(NULL, LOG, buffer); record = ReadRecord(NULL, LOG, buffer);
if (record != NULL) if (record != NULL)
@ -2411,8 +2444,11 @@ StartupXLOG(void)
XLogCtl->xlblocks[0].xrecoff = XLogCtl->xlblocks[0].xrecoff =
((EndOfLog.xrecoff - 1) / BLCKSZ + 1) * BLCKSZ; ((EndOfLog.xrecoff - 1) / BLCKSZ + 1) * BLCKSZ;
Insert = &XLogCtl->Insert; Insert = &XLogCtl->Insert;
/* Tricky point here: readBuf contains the *last* block that the LastRec
* record spans, not the one it starts in, which is what we want. /*
* Tricky point here: readBuf contains the *last* block that the
* LastRec record spans, not the one it starts in, which is what we
* want.
*/ */
Assert(readOff == (XLogCtl->xlblocks[0].xrecoff - BLCKSZ) % XLogSegSize); Assert(readOff == (XLogCtl->xlblocks[0].xrecoff - BLCKSZ) % XLogSegSize);
memcpy((char *) Insert->currpage, readBuf, BLCKSZ); memcpy((char *) Insert->currpage, readBuf, BLCKSZ);
@ -2458,6 +2494,7 @@ StartupXLOG(void)
if (InRecovery) if (InRecovery)
{ {
/* /*
* In case we had to use the secondary checkpoint, make sure that * In case we had to use the secondary checkpoint, make sure that
* it will still be shown as the secondary checkpoint after this * it will still be shown as the secondary checkpoint after this
@ -2639,17 +2676,17 @@ CreateCheckPoint(bool shutdown)
/* /*
* If this isn't a shutdown, and we have not inserted any XLOG records * If this isn't a shutdown, and we have not inserted any XLOG records
* since the start of the last checkpoint, skip the checkpoint. The * since the start of the last checkpoint, skip the checkpoint. The
* idea here is to avoid inserting duplicate checkpoints when the system * idea here is to avoid inserting duplicate checkpoints when the
* is idle. That wastes log space, and more importantly it exposes us to * system is idle. That wastes log space, and more importantly it
* possible loss of both current and previous checkpoint records if the * exposes us to possible loss of both current and previous checkpoint
* machine crashes just as we're writing the update. (Perhaps it'd make * records if the machine crashes just as we're writing the update.
* even more sense to checkpoint only when the previous checkpoint record * (Perhaps it'd make even more sense to checkpoint only when the
* is in a different xlog page?) * previous checkpoint record is in a different xlog page?)
* *
* We have to make two tests to determine that nothing has happened since * We have to make two tests to determine that nothing has happened since
* the start of the last checkpoint: current insertion point must match * the start of the last checkpoint: current insertion point must
* the end of the last checkpoint record, and its redo pointer must point * match the end of the last checkpoint record, and its redo pointer
* to itself. * must point to itself.
*/ */
if (!shutdown) if (!shutdown)
{ {
@ -2687,16 +2724,18 @@ CreateCheckPoint(bool shutdown)
freespace = BLCKSZ - SizeOfXLogPHD; freespace = BLCKSZ - SizeOfXLogPHD;
} }
INSERT_RECPTR(checkPoint.redo, Insert, Insert->curridx); INSERT_RECPTR(checkPoint.redo, Insert, Insert->curridx);
/* /*
* Here we update the shared RedoRecPtr for future XLogInsert calls; * Here we update the shared RedoRecPtr for future XLogInsert calls;
* this must be done while holding the insert lock. * this must be done while holding the insert lock.
*/ */
RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo; RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
/* /*
* Get UNDO record ptr - this is oldest of PROC->logRec values. * Get UNDO record ptr - this is oldest of PROC->logRec values. We do
* We do this while holding insert lock to ensure that we won't miss * this while holding insert lock to ensure that we won't miss any
* any about-to-commit transactions (UNDO must include all xacts that * about-to-commit transactions (UNDO must include all xacts that have
* have commits after REDO point). * commits after REDO point).
*/ */
checkPoint.undo = GetUndoRecPtr(); checkPoint.undo = GetUndoRecPtr();
@ -2720,8 +2759,8 @@ CreateCheckPoint(bool shutdown)
SpinRelease(OidGenLockId); SpinRelease(OidGenLockId);
/* /*
* Having constructed the checkpoint record, ensure all shmem disk buffers * Having constructed the checkpoint record, ensure all shmem disk
* are flushed to disk. * buffers are flushed to disk.
*/ */
FlushBufferPool(); FlushBufferPool();
@ -2748,9 +2787,9 @@ CreateCheckPoint(bool shutdown)
elog(STOP, "XLog concurrent activity while data base is shutting down"); elog(STOP, "XLog concurrent activity while data base is shutting down");
/* /*
* Remember location of prior checkpoint's earliest info. * Remember location of prior checkpoint's earliest info. Oldest item
* Oldest item is redo or undo, whichever is older; but watch out * is redo or undo, whichever is older; but watch out for case that
* for case that undo = 0. * undo = 0.
*/ */
if (ControlFile->checkPointCopy.undo.xrecoff != 0 && if (ControlFile->checkPointCopy.undo.xrecoff != 0 &&
XLByteLT(ControlFile->checkPointCopy.undo, XLByteLT(ControlFile->checkPointCopy.undo,
@ -2846,9 +2885,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
/* In an ONLINE checkpoint, treat the counters like NEXTOID */ /* In an ONLINE checkpoint, treat the counters like NEXTOID */
if (ShmemVariableCache->nextXid < checkPoint.nextXid) if (ShmemVariableCache->nextXid < checkPoint.nextXid)
{
ShmemVariableCache->nextXid = checkPoint.nextXid; ShmemVariableCache->nextXid = checkPoint.nextXid;
}
if (ShmemVariableCache->nextOid < checkPoint.nextOid) if (ShmemVariableCache->nextOid < checkPoint.nextOid)
{ {
ShmemVariableCache->nextOid = checkPoint.nextOid; ShmemVariableCache->nextOid = checkPoint.nextOid;
@ -2871,6 +2908,7 @@ xlog_desc(char *buf, uint8 xl_info, char* rec)
info == XLOG_CHECKPOINT_ONLINE) info == XLOG_CHECKPOINT_ONLINE)
{ {
CheckPoint *checkpoint = (CheckPoint *) rec; CheckPoint *checkpoint = (CheckPoint *) rec;
sprintf(buf + strlen(buf), "checkpoint: redo %u/%u; undo %u/%u; " sprintf(buf + strlen(buf), "checkpoint: redo %u/%u; undo %u/%u; "
"sui %u; xid %u; oid %u; %s", "sui %u; xid %u; oid %u; %s",
checkpoint->redo.xlogid, checkpoint->redo.xrecoff, checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
@ -2923,15 +2961,19 @@ xlog_outrec(char *buf, XLogRecord *record)
bool bool
check_xlog_sync_method(const char *method) check_xlog_sync_method(const char *method)
{ {
if (strcasecmp(method, "fsync") == 0) return true; if (strcasecmp(method, "fsync") == 0)
return true;
#ifdef HAVE_FDATASYNC #ifdef HAVE_FDATASYNC
if (strcasecmp(method, "fdatasync") == 0) return true; if (strcasecmp(method, "fdatasync") == 0)
return true;
#endif #endif
#ifdef OPEN_SYNC_FLAG #ifdef OPEN_SYNC_FLAG
if (strcasecmp(method, "open_sync") == 0) return true; if (strcasecmp(method, "open_sync") == 0)
return true;
#endif #endif
#ifdef OPEN_DATASYNC_FLAG #ifdef OPEN_DATASYNC_FLAG
if (strcasecmp(method, "open_datasync") == 0) return true; if (strcasecmp(method, "open_datasync") == 0)
return true;
#endif #endif
return false; return false;
} }
@ -2978,11 +3020,12 @@ assign_xlog_sync_method(const char *method)
if (sync_method != new_sync_method || open_sync_bit != new_sync_bit) if (sync_method != new_sync_method || open_sync_bit != new_sync_bit)
{ {
/* /*
* To ensure that no blocks escape unsynced, force an fsync on * To ensure that no blocks escape unsynced, force an fsync on the
* the currently open log segment (if any). Also, if the open * currently open log segment (if any). Also, if the open flag is
* flag is changing, close the log file so it will be reopened * changing, close the log file so it will be reopened (with new
* (with new flag bit) at next use. * flag bit) at next use.
*/ */
if (openLogFile >= 0) if (openLogFile >= 0)
{ {

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.14 2001/03/13 01:17:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.15 2001/03/22 03:59:18 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -239,6 +239,7 @@ static XLogRelDesc *_xlrelarr = NULL;
static Form_pg_class _xlpgcarr = NULL; static Form_pg_class _xlpgcarr = NULL;
static int _xlast = 0; static int _xlast = 0;
static int _xlcnt = 0; static int _xlcnt = 0;
#define _XLOG_RELCACHESIZE 512 #define _XLOG_RELCACHESIZE 512
static void static void

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.46 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.47 2001/03/22 03:59:18 momjian Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
@ -250,8 +250,8 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
num; num;
/* /*
* If ACL is null, default to "OK" --- this should not happen, * If ACL is null, default to "OK" --- this should not happen, since
* since caller should have inserted appropriate default * caller should have inserted appropriate default
*/ */
if (!acl) if (!acl)
{ {
@ -265,8 +265,8 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
/* /*
* We'll treat the empty ACL like that, too, although this is more * We'll treat the empty ACL like that, too, although this is more
* like an error (i.e., you manually blew away your ACL array) -- the * like an error (i.e., you manually blew away your ACL array) -- the
* system never creates an empty ACL, since there must always be * system never creates an empty ACL, since there must always be a
* a "world" entry in the first slot. * "world" entry in the first slot.
*/ */
if (num < 1) if (num < 1)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.39 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.40 2001/03/22 03:59:19 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.160 2001/02/14 21:34:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.161 2001/03/22 03:59:19 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -270,7 +270,11 @@ heap_create(char *relname,
if (istemp) if (istemp)
{ {
/* replace relname of caller with a unique name for a temp relation */
/*
* replace relname of caller with a unique name for a temp
* relation
*/
snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u", snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",
(int) MyProcPid, uniqueId++); (int) MyProcPid, uniqueId++);
} }
@ -738,6 +742,7 @@ AddNewRelationTuple(Relation pg_class_desc,
static void static void
AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid) AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
{ {
/* /*
* The sizes are set to oid size because it makes implementing sets * The sizes are set to oid size because it makes implementing sets
* MUCH easier, and no one (we hope) uses these fields to figure out * MUCH easier, and no one (we hope) uses these fields to figure out
@ -1025,9 +1030,7 @@ RelationRemoveInheritance(Relation relation)
&entry); &entry);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
simple_heap_delete(catalogRelation, &tuple->t_self); simple_heap_delete(catalogRelation, &tuple->t_self);
}
heap_endscan(scan); heap_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock); heap_close(catalogRelation, RowExclusiveLock);
@ -1152,8 +1155,8 @@ RelationTruncateIndexes(Oid heapId)
/* /*
* We have to re-open the heap rel each time through this loop * We have to re-open the heap rel each time through this loop
* because index_build will close it again. We need grab no lock, * because index_build will close it again. We need grab no lock,
* however, because we assume heap_truncate is holding an exclusive * however, because we assume heap_truncate is holding an
* lock on the heap rel. * exclusive lock on the heap rel.
*/ */
heapRelation = heap_open(heapId, NoLock); heapRelation = heap_open(heapId, NoLock);
@ -1164,8 +1167,8 @@ RelationTruncateIndexes(Oid heapId)
LockRelation(currentIndex, AccessExclusiveLock); LockRelation(currentIndex, AccessExclusiveLock);
/* /*
* Drop any buffers associated with this index. If they're * Drop any buffers associated with this index. If they're dirty,
* dirty, they're just dropped without bothering to flush to disk. * they're just dropped without bothering to flush to disk.
*/ */
DropRelationBuffers(currentIndex); DropRelationBuffers(currentIndex);
@ -1177,6 +1180,7 @@ RelationTruncateIndexes(Oid heapId)
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
currentIndex, accessMethodId); currentIndex, accessMethodId);
index_build(heapRelation, currentIndex, indexInfo, NULL); index_build(heapRelation, currentIndex, indexInfo, NULL);
/* /*
* index_build will close both the heap and index relations (but * index_build will close both the heap and index relations (but
* not give up the locks we hold on them). * not give up the locks we hold on them).
@ -1981,9 +1985,7 @@ RemoveAttrDefault(Relation rel)
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key); adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
{
simple_heap_delete(adrel, &tup->t_self); simple_heap_delete(adrel, &tup->t_self);
}
heap_endscan(adscan); heap_endscan(adscan);
heap_close(adrel, RowExclusiveLock); heap_close(adrel, RowExclusiveLock);
@ -2005,9 +2007,7 @@ RemoveRelCheck(Relation rel)
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
{
simple_heap_delete(rcrel, &tup->t_self); simple_heap_delete(rcrel, &tup->t_self);
}
heap_endscan(rcscan); heap_endscan(rcscan);
heap_close(rcrel, RowExclusiveLock); heap_close(rcrel, RowExclusiveLock);
@ -2044,9 +2044,7 @@ RemoveStatistics(Relation rel)
scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key); scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
simple_heap_delete(pgstatistic, &tuple->t_self); simple_heap_delete(pgstatistic, &tuple->t_self);
}
heap_endscan(scan); heap_endscan(scan);
heap_close(pgstatistic, RowExclusiveLock); heap_close(pgstatistic, RowExclusiveLock);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.142 2001/02/23 09:31:52 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.143 2001/03/22 03:59:19 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -301,7 +301,8 @@ ConstructTupleDescriptor(Relation heapRelation,
memcpy(to, from, ATTRIBUTE_TUPLE_SIZE); memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);
/* /*
* Fix the stuff that should not be the same as the underlying attr * Fix the stuff that should not be the same as the underlying
* attr
*/ */
to->attnum = i + 1; to->attnum = i + 1;
@ -311,9 +312,9 @@ ConstructTupleDescriptor(Relation heapRelation,
to->attcacheoff = -1; to->attcacheoff = -1;
/* /*
* We do not yet have the correct relation OID for the index, * We do not yet have the correct relation OID for the index, so
* so just set it invalid for now. InitializeAttributeOids() * just set it invalid for now. InitializeAttributeOids() will
* will fix it later. * fix it later.
*/ */
to->attrelid = InvalidOid; to->attrelid = InvalidOid;
} }
@ -1008,10 +1009,8 @@ index_create(char *heapRelationName,
/* XXX shouldn't we close the heap and index rels here? */ /* XXX shouldn't we close the heap and index rels here? */
} }
else else
{
index_build(heapRelation, indexRelation, indexInfo, NULL); index_build(heapRelation, indexRelation, indexInfo, NULL);
} }
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* *
@ -1081,12 +1080,12 @@ index_drop(Oid indexId)
heap_freetuple(tuple); heap_freetuple(tuple);
/* /*
* Update the pg_class tuple for the owning relation. We are presently * Update the pg_class tuple for the owning relation. We are
* too lazy to attempt to compute the new correct value of relhasindex * presently too lazy to attempt to compute the new correct value of
* (the next VACUUM will fix it if necessary). But we must send out a * relhasindex (the next VACUUM will fix it if necessary). But we
* shared-cache-inval notice on the owning relation to ensure other * must send out a shared-cache-inval notice on the owning relation to
* backends update their relcache lists of indexes. So, unconditionally * ensure other backends update their relcache lists of indexes. So,
* do setRelhasindex(true). * unconditionally do setRelhasindex(true).
*/ */
setRelhasindex(heapId, true); setRelhasindex(heapId, true);
@ -1326,8 +1325,8 @@ LockClassinfoForUpdate(Oid relid, HeapTuple rtup,
Relation relationRelation; Relation relationRelation;
/* /*
* NOTE: get and hold RowExclusiveLock on pg_class, because caller will * NOTE: get and hold RowExclusiveLock on pg_class, because caller
* probably modify the rel's pg_class tuple later on. * will probably modify the rel's pg_class tuple later on.
*/ */
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
classTuple = SearchSysCache(RELOID, PointerGetDatum(relid), classTuple = SearchSysCache(RELOID, PointerGetDatum(relid),
@ -1513,7 +1512,8 @@ setRelhasindex(Oid relid, bool hasindex)
void void
setNewRelfilenode(Relation relation) setNewRelfilenode(Relation relation)
{ {
Relation pg_class, idescs[Num_pg_class_indices]; Relation pg_class,
idescs[Num_pg_class_indices];
Oid newrelfilenode; Oid newrelfilenode;
bool in_place_update = false; bool in_place_update = false;
HeapTupleData lockTupleData; HeapTupleData lockTupleData;
@ -1577,6 +1577,7 @@ setNewRelfilenode(Relation relation)
/* Make sure the relfilenode change */ /* Make sure the relfilenode change */
CommandCounterIncrement(); CommandCounterIncrement();
} }
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
/* ---------------- /* ----------------
@ -1713,6 +1714,7 @@ UpdateStats(Oid relid, long reltuples)
*/ */
if (in_place_upd) if (in_place_upd)
{ {
/* /*
* At bootstrap time, we don't need to worry about concurrency or * At bootstrap time, we don't need to worry about concurrency or
* visibility of changes, so we cheat. Also cheat if REINDEX. * visibility of changes, so we cheat. Also cheat if REINDEX.
@ -1787,9 +1789,11 @@ DefaultBuild(Relation heapRelation,
long reltuples, long reltuples,
indtuples; indtuples;
Node *predicate = indexInfo->ii_Predicate; Node *predicate = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult insertResult; InsertIndexResult insertResult;
@ -1855,6 +1859,7 @@ DefaultBuild(Relation heapRelation,
reltuples++; reltuples++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -1906,9 +1911,7 @@ DefaultBuild(Relation heapRelation,
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (predicate != NULL || oldPred != NULL) if (predicate != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -2098,9 +2101,10 @@ reindex_index(Oid indexId, bool force, bool inplace)
if (inplace) if (inplace)
{ {
/* /*
* Release any buffers associated with this index. If they're dirty, * Release any buffers associated with this index. If they're
* 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);
@ -2164,18 +2168,24 @@ reindex_relation(Oid relid, bool force)
bool old, bool old,
reindexed; reindexed;
bool deactivate_needed, overwrite, upd_pg_class_inplace; bool deactivate_needed,
overwrite,
upd_pg_class_inplace;
#ifdef OLD_FILE_NAMING #ifdef OLD_FILE_NAMING
overwrite = upd_pg_class_inplace = deactivate_needed = true; overwrite = upd_pg_class_inplace = deactivate_needed = true;
#else #else
Relation rel; Relation rel;
overwrite = upd_pg_class_inplace = deactivate_needed = false; overwrite = upd_pg_class_inplace = deactivate_needed = false;
/* /*
* avoid heap_update() pg_class tuples while processing * avoid heap_update() pg_class tuples while processing reindex for
* reindex for pg_class. * pg_class.
*/ */
if (IsIgnoringSystemIndexes()) if (IsIgnoringSystemIndexes())
upd_pg_class_inplace = true; upd_pg_class_inplace = true;
/* /*
* ignore the indexes of the target system relation while processing * ignore the indexes of the target system relation while processing
* reindex. * reindex.
@ -2184,10 +2194,10 @@ reindex_relation(Oid relid, bool force)
if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname))) if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname)))
deactivate_needed = true; deactivate_needed = true;
#ifndef ENABLE_REINDEX_NAILED_RELATIONS #ifndef ENABLE_REINDEX_NAILED_RELATIONS
/* /*
* nailed relations are never updated. * nailed relations are never updated. We couldn't keep the
* We couldn't keep the consistency between the relation * consistency between the relation descriptors and pg_class tuples.
* descriptors and pg_class tuples.
*/ */
if (rel->rd_isnailed) if (rel->rd_isnailed)
{ {
@ -2200,9 +2210,10 @@ reindex_relation(Oid relid, bool force)
elog(ERROR, "the target relation %u is nailed", relid); elog(ERROR, "the target relation %u is nailed", relid);
} }
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ #endif /* ENABLE_REINDEX_NAILED_RELATIONS */
/* /*
* Shared system indexes must be overwritten because it's * Shared system indexes must be overwritten because it's impossible
* impossible to update pg_class tuples of all databases. * to update pg_class tuples of all databases.
*/ */
if (IsSharedSystemRelationName(NameStr(rel->rd_rel->relname))) if (IsSharedSystemRelationName(NameStr(rel->rd_rel->relname)))
{ {
@ -2252,24 +2263,27 @@ reindex_relation(Oid relid, bool force)
heap_endscan(scan); heap_endscan(scan);
heap_close(indexRelation, AccessShareLock); heap_close(indexRelation, AccessShareLock);
if (reindexed) if (reindexed)
/* /*
* Ok,we could use the reindexed indexes of the target * Ok,we could use the reindexed indexes of the target system
* system relation now. * relation now.
*/ */
{ {
if (deactivate_needed) if (deactivate_needed)
{ {
if (!overwrite && relid == RelOid_pg_class) if (!overwrite && relid == RelOid_pg_class)
{ {
/* /*
* For pg_class, relhasindex should be set * For pg_class, relhasindex should be set to true here in
* to true here in place. * place.
*/ */
setRelhasindex(relid, true); setRelhasindex(relid, true);
CommandCounterIncrement(); CommandCounterIncrement();
/* /*
* However the following setRelhasindex() * However the following setRelhasindex() is needed to
* is needed to keep consistency with WAL. * keep consistency with WAL.
*/ */
} }
setRelhasindex(relid, true); setRelhasindex(relid, true);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.76 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.77 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.37 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.38 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -79,8 +79,8 @@ AggregateCreate(char *aggName,
/* /*
* Handle the aggregate's base type (input data type). This can be * Handle the aggregate's base type (input data type). This can be
* specified as 'ANY' for a data-independent transition function, * specified as 'ANY' for a data-independent transition function, such
* such as COUNT(*). * as COUNT(*).
*/ */
basetype = GetSysCacheOid(TYPENAME, basetype = GetSysCacheOid(TYPENAME,
PointerGetDatum(aggbasetypeName), PointerGetDatum(aggbasetypeName),
@ -118,9 +118,7 @@ AggregateCreate(char *aggName,
nargs = 2; nargs = 2;
} }
else else
{
nargs = 1; nargs = 1;
}
tup = SearchSysCache(PROCNAME, tup = SearchSysCache(PROCNAME,
PointerGetDatum(aggtransfnName), PointerGetDatum(aggtransfnName),
Int32GetDatum(nargs), Int32GetDatum(nargs),
@ -134,11 +132,12 @@ AggregateCreate(char *aggName,
if (proc->prorettype != transtype) if (proc->prorettype != transtype)
elog(ERROR, "AggregateCreate: return type of '%s' is not '%s'", elog(ERROR, "AggregateCreate: return type of '%s' is not '%s'",
aggtransfnName, aggtranstypeName); aggtransfnName, aggtranstypeName);
/* /*
* If the transfn is strict and the initval is NULL, make sure * If the transfn is strict and the initval is NULL, make sure input
* input type and transtype are the same (or at least binary- * type and transtype are the same (or at least binary- compatible),
* compatible), so that it's OK to use the first input value * so that it's OK to use the first input value as the initial
* as the initial transValue. * transValue.
*/ */
if (proc->proisstrict && agginitval == NULL) if (proc->proisstrict && agginitval == NULL)
{ {
@ -168,6 +167,7 @@ AggregateCreate(char *aggName,
} }
else else
{ {
/* /*
* If no finalfn, aggregate result type is type of the state value * If no finalfn, aggregate result type is type of the state value
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.7 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.8 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.55 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.56 2001/03/22 03:59:20 momjian Exp $
* *
* NOTES * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.53 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.54 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -247,8 +247,8 @@ ProcedureCreate(char *procedureName,
* symbol. Also check for a valid function information record. * symbol. Also check for a valid function information record.
* *
* We used to perform these checks only when the function was first * We used to perform these checks only when the function was first
* called, but it seems friendlier to verify the library's validity * called, but it seems friendlier to verify the library's validity at
* at CREATE FUNCTION time. * CREATE FUNCTION time.
*/ */
if (languageObjectId == ClanguageId) if (languageObjectId == ClanguageId)
@ -355,7 +355,8 @@ checkretval(Oid rettype, List *queryTreeList)
tlist = parse->targetList; tlist = parse->targetList;
/* /*
* The last query must be a SELECT if and only if there is a return type. * The last query must be a SELECT if and only if there is a return
* type.
*/ */
if (rettype == InvalidOid) if (rettype == InvalidOid)
{ {
@ -375,8 +376,8 @@ checkretval(Oid rettype, List *queryTreeList)
tlistlen = ExecCleanTargetListLength(tlist); tlistlen = ExecCleanTargetListLength(tlist);
/* /*
* For base-type returns, the target list should have exactly one entry, * For base-type returns, the target list should have exactly one
* and its type should agree with what the user declared. * entry, and its type should agree with what the user declared.
*/ */
typerelid = typeidTypeRelid(rettype); typerelid = typeidTypeRelid(rettype);
if (typerelid == InvalidOid) if (typerelid == InvalidOid)
@ -397,8 +398,8 @@ checkretval(Oid rettype, List *queryTreeList)
* If the target list is of length 1, and the type of the varnode in * If the target list is of length 1, and the type of the varnode in
* the target list is the same as the declared return type, this is * the target list is the same as the declared return type, this is
* okay. This can happen, for example, where the body of the function * okay. This can happen, for example, where the body of the function
* is 'SELECT (x = func2())', where func2 has the same return type * is 'SELECT (x = func2())', where func2 has the same return type as
* as the function that's calling it. * the function that's calling it.
*/ */
if (tlistlen == 1) if (tlistlen == 1)
{ {
@ -408,10 +409,10 @@ checkretval(Oid rettype, List *queryTreeList)
} }
/* /*
* By here, the procedure returns a tuple or set of tuples. This part of * By here, the procedure returns a tuple or set of tuples. This part
* the typechecking is a hack. We look up the relation that is the * of the typechecking is a hack. We look up the relation that is the
* declared return type, and be sure that attributes 1 .. n in the target * declared return type, and be sure that attributes 1 .. n in the
* list match the declared types. * target list match the declared types.
*/ */
reln = heap_open(typerelid, AccessShareLock); reln = heap_open(typerelid, AccessShareLock);
relid = reln->rd_id; relid = reln->rd_id;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.60 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.14 2001/02/16 03:16:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.15 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -86,9 +86,10 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
CommitTransactionCommand(); CommitTransactionCommand();
return; return;
} }
/* /*
* We can VACUUM ANALYZE any table except pg_statistic. * We can VACUUM ANALYZE any table except pg_statistic. see
* see update_relstats * update_relstats
*/ */
if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname), if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname),
StatisticRelationName) == 0) StatisticRelationName) == 0)
@ -104,9 +105,11 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel), if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
RELNAME)) RELNAME))
{ {
/* we already did an elog during vacuum
elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it", /*
RelationGetRelationName(onerel)); * we already did an elog during vacuum elog(NOTICE, "Skipping
* \"%s\" --- only table owner can VACUUM it",
* RelationGetRelationName(onerel));
*/ */
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
CommitTransactionCommand(); CommitTransactionCommand();
@ -295,8 +298,9 @@ attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple
stats->nonnull_cnt++; stats->nonnull_cnt++;
/* /*
* If the value is toasted, detoast it to avoid repeated detoastings * If the value is toasted, detoast it to avoid repeated
* and resultant memory leakage inside the comparison routines. * detoastings and resultant memory leakage inside the comparison
* routines.
*/ */
if (!stats->attr->attbyval && stats->attr->attlen == -1) if (!stats->attr->attbyval && stats->attr->attlen == -1)
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue)); value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
@ -489,22 +493,21 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
{ {
/* /*
* empty relation, so put a dummy value in * empty relation, so put a dummy value in attdispersion
* attdispersion
*/ */
selratio = 0; selratio = 0;
} }
else if (stats->null_cnt <= 1 && stats->best_cnt == 1) else if (stats->null_cnt <= 1 && stats->best_cnt == 1)
{ {
/* /*
* looks like we have a unique-key attribute --- flag * looks like we have a unique-key attribute --- flag this
* this with special -1.0 flag value. * with special -1.0 flag value.
* *
* The correct dispersion is 1.0/numberOfRows, but since * The correct dispersion is 1.0/numberOfRows, but since the
* the relation row count can get updated without * relation row count can get updated without recomputing
* recomputing dispersion, we want to store a * dispersion, we want to store a "symbolic" value and
* "symbolic" value and figure 1.0/numberOfRows on the * figure 1.0/numberOfRows on the fly.
* fly.
*/ */
selratio = -1; selratio = -1;
} }
@ -515,8 +518,7 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
{ {
/* /*
* exact result when there are just 1 or 2 * exact result when there are just 1 or 2 values...
* values...
*/ */
double min_cnt_d = stats->min_cnt, double min_cnt_d = stats->min_cnt,
max_cnt_d = stats->max_cnt, max_cnt_d = stats->max_cnt,
@ -552,12 +554,12 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
/* /*
* Create pg_statistic tuples for the relation, if we have * Create pg_statistic tuples for the relation, if we have
* gathered the right data. del_stats() previously * gathered the right data. del_stats() previously deleted
* deleted all the pg_statistic tuples for the rel, so we * all the pg_statistic tuples for the rel, so we just have to
* just have to insert new ones here. * insert new ones here.
* *
* Note analyze_rel() has seen to it that we won't come here * Note analyze_rel() has seen to it that we won't come here when
* when vacuuming pg_statistic itself. * vacuuming pg_statistic itself.
*/ */
if (VacAttrStatsLtGtValid(stats) && stats->initialized) if (VacAttrStatsLtGtValid(stats) && stats->initialized)
{ {
@ -682,6 +684,3 @@ del_stats(Oid relid, int attcnt, int *attnums)
*/ */
heap_close(pgstatistic, NoLock); heap_close(pgstatistic, NoLock);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.76 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.77 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -161,6 +161,7 @@ Async_Notify(char *relname)
/* no point in making duplicate entries in the list ... */ /* no point in making duplicate entries in the list ... */
if (!AsyncExistsPendingNotify(relname)) if (!AsyncExistsPendingNotify(relname))
{ {
/* /*
* We allocate list memory from the global malloc pool to ensure * We allocate list memory from the global malloc pool to ensure
* that it will live until we want to use it. This is probably * that it will live until we want to use it. This is probably
@ -349,9 +350,7 @@ Async_UnlistenAll()
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key); sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0))) while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
{
simple_heap_delete(lRel, &lTuple->t_self); simple_heap_delete(lRel, &lTuple->t_self);
}
heap_endscan(sRel); heap_endscan(sRel);
heap_close(lRel, AccessExclusiveLock); heap_close(lRel, AccessExclusiveLock);
@ -499,6 +498,7 @@ AtCommit_Notify()
*/ */
if (kill(listenerPID, SIGUSR2) < 0) if (kill(listenerPID, SIGUSR2) < 0)
{ {
/* /*
* Get rid of pg_listener entry if it refers to a PID * Get rid of pg_listener entry if it refers to a PID
* that no longer exists. Presumably, that backend * that no longer exists. Presumably, that backend

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.64 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.65 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -75,8 +75,8 @@ cluster(char *oldrelname, char *oldindexname)
StrNCpy(saveoldindexname, oldindexname, NAMEDATALEN); StrNCpy(saveoldindexname, oldindexname, NAMEDATALEN);
/* /*
* We grab exclusive access to the target rel and index for the duration * We grab exclusive access to the target rel and index for the
* of the transaction. * duration of the transaction.
*/ */
OldHeap = heap_openr(saveoldrelname, AccessExclusiveLock); OldHeap = heap_openr(saveoldrelname, AccessExclusiveLock);
OIDOldHeap = RelationGetRelid(OldHeap); OIDOldHeap = RelationGetRelid(OldHeap);
@ -154,8 +154,8 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
OldHeapDesc = RelationGetDescr(OldHeap); OldHeapDesc = RelationGetDescr(OldHeap);
/* /*
* Need to make a copy of the tuple descriptor, * Need to make a copy of the tuple descriptor, since
* since heap_create_with_catalog modifies it. * heap_create_with_catalog modifies it.
*/ */
tupdesc = CreateTupleDescCopyConstr(OldHeapDesc); tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
@ -164,16 +164,15 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
allowSystemTableMods); allowSystemTableMods);
/* /*
* Advance command counter so that the newly-created * Advance command counter so that the newly-created relation's
* relation's catalog tuples will be visible to heap_open. * catalog tuples will be visible to heap_open.
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
/* /*
* If necessary, create a TOAST table for the new relation. * If necessary, create a TOAST table for the new relation. Note that
* Note that AlterTableCreateToastTable ends with * AlterTableCreateToastTable ends with CommandCounterIncrement(), so
* CommandCounterIncrement(), so that the TOAST table will * that the TOAST table will be visible for insertion.
* be visible for insertion.
*/ */
AlterTableCreateToastTable(NewName, true); AlterTableCreateToastTable(NewName, true);
@ -198,12 +197,12 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName)
/* /*
* Create a new index like the old one. To do this I get the info * Create a new index like the old one. To do this I get the info
* from pg_index, and add a new index with a temporary name (that * from pg_index, and add a new index with a temporary name (that will
* will be changed later). * be changed later).
* *
* NOTE: index_create will cause the new index to be a temp relation * NOTE: index_create will cause the new index to be a temp relation if
* if its parent table is, so we don't need to do anything special * its parent table is, so we don't need to do anything special for
* for the temp-table case here. * the temp-table case here.
*/ */
Old_pg_index_Tuple = SearchSysCache(INDEXRELID, Old_pg_index_Tuple = SearchSysCache(INDEXRELID,
ObjectIdGetDatum(OIDOldIndex), ObjectIdGetDatum(OIDOldIndex),
@ -266,13 +265,15 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
LocalHeapTuple.t_datamcxt = NULL; LocalHeapTuple.t_datamcxt = NULL;
LocalHeapTuple.t_data = NULL; LocalHeapTuple.t_data = NULL;
heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer); heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer);
if (LocalHeapTuple.t_data != NULL) { if (LocalHeapTuple.t_data != NULL)
{
/* /*
* We must copy the tuple because heap_insert() will overwrite * We must copy the tuple because heap_insert() will overwrite
* the commit-status fields of the tuple it's handed, and the * the commit-status fields of the tuple it's handed, and the
* retrieved tuple will actually be in a disk buffer! Thus, * retrieved tuple will actually be in a disk buffer! Thus,
* the source relation would get trashed, which is bad news * the source relation would get trashed, which is bad news if
* if we abort later on. (This was a bug in releases thru 7.0) * we abort later on. (This was a bug in releases thru 7.0)
*/ */
HeapTuple copiedTuple = heap_copytuple(&LocalHeapTuple); HeapTuple copiedTuple = heap_copytuple(&LocalHeapTuple);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.122 2001/02/27 22:07:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.123 2001/03/22 03:59:21 momjian Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
@ -502,8 +502,8 @@ AlterTableAddColumn(const char *relationName,
heap_close(rel, NoLock); heap_close(rel, NoLock);
/* /*
* Automatically create the secondary relation for TOAST * Automatically create the secondary relation for TOAST if it
* if it formerly had no such but now has toastable attributes. * formerly had no such but now has toastable attributes.
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
AlterTableCreateToastTable(relationName, true); AlterTableCreateToastTable(relationName, true);
@ -1147,15 +1147,17 @@ AlterTableAddConstraint(char *relationName,
elog(ERROR, "ALTER TABLE: cannot add constraint to a view"); elog(ERROR, "ALTER TABLE: cannot add constraint to a view");
/* /*
* Scan all of the rows, looking for a false match * Scan all of the rows, looking for a false
* match
*/ */
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL); scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
AssertState(scan != NULL); AssertState(scan != NULL);
/* /*
* We need to make a parse state and range table to allow * We need to make a parse state and range
* us to transformExpr and fix_opids to get a version of * table to allow us to transformExpr and
* the expression we can pass to ExecQual * fix_opids to get a version of the
* expression we can pass to ExecQual
*/ */
pstate = make_parsestate(NULL); pstate = make_parsestate(NULL);
rte = addRangeTableEntry(pstate, relationName, NULL, rte = addRangeTableEntry(pstate, relationName, NULL,
@ -1174,14 +1176,16 @@ AlterTableAddConstraint(char *relationName,
name); name);
/* /*
* Make sure no outside relations are referred to. * Make sure no outside relations are referred
* to.
*/ */
if (length(pstate->p_rtable) != 1) if (length(pstate->p_rtable) != 1)
elog(ERROR, "Only relation '%s' can be referenced in CHECK", elog(ERROR, "Only relation '%s' can be referenced in CHECK",
relationName); relationName);
/* /*
* Might as well try to reduce any constant expressions. * Might as well try to reduce any constant
* expressions.
*/ */
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);
@ -1197,8 +1201,8 @@ AlterTableAddConstraint(char *relationName,
econtext = MakeExprContext(slot, CurrentMemoryContext); econtext = MakeExprContext(slot, CurrentMemoryContext);
/* /*
* Scan through the rows now, checking the expression * Scan through the rows now, checking the
* at each row. * expression at each row.
*/ */
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{ {
@ -1221,10 +1225,12 @@ AlterTableAddConstraint(char *relationName,
heap_close(rel, NoLock); heap_close(rel, NoLock);
elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s", name); elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s", name);
} }
/* /*
* Call AddRelationRawConstraints to do the real adding -- * Call AddRelationRawConstraints to do the
* It duplicates some of the above, but does not check the * real adding -- It duplicates some of the
* validity of the constraint against tuples already in * above, but does not check the validity of
* the constraint against tuples already in
* the table. * the table.
*/ */
AddRelationRawConstraints(rel, NIL, constlist); AddRelationRawConstraints(rel, NIL, constlist);
@ -1241,7 +1247,8 @@ AlterTableAddConstraint(char *relationName,
case T_FkConstraint: case T_FkConstraint:
{ {
FkConstraint *fkconstraint = (FkConstraint *) newConstraint; FkConstraint *fkconstraint = (FkConstraint *) newConstraint;
Relation rel, pkrel; Relation rel,
pkrel;
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
Trigger trig; Trigger trig;
@ -1279,7 +1286,10 @@ AlterTableAddConstraint(char *relationName,
elog(ERROR, "referencing table \"%s\" not a relation", elog(ERROR, "referencing table \"%s\" not a relation",
relationName); relationName);
/* First we check for limited correctness of the constraint */ /*
* First we check for limited correctness of the
* constraint
*/
rel_attrs = pkrel->rd_att->attrs; rel_attrs = pkrel->rd_att->attrs;
indexoidlist = RelationGetIndexList(pkrel); indexoidlist = RelationGetIndexList(pkrel);
@ -1302,23 +1312,29 @@ AlterTableAddConstraint(char *relationName,
{ {
List *attrl; List *attrl;
/* Make sure this index has the same number of keys -- It obviously /*
* won't match otherwise. */ * Make sure this index has the same number of
* keys -- It obviously won't match otherwise.
*/
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++); for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
if (i != length(fkconstraint->pk_attrs)) if (i != length(fkconstraint->pk_attrs))
found = false; found = false;
else { else
{
/* go through the fkconstraint->pk_attrs list */ /* go through the fkconstraint->pk_attrs list */
foreach(attrl, fkconstraint->pk_attrs) foreach(attrl, fkconstraint->pk_attrs)
{ {
Ident *attr = lfirst(attrl); Ident *attr = lfirst(attrl);
found = false; found = false;
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
{ {
int pkattno = indexStruct->indkey[i]; int pkattno = indexStruct->indkey[i];
if (pkattno > 0) if (pkattno > 0)
{ {
char *name = NameStr(rel_attrs[pkattno - 1]->attname); char *name = NameStr(rel_attrs[pkattno - 1]->attname);
if (strcmp(name, attr->name) == 0) if (strcmp(name, attr->name) == 0)
{ {
found = true; found = true;
@ -1344,18 +1360,24 @@ AlterTableAddConstraint(char *relationName,
heap_close(pkrel, NoLock); heap_close(pkrel, NoLock);
rel_attrs = rel->rd_att->attrs; rel_attrs = rel->rd_att->attrs;
if (fkconstraint->fk_attrs!=NIL) { if (fkconstraint->fk_attrs != NIL)
{
List *fkattrs; List *fkattrs;
Ident *fkattr; Ident *fkattr;
found = false; found = false;
foreach(fkattrs, fkconstraint->fk_attrs) { foreach(fkattrs, fkconstraint->fk_attrs)
{
int count; int count;
found = false; found = false;
fkattr = lfirst(fkattrs); fkattr = lfirst(fkattrs);
for (count = 0; count < rel->rd_att->natts; count++) { for (count = 0; count < rel->rd_att->natts; count++)
{
char *name = NameStr(rel->rd_att->attrs[count]->attname); char *name = NameStr(rel->rd_att->attrs[count]->attname);
if (strcmp(name, fkattr->name)==0) {
if (strcmp(name, fkattr->name) == 0)
{
found = true; found = true;
break; break;
} }
@ -1652,10 +1674,11 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
"chunk_data", "chunk_data",
BYTEAOID, BYTEAOID,
-1, 0, false); -1, 0, false);
/* /*
* Ensure that the toast table doesn't itself get toasted, * Ensure that the toast table doesn't itself get toasted, or we'll be
* or we'll be toast :-(. This is essential for chunk_data because * toast :-(. This is essential for chunk_data because type bytea is
* type bytea is toastable; hit the other two just to be sure. * toastable; hit the other two just to be sure.
*/ */
tupdesc->attrs[0]->attstorage = 'p'; tupdesc->attrs[0]->attstorage = 'p';
tupdesc->attrs[1]->attstorage = 'p'; tupdesc->attrs[1]->attstorage = 'p';

View File

@ -7,7 +7,7 @@
* Copyright (c) 1999, PostgreSQL Global Development Group * Copyright (c) 1999, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.26 2001/01/23 04:32:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.27 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.134 2001/03/14 21:47:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.135 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -76,6 +76,7 @@ static StringInfoData attribute_buf;
#ifdef MULTIBYTE #ifdef MULTIBYTE
static int client_encoding; static int client_encoding;
static int server_encoding; static int server_encoding;
#endif #endif
@ -285,6 +286,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
elog(ERROR, "You must have Postgres superuser privilege to do a COPY " elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or " "directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone."); "from stdin. Psql's \\copy command also works for anyone.");
/* /*
* This restriction is unfortunate, but necessary until the frontend * This restriction is unfortunate, but necessary until the frontend
* COPY protocol is redesigned to be binary-safe... * COPY protocol is redesigned to be binary-safe...
@ -344,8 +346,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
mode_t oumask; /* Pre-existing umask value */ mode_t oumask; /* Pre-existing umask value */
/* /*
* Prevent write to relative path ... too easy to shoot oneself * Prevent write to relative path ... too easy to shoot
* in the foot by overwriting a database file ... * oneself in the foot by overwriting a database file ...
*/ */
if (filename[0] != '/') if (filename[0] != '/')
elog(ERROR, "Relative path not allowed for server side" elog(ERROR, "Relative path not allowed for server side"
@ -408,7 +410,10 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
attr_count = rel->rd_att->natts; attr_count = rel->rd_att->natts;
attr = rel->rd_att->attrs; attr = rel->rd_att->attrs;
/* For binary copy we really only need isvarlena, but compute it all... */ /*
* For binary copy we really only need isvarlena, but compute it
* all...
*/
out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo)); out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
elements = (Oid *) palloc(attr_count * sizeof(Oid)); elements = (Oid *) palloc(attr_count * sizeof(Oid));
isvarlena = (bool *) palloc(attr_count * sizeof(bool)); isvarlena = (bool *) palloc(attr_count * sizeof(bool));
@ -507,10 +512,12 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
} }
else else
{ {
/* /*
* If we have a toasted datum, forcibly detoast it to avoid * If we have a toasted datum, forcibly detoast it to
* memory leakage inside the type's output routine (or * avoid memory leakage inside the type's output routine
* for binary case, becase we must output untoasted value). * (or for binary case, becase we must output untoasted
* value).
*/ */
if (isvarlena[i]) if (isvarlena[i])
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue)); value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
@ -552,8 +559,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
Datum datumBuf; Datum datumBuf;
/* /*
* We need this horsing around because we don't know * We need this horsing around because we don't
* how shorter data values are aligned within a Datum. * know how shorter data values are aligned within
* a Datum.
*/ */
store_att_byval(&datumBuf, value, fld_size); store_att_byval(&datumBuf, value, fld_size);
CopySendData(&datumBuf, CopySendData(&datumBuf,
@ -622,8 +630,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
/* /*
* We need a ResultRelInfo so we can use the regular executor's * We need a ResultRelInfo so we can use the regular executor's
* index-entry-making machinery. (There used to be a huge amount * index-entry-making machinery. (There used to be a huge amount of
* of code here that basically duplicated execUtils.c ...) * code here that basically duplicated execUtils.c ...)
*/ */
resultRelInfo = makeNode(ResultRelInfo); resultRelInfo = makeNode(ResultRelInfo);
resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
@ -833,8 +841,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
Datum datumBuf; Datum datumBuf;
/* /*
* We need this horsing around because we don't know * We need this horsing around because we don't
* how shorter data values are aligned within a Datum. * know how shorter data values are aligned within
* a Datum.
*/ */
Assert(fld_size > 0 && fld_size <= sizeof(Datum)); Assert(fld_size > 0 && fld_size <= sizeof(Datum));
CopyGetData(&datumBuf, fld_size, fp); CopyGetData(&datumBuf, fld_size, fp);
@ -1163,6 +1172,7 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
char *string_start; char *string_start;
int mblen; int mblen;
int i; int i;
#endif #endif
#ifdef MULTIBYTE #ifdef MULTIBYTE

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.72 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.73 2001/03/22 03:59:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -152,8 +152,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
/* /*
* Open the new relation and acquire exclusive lock on it. This isn't * Open the new relation and acquire exclusive lock on it. This isn't
* really necessary for locking out other backends (since they can't * really necessary for locking out other backends (since they can't
* see the new rel anyway until we commit), but it keeps the lock manager * see the new rel anyway until we commit), but it keeps the lock
* from complaining about deadlock risks. * manager from complaining about deadlock risks.
*/ */
rel = heap_openr(relname, AccessExclusiveLock); rel = heap_openr(relname, AccessExclusiveLock);
@ -255,11 +255,11 @@ change_varattnos_walker(Node *node, const AttrNumber *newattno)
if (var->varlevelsup == 0 && var->varno == 1) if (var->varlevelsup == 0 && var->varno == 1)
{ {
/* /*
* ??? the following may be a problem when the * ??? the following may be a problem when the node is
* node is multiply referenced though * multiply referenced though stringToNode() doesn't create
* stringToNode() doesn't create such a node * such a node currently.
* currently.
*/ */
Assert(newattno[var->varattno - 1] > 0); Assert(newattno[var->varattno - 1] > 0);
var->varattno = newattno[var->varattno - 1]; var->varattno = newattno[var->varattno - 1];
@ -373,9 +373,12 @@ MergeAttributes(List *schema, List *supers, bool istemp,
AttrNumber attrno; AttrNumber attrno;
TupleDesc tupleDesc; TupleDesc tupleDesc;
TupleConstr *constr; TupleConstr *constr;
AttrNumber *newattno, *partialAttidx; AttrNumber *newattno,
*partialAttidx;
Node *expr; Node *expr;
int i, attidx, attno_exist; int i,
attidx,
attno_exist;
relation = heap_openr(name, AccessShareLock); relation = heap_openr(name, AccessShareLock);
@ -385,7 +388,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
if (!istemp && is_temp_rel_name(name)) if (!istemp && is_temp_rel_name(name))
elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name); elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name);
/* We should have an UNDER permission flag for this, but for now, /*
* We should have an UNDER permission flag for this, but for now,
* demand that creator of a child table own the parent. * demand that creator of a child table own the parent.
*/ */
if (!pg_ownercheck(GetUserId(), name, RELNAME)) if (!pg_ownercheck(GetUserId(), name, RELNAME))
@ -398,9 +402,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber)); newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
for (i = 0; i < tupleDesc->natts; i++) for (i = 0; i < tupleDesc->natts; i++)
newattno[i] = 0; newattno[i] = 0;
/* /*
* searching and storing order are different. * searching and storing order are different. another table is
* another table is needed. * needed.
*/ */
partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber)); partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
for (i = 0; i < tupleDesc->natts; i++) for (i = 0; i < tupleDesc->natts; i++)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.73 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.74 2001/03/22 03:59:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -84,10 +84,10 @@ createdb(const char *dbname, const char *dbpath,
/* /*
* Check for db name conflict. There is a race condition here, since * Check for db name conflict. There is a race condition here, since
* another backend could create the same DB name before we commit. * another backend could create the same DB name before we commit.
* However, holding an exclusive lock on pg_database for the whole time * However, holding an exclusive lock on pg_database for the whole
* we are copying the source database doesn't seem like a good idea, * time we are copying the source database doesn't seem like a good
* so accept possibility of race to create. We will check again after * idea, so accept possibility of race to create. We will check again
* we grab the exclusive lock. * after we grab the exclusive lock.
*/ */
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL)) if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL))
elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname); elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname);
@ -102,9 +102,10 @@ createdb(const char *dbname, const char *dbpath,
&src_istemplate, &src_lastsysoid, src_dbpath)) &src_istemplate, &src_lastsysoid, src_dbpath))
elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist", elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist",
dbtemplate); dbtemplate);
/* /*
* Permission check: to copy a DB that's not marked datistemplate, * Permission check: to copy a DB that's not marked datistemplate, you
* you must be superuser or the owner thereof. * must be superuser or the owner thereof.
*/ */
if (!src_istemplate) if (!src_istemplate)
{ {
@ -112,6 +113,7 @@ createdb(const char *dbname, const char *dbpath,
elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied", elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied",
dbtemplate); dbtemplate);
} }
/* /*
* Determine physical path of source database * Determine physical path of source database
*/ */
@ -134,13 +136,15 @@ createdb(const char *dbname, const char *dbpath,
encoding = src_encoding; encoding = src_encoding;
/* /*
* Preassign OID for pg_database tuple, so that we can compute db path. * Preassign OID for pg_database tuple, so that we can compute db
* path.
*/ */
dboid = newoid(); dboid = newoid();
/* /*
* Compute nominal location (where we will try to access the database), * Compute nominal location (where we will try to access the
* and resolve alternate physical location if one is specified. * database), and resolve alternate physical location if one is
* specified.
*/ */
nominal_loc = GetDatabasePath(dboid); nominal_loc = GetDatabasePath(dboid);
alt_loc = resolve_alt_dbpath(dbpath, dboid); alt_loc = resolve_alt_dbpath(dbpath, dboid);
@ -155,8 +159,8 @@ createdb(const char *dbname, const char *dbpath,
/* /*
* Force dirty buffers out to disk, to ensure source database is * Force dirty buffers out to disk, to ensure source database is
* up-to-date for the copy. (We really only need to flush buffers * up-to-date for the copy. (We really only need to flush buffers for
* for the source database...) * the source database...)
*/ */
BufferSync(); BufferSync();
@ -231,7 +235,8 @@ createdb(const char *dbname, const char *dbpath,
tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls); tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
tuple->t_data->t_oid = dboid; /* override heap_insert's OID selection */ tuple->t_data->t_oid = dboid; /* override heap_insert's OID
* selection */
heap_insert(pg_database_rel, tuple); heap_insert(pg_database_rel, tuple);
@ -311,8 +316,8 @@ dropdb(const char *dbname)
elog(ERROR, "DROP DATABASE: permission denied"); elog(ERROR, "DROP DATABASE: permission denied");
/* /*
* Disallow dropping a DB that is marked istemplate. This is just * Disallow dropping a DB that is marked istemplate. This is just to
* to prevent people from accidentally dropping template0 or template1; * prevent people from accidentally dropping template0 or template1;
* they can do so if they're really determined ... * they can do so if they're really determined ...
*/ */
if (db_istemplate) if (db_istemplate)
@ -338,6 +343,7 @@ dropdb(const char *dbname)
tup = heap_getnext(pgdbscan, 0); tup = heap_getnext(pgdbscan, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
/* /*
* This error should never come up since the existence of the * This error should never come up since the existence of the
* database is checked earlier * database is checked earlier
@ -503,6 +509,7 @@ resolve_alt_dbpath(const char * dbpath, Oid dboid)
{ {
/* must be environment variable */ /* must be environment variable */
char *var = getenv(dbpath); char *var = getenv(dbpath);
if (!var) if (!var)
elog(ERROR, "Postmaster environment variable '%s' not set", dbpath); elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
if (var[0] != '/') if (var[0] != '/')

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.53 2001/03/22 03:59:22 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
@ -217,21 +217,26 @@ void
CreateFunction(ProcedureStmt *stmt, CommandDest dest) CreateFunction(ProcedureStmt *stmt, CommandDest dest)
{ {
char *probin_str; char *probin_str;
/* pathname of executable file that executes this function, if any */ /* pathname of executable file that executes this function, if any */
char *prosrc_str; char *prosrc_str;
/* SQL that executes this function, if any */ /* SQL that executes this function, if any */
char *prorettype; char *prorettype;
/* Type of return value (or member of set of values) from function */ /* Type of return value (or member of set of values) from function */
char languageName[NAMEDATALEN]; char languageName[NAMEDATALEN];
/* /*
* name of language of function, with case adjusted: "C", * name of language of function, with case adjusted: "C", "internal",
* "internal", "sql", etc. * "sql", etc.
*/ */
bool returnsSet; bool returnsSet;
/* The function returns a set of values, as opposed to a singleton. */ /* The function returns a set of values, as opposed to a singleton. */
/* /*
@ -478,8 +483,8 @@ DefineAggregate(char *aggName, List *parameters)
DefElem *defel = (DefElem *) lfirst(pl); DefElem *defel = (DefElem *) lfirst(pl);
/* /*
* sfunc1, stype1, and initcond1 are accepted as obsolete spellings * sfunc1, stype1, and initcond1 are accepted as obsolete
* for sfunc, stype, initcond. * spellings for sfunc, stype, initcond.
*/ */
if (strcasecmp(defel->defname, "sfunc") == 0) if (strcasecmp(defel->defname, "sfunc") == 0)
transfuncName = defGetString(defel); transfuncName = defGetString(defel);
@ -547,9 +552,9 @@ DefineType(char *typeName, List *parameters)
char storage = 'p'; /* default storage in TOAST */ char storage = 'p'; /* default storage in TOAST */
/* /*
* Type names must be one character shorter than other names, * Type names must be one character shorter than other names, allowing
* allowing room to create the corresponding array type name with * room to create the corresponding array type name with prepended
* prepended "_". * "_".
*/ */
if (strlen(typeName) > (NAMEDATALEN - 2)) if (strlen(typeName) > (NAMEDATALEN - 2))
{ {
@ -699,7 +704,9 @@ defGetString(DefElem *def)
return str; return str;
} }
case T_Float: case T_Float:
/* T_Float values are kept in string form, so this type cheat
/*
* T_Float values are kept in string form, so this type cheat
* works (and doesn't risk losing precision) * works (and doesn't risk losing precision)
*/ */
return strVal(def->arg); return strVal(def->arg);

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.64 2001/01/27 01:41:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.65 2001/03/22 03:59:22 momjian Exp $
* *
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.45 2001/02/23 09:26:14 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.46 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -118,9 +118,9 @@ DefineIndex(char *heapRelationName,
accessMethodName); accessMethodName);
/* /*
* XXX Hardwired hacks to check for limitations on supported index types. * XXX Hardwired hacks to check for limitations on supported index
* We really ought to be learning this info from entries in the pg_am * types. We really ought to be learning this info from entries in the
* table, instead of having it wired in here! * pg_am table, instead of having it wired in here!
*/ */
if (unique && accessMethodId != BTREE_AM_OID) if (unique && accessMethodId != BTREE_AM_OID)
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method"); elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
@ -161,7 +161,8 @@ DefineIndex(char *heapRelationName,
elog(ERROR, "Existing indexes are inactive. REINDEX first"); elog(ERROR, "Existing indexes are inactive. REINDEX first");
/* /*
* Prepare arguments for index_create, primarily an IndexInfo structure * Prepare arguments for index_create, primarily an IndexInfo
* structure
*/ */
indexInfo = makeNode(IndexInfo); indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = (Node *) cnfPred; indexInfo->ii_Predicate = (Node *) cnfPred;
@ -515,8 +516,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
attribute->class); attribute->class);
/* /*
* Assume the opclass is supported by this index access method * Assume the opclass is supported by this index access method if we
* if we can find at least one relevant entry in pg_amop. * can find at least one relevant entry in pg_amop.
*/ */
ScanKeyEntryInitialize(&entry[0], 0, ScanKeyEntryInitialize(&entry[0], 0,
Anum_pg_amop_amopid, Anum_pg_amop_amopid,
@ -540,17 +541,18 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
heap_close(relation, AccessShareLock); heap_close(relation, AccessShareLock);
/* /*
* Make sure the operators associated with this opclass actually accept * Make sure the operators associated with this opclass actually
* the column data type. This prevents possible coredumps caused by * accept the column data type. This prevents possible coredumps
* user errors like applying text_ops to an int4 column. We will accept * caused by user errors like applying text_ops to an int4 column. We
* an opclass as OK if the operator's input datatype is binary-compatible * will accept an opclass as OK if the operator's input datatype is
* with the actual column datatype. Note we assume that all the operators * binary-compatible with the actual column datatype. Note we assume
* associated with an opclass accept the same datatypes, so checking the * that all the operators associated with an opclass accept the same
* first one we happened to find in the table is sufficient. * datatypes, so checking the first one we happened to find in the
* table is sufficient.
* *
* If the opclass was the default for the datatype, assume we can skip * If the opclass was the default for the datatype, assume we can skip
* this check --- that saves a few cycles in the most common case. * this check --- that saves a few cycles in the most common case. If
* If pg_opclass is wrong then we're probably screwed anyway... * pg_opclass is wrong then we're probably screwed anyway...
*/ */
if (doTypeCheck) if (doTypeCheck)
{ {
@ -752,18 +754,18 @@ ReindexDatabase(const char *dbname, bool force, bool all)
elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database."); elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
/* /*
* We cannot run inside a user transaction block; if we were * We cannot run inside a user transaction block; if we were inside a
* inside a transaction, then our commit- and * transaction, then our commit- and start-transaction-command calls
* start-transaction-command calls would not have the intended effect! * would not have the intended effect!
*/ */
if (IsTransactionBlock()) if (IsTransactionBlock())
elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block"); elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block");
/* /*
* Create a memory context that will survive forced transaction commits * Create a memory context that will survive forced transaction
* we do below. Since it is a child of QueryContext, it will go away * commits we do below. Since it is a child of QueryContext, it will
* eventually even if we suffer an error; there's no need for special * go away eventually even if we suffer an error; there's no need for
* abort cleanup logic. * special abort cleanup logic.
*/ */
private_context = AllocSetContextCreate(QueryContext, private_context = AllocSetContextCreate(QueryContext,
"ReindexDatabase", "ReindexDatabase",

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.59 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.60 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.55 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.56 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -189,15 +189,15 @@ renamerel(const char *oldrelname, const char *newrelname)
newrelname); newrelname);
/* /*
* Check for renaming a temp table, which only requires altering * Check for renaming a temp table, which only requires altering the
* the temp-table mapping, not the underlying table. * temp-table mapping, not the underlying table.
*/ */
if (rename_temp_relation(oldrelname, newrelname)) if (rename_temp_relation(oldrelname, newrelname))
return; /* all done... */ return; /* all done... */
/* /*
* Instead of using heap_openr(), do it the hard way, so that we * Instead of using heap_openr(), do it the hard way, so that we can
* can rename indexes as well as regular relations. * rename indexes as well as regular relations.
*/ */
targetrelation = RelationNameGetRelation(oldrelname); targetrelation = RelationNameGetRelation(oldrelname);
@ -219,8 +219,9 @@ renamerel(const char *oldrelname, const char *newrelname)
heap_close(targetrelation, NoLock); heap_close(targetrelation, NoLock);
/* /*
* Flush the relcache entry (easier than trying to change it at exactly * Flush the relcache entry (easier than trying to change it at
* the right instant). It'll get rebuilt on next access to relation. * exactly the right instant). It'll get rebuilt on next access to
* relation.
* *
* XXX What if relation is myxactonly? * XXX What if relation is myxactonly?
* *
@ -244,8 +245,8 @@ renamerel(const char *oldrelname, const char *newrelname)
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname); elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
/* /*
* Update pg_class tuple with new relname. (Scribbling on reltup * Update pg_class tuple with new relname. (Scribbling on reltup is
* is OK because it's a copy...) * OK because it's a copy...)
*/ */
StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname), StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
newrelname, NAMEDATALEN); newrelname, NAMEDATALEN);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.51 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.52 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -409,7 +409,8 @@ do_setval(char *seqname, int32 next, bool iscalled)
/* save info in local cache */ /* save info in local cache */
elm->last = next; /* last returned number */ elm->last = next; /* last returned number */
elm->cached = next; /* last cached number (forget cached values) */ elm->cached = next; /* last cached number (forget cached
* values) */
START_CRIT_SECTION(); START_CRIT_SECTION();
{ {
@ -511,6 +512,7 @@ get_seq_name(text *seqin)
else else
{ {
seqname = rawname; seqname = rawname;
/* /*
* It's important that this match the identifier downcasing code * It's important that this match the identifier downcasing code
* used by backend/parser/scan.l. * used by backend/parser/scan.l.
@ -752,7 +754,8 @@ get_param(DefElem *def)
return -1; return -1;
} }
void seq_redo(XLogRecPtr lsn, XLogRecord *record) void
seq_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
Relation reln; Relation reln;
@ -795,11 +798,13 @@ void seq_redo(XLogRecPtr lsn, XLogRecord *record)
return; return;
} }
void seq_undo(XLogRecPtr lsn, XLogRecord *record) void
seq_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
} }
void seq_desc(char *buf, uint8 xl_info, char* rec) void
seq_desc(char *buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
xl_seq_rec *xlrec = (xl_seq_rec *) rec; xl_seq_rec *xlrec = (xl_seq_rec *) rec;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.88 2001/03/14 21:50:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.89 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -87,7 +87,9 @@ CreateTrigger(CreateTrigStmt *stmt)
constrrelid = InvalidOid; constrrelid = InvalidOid;
else else
{ {
/* NoLock is probably sufficient here, since we're only
/*
* NoLock is probably sufficient here, since we're only
* interested in getting the relation's OID... * interested in getting the relation's OID...
*/ */
rel = heap_openr(stmt->constrrelname, NoLock); rel = heap_openr(stmt->constrrelname, NoLock);
@ -577,7 +579,8 @@ RelationBuildTriggers(Relation relation)
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(&pg_trigger->tgname)))); NameGetDatum(&pg_trigger->tgname))));
build->tgfoid = pg_trigger->tgfoid; build->tgfoid = pg_trigger->tgfoid;
build->tgfunc.fn_oid = InvalidOid; /* mark FmgrInfo as uninitialized */ build->tgfunc.fn_oid = InvalidOid; /* mark FmgrInfo as
* uninitialized */
build->tgtype = pg_trigger->tgtype; build->tgtype = pg_trigger->tgtype;
build->tgenabled = pg_trigger->tgenabled; build->tgenabled = pg_trigger->tgenabled;
build->tgisconstraint = pg_trigger->tgisconstraint; build->tgisconstraint = pg_trigger->tgisconstraint;
@ -841,17 +844,17 @@ ExecCallTriggerFunc(Trigger *trigger,
MemoryContext oldContext; MemoryContext oldContext;
/* /*
* Fmgr lookup info is cached in the Trigger structure, * Fmgr lookup info is cached in the Trigger structure, so that we
* so that we need not repeat the lookup on every call. * need not repeat the lookup on every call.
*/ */
if (trigger->tgfunc.fn_oid == InvalidOid) if (trigger->tgfunc.fn_oid == InvalidOid)
fmgr_info(trigger->tgfoid, &trigger->tgfunc); fmgr_info(trigger->tgfoid, &trigger->tgfunc);
/* /*
* Do the function evaluation in the per-tuple memory context, * Do the function evaluation in the per-tuple memory context, so that
* so that leaked memory will be reclaimed once per tuple. * leaked memory will be reclaimed once per tuple. Note in particular
* Note in particular that any new tuple created by the trigger function * that any new tuple created by the trigger function will live till
* will live till the end of the tuple cycle. * the end of the tuple cycle.
*/ */
oldContext = MemoryContextSwitchTo(per_tuple_context); oldContext = MemoryContextSwitchTo(per_tuple_context);
@ -868,8 +871,8 @@ ExecCallTriggerFunc(Trigger *trigger,
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
/* /*
* Trigger protocol allows function to return a null pointer, * Trigger protocol allows function to return a null pointer, but NOT
* but NOT to set the isnull result flag. * to set the isnull result flag.
*/ */
if (fcinfo.isnull) if (fcinfo.isnull)
elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL", elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL",
@ -915,10 +918,8 @@ ExecARInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
if (rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 || if (rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 ||
rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 || rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 ||
rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0) rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
{
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple); DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple);
} }
}
bool bool
ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid) ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
@ -1240,10 +1241,11 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate)
static void static void
deferredTriggerAddEvent(DeferredTriggerEvent event) deferredTriggerAddEvent(DeferredTriggerEvent event)
{ {
/* /*
* Since the event list could grow quite long, we keep track of the * Since the event list could grow quite long, we keep track of the
* list tail and append there, rather than just doing a stupid "lappend". * list tail and append there, rather than just doing a stupid
* This avoids O(N^2) behavior for large numbers of events. * "lappend". This avoids O(N^2) behavior for large numbers of events.
*/ */
event->dte_next = NULL; event->dte_next = NULL;
if (deftrig_event_tail == NULL) if (deftrig_event_tail == NULL)

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.73 2001/01/24 19:42:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.74 2001/03/22 03:59:24 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -603,6 +603,7 @@ DropUser(DropUserStmt *stmt)
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(pg_rel, AccessExclusiveLock); heap_close(pg_rel, AccessExclusiveLock);
/* /*
* Advance command counter so that later iterations of this loop * Advance command counter so that later iterations of this loop
* will see the changes already made. This is essential if, for * will see the changes already made. This is essential if, for

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.187 2001/03/14 08:40:57 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.188 2001/03/22 03:59:24 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -120,9 +120,9 @@ vacuum(char *vacrel, bool verbose, bool analyze, List *anal_cols)
/* /*
* Create special memory context for cross-transaction storage. * Create special memory context for cross-transaction storage.
* *
* Since it is a child of QueryContext, it will go away eventually * Since it is a child of QueryContext, it will go away eventually even
* even if we suffer an error; there's no need for special abort * if we suffer an error; there's no need for special abort cleanup
* cleanup logic. * logic.
*/ */
vac_context = AllocSetContextCreate(QueryContext, vac_context = AllocSetContextCreate(QueryContext,
"Vacuum", "Vacuum",
@ -215,8 +215,8 @@ vacuum_shutdown()
/* /*
* Clean up working storage --- note we must do this after * Clean up working storage --- note we must do this after
* StartTransactionCommand, else we might be trying to delete * StartTransactionCommand, else we might be trying to delete the
* the active context! * active context!
*/ */
MemoryContextDelete(vac_context); MemoryContextDelete(vac_context);
vac_context = NULL; vac_context = NULL;
@ -360,10 +360,10 @@ vacuum_rel(Oid relid)
{ {
Relation onerel; Relation onerel;
LockRelId onerelid; LockRelId onerelid;
VacPageListData vacuum_pages; /* List of pages to vacuum and/or clean VacPageListData vacuum_pages; /* List of pages to vacuum and/or
* indices */ * clean indices */
VacPageListData fraged_pages; /* List of pages with space enough for VacPageListData fraged_pages; /* List of pages with space enough
* re-using */ * for re-using */
Relation *Irel; Relation *Irel;
int32 nindices, int32 nindices,
i; i;
@ -412,9 +412,9 @@ vacuum_rel(Oid relid)
/* /*
* Get a session-level exclusive lock too. This will protect our * Get a session-level exclusive lock too. This will protect our
* exclusive access to the relation across multiple transactions, * exclusive access to the relation across multiple transactions, so
* so that we can vacuum the relation's TOAST table (if any) secure * that we can vacuum the relation's TOAST table (if any) secure in
* in the knowledge that no one is diddling the parent relation. * the knowledge that no one is diddling the parent relation.
* *
* NOTE: this cannot block, even if someone else is waiting for access, * NOTE: this cannot block, even if someone else is waiting for access,
* because the lock manager knows that both lock requests are from the * because the lock manager knows that both lock requests are from the
@ -459,9 +459,10 @@ vacuum_rel(Oid relid)
else else
vacrelstats->hasindex = false; vacrelstats->hasindex = false;
#ifdef NOT_USED #ifdef NOT_USED
/* /*
* reindex in VACUUM is dangerous under WAL. * reindex in VACUUM is dangerous under WAL. ifdef out until it
* ifdef out until it becomes safe. * becomes safe.
*/ */
if (reindex) if (reindex)
{ {
@ -506,6 +507,7 @@ vacuum_rel(Oid relid)
} }
else else
{ {
/* /*
* Flush dirty pages out to disk. We must do this even if we * Flush dirty pages out to disk. We must do this even if we
* didn't do anything else, because we want to ensure that all * didn't do anything else, because we want to ensure that all
@ -537,11 +539,11 @@ vacuum_rel(Oid relid)
CommitTransactionCommand(); CommitTransactionCommand();
/* /*
* If the relation has a secondary toast one, vacuum that too * If the relation has a secondary toast one, vacuum that too while we
* while we still hold the session lock on the master table. * still hold the session lock on the master table. We don't need to
* We don't need to propagate "analyze" to it, because the toaster * propagate "analyze" to it, because the toaster always uses
* always uses hardcoded index access and statistics are * hardcoded index access and statistics are totally unimportant for
* totally unimportant for toast relations * toast relations
*/ */
if (toast_relid != InvalidOid) if (toast_relid != InvalidOid)
vacuum_rel(toast_relid); vacuum_rel(toast_relid);
@ -1142,8 +1144,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* If this (chain) tuple is moved by me already then I * If this (chain) tuple is moved by me already then I
* have to check is it in vacpage or not - i.e. is it moved * have to check is it in vacpage or not - i.e. is it
* while cleaning this page or some previous one. * moved while cleaning this page or some previous one.
*/ */
if (tuple.t_data->t_infomask & HEAP_MOVED_OFF) if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
{ {
@ -1232,8 +1234,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* xaction and this tuple is already deleted by * xaction and this tuple is already deleted by
* me. Actually, upper part of chain should be * me. Actually, upper part of chain should be
* removed and seems that this should be handled * removed and seems that this should be handled
* in scan_heap(), but it's not implemented at * in scan_heap(), but it's not implemented at the
* the moment and so we just stop shrinking here. * moment and so we just stop shrinking here.
*/ */
ReleaseBuffer(Cbuf); ReleaseBuffer(Cbuf);
pfree(vtmove); pfree(vtmove);
@ -1256,8 +1258,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
{ {
/* /*
* if to_vacpage no longer has enough free space to be * if to_vacpage no longer has enough free space
* useful, remove it from fraged_pages list * to be useful, remove it from fraged_pages list
*/ */
if (to_vacpage != NULL && if (to_vacpage != NULL &&
!enough_space(to_vacpage, vacrelstats->min_tlen)) !enough_space(to_vacpage, vacrelstats->min_tlen))
@ -1460,21 +1462,22 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* *
* NOTE: a nasty bug used to lurk here. It is possible * NOTE: a nasty bug used to lurk here. It is possible
* for the source and destination pages to be the same * for the source and destination pages to be the same
* (since this tuple-chain member can be on a page lower * (since this tuple-chain member can be on a page
* than the one we're currently processing in the outer * lower than the one we're currently processing in
* loop). If that's true, then after vacuum_page() the * the outer loop). If that's true, then after
* source tuple will have been moved, and tuple.t_data * vacuum_page() the source tuple will have been
* will be pointing at garbage. Therefore we must do * moved, and tuple.t_data will be pointing at
* everything that uses tuple.t_data BEFORE this step!! * garbage. Therefore we must do everything that uses
* tuple.t_data BEFORE this step!!
* *
* This path is different from the other callers of * This path is different from the other callers of
* vacuum_page, because we have already incremented the * vacuum_page, because we have already incremented
* vacpage's offsets_used field to account for the * the vacpage's offsets_used field to account for the
* tuple(s) we expect to move onto the page. Therefore * tuple(s) we expect to move onto the page. Therefore
* vacuum_page's check for offsets_used == 0 is * vacuum_page's check for offsets_used == 0 is wrong.
* wrong. But since that's a good debugging check for * But since that's a good debugging check for all
* all other callers, we work around it here rather * other callers, we work around it here rather than
* than remove it. * remove it.
*/ */
if (!PageIsEmpty(ToPage) && vtmove[ti].cleanVpd) if (!PageIsEmpty(ToPage) && vtmove[ti].cleanVpd)
{ {
@ -1526,7 +1529,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* Set new tuple's t_ctid pointing to itself for last * Set new tuple's t_ctid pointing to itself for last
* tuple in chain, and to next tuple in chain otherwise. * tuple in chain, and to next tuple in chain
* otherwise.
*/ */
if (!ItemPointerIsValid(&Ctid)) if (!ItemPointerIsValid(&Ctid))
newtup.t_data->t_ctid = newtup.t_self; newtup.t_data->t_ctid = newtup.t_self;
@ -1552,13 +1556,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
{ {
/* /*
* XXX using CurrentMemoryContext here means * XXX using CurrentMemoryContext here means
* intra-vacuum memory leak for functional indexes. * intra-vacuum memory leak for functional
* Should fix someday. * indexes. Should fix someday.
* *
* XXX This code fails to handle partial indexes! * XXX This code fails to handle partial indexes!
* Probably should change it to use ExecOpenIndices. * Probably should change it to use
* ExecOpenIndices.
*/ */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
{ {
@ -1698,13 +1704,13 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
/* insert index' tuples if needed */ /* insert index' tuples if needed */
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
{ {
/* /*
* XXX using CurrentMemoryContext here means * XXX using CurrentMemoryContext here means intra-vacuum
* intra-vacuum memory leak for functional indexes. * memory leak for functional indexes. Should fix someday.
* Should fix someday.
* *
* XXX This code fails to handle partial indexes! * XXX This code fails to handle partial indexes! Probably
* Probably should change it to use ExecOpenIndices. * should change it to use ExecOpenIndices.
*/ */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
{ {
@ -1803,14 +1809,15 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
if (num_moved > 0) if (num_moved > 0)
{ {
/* /*
* We have to commit our tuple movings before we truncate the * We have to commit our tuple movings before we truncate the
* relation. Ideally we should do Commit/StartTransactionCommand * relation. Ideally we should do Commit/StartTransactionCommand
* here, relying on the session-level table lock to protect our * here, relying on the session-level table lock to protect our
* exclusive access to the relation. However, that would require * exclusive access to the relation. However, that would require
* a lot of extra code to close and re-open the relation, indices, * a lot of extra code to close and re-open the relation, indices,
* etc. For now, a quick hack: record status of current transaction * etc. For now, a quick hack: record status of current
* as committed, and continue. * transaction as committed, and continue.
*/ */
RecordTransactionCommit(); RecordTransactionCommit();
} }
@ -1943,6 +1950,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
uncnt = PageRepairFragmentation(page, unused); uncnt = PageRepairFragmentation(page, unused);
{ {
XLogRecPtr recptr; XLogRecPtr recptr;
recptr = log_heap_clean(onerel, buf, (char *) unused, recptr = log_heap_clean(onerel, buf, (char *) unused,
(char *) (&(unused[uncnt])) - (char *) unused); (char *) (&(unused[uncnt])) - (char *) unused);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
@ -1962,9 +1970,9 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
/* /*
* Flush dirty pages out to disk. We do this unconditionally, even if * Flush dirty pages out to disk. We do this unconditionally, even if
* we don't need to truncate, because we want to ensure that all tuples * we don't need to truncate, because we want to ensure that all
* have correct on-row commit status on disk (see bufmgr.c's comments * tuples have correct on-row commit status on disk (see bufmgr.c's
* for FlushRelationBuffers()). * comments for FlushRelationBuffers()).
*/ */
i = FlushRelationBuffers(onerel, blkno); i = FlushRelationBuffers(onerel, blkno);
if (i < 0) if (i < 0)
@ -2005,8 +2013,7 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
int i; int i;
nblocks = vacuum_pages->num_pages; nblocks = vacuum_pages->num_pages;
nblocks -= vacuum_pages->empty_end_pages; /* nothing to do with nblocks -= vacuum_pages->empty_end_pages; /* nothing to do with them */
* them */
for (i = 0, vacpage = vacuum_pages->pagedesc; i < nblocks; i++, vacpage++) for (i = 0, vacpage = vacuum_pages->pagedesc; i < nblocks; i++, vacpage++)
{ {
@ -2022,9 +2029,9 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
/* /*
* Flush dirty pages out to disk. We do this unconditionally, even if * Flush dirty pages out to disk. We do this unconditionally, even if
* we don't need to truncate, because we want to ensure that all tuples * we don't need to truncate, because we want to ensure that all
* have correct on-row commit status on disk (see bufmgr.c's comments * tuples have correct on-row commit status on disk (see bufmgr.c's
* for FlushRelationBuffers()). * comments for FlushRelationBuffers()).
*/ */
Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages); Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages);
nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages; nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages;
@ -2042,7 +2049,8 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
vacrelstats->num_pages, nblocks); vacrelstats->num_pages, nblocks);
nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks); nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks);
Assert(nblocks >= 0); Assert(nblocks >= 0);
vacrelstats->num_pages = nblocks; /* set new number of blocks */ vacrelstats->num_pages = nblocks; /* set new number of
* blocks */
} }
} }
@ -2072,6 +2080,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
uncnt = PageRepairFragmentation(page, unused); uncnt = PageRepairFragmentation(page, unused);
{ {
XLogRecPtr recptr; XLogRecPtr recptr;
recptr = log_heap_clean(onerel, buffer, (char *) unused, recptr = log_heap_clean(onerel, buffer, (char *) unused,
(char *) (&(unused[uncnt])) - (char *) unused); (char *) (&(unused[uncnt])) - (char *) unused);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.45 2001/01/24 19:42:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.46 2001/03/22 03:59:25 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -453,6 +453,7 @@ parse_DefaultXactIsoLevel(char *value)
{ {
#if 0 #if 0
TransactionState s = CurrentTransactionState; TransactionState s = CurrentTransactionState;
#endif #endif
if (value == NULL) if (value == NULL)
@ -704,8 +705,7 @@ SetPGVariable(const char *name, const char *value)
char *mvalue = value ? pstrdup(value) : ((char *) NULL); char *mvalue = value ? pstrdup(value) : ((char *) NULL);
/* /*
* Special cases ought to be removed and handled separately * Special cases ought to be removed and handled separately by TCOP
* by TCOP
*/ */
if (strcasecmp(name, "datestyle") == 0) if (strcasecmp(name, "datestyle") == 0)
parse_date(mvalue); parse_date(mvalue);
@ -749,6 +749,7 @@ GetPGVariable(const char *name)
else else
{ {
const char *val = GetConfigOption(name); const char *val = GetConfigOption(name);
elog(NOTICE, "%s is %s", name, val); elog(NOTICE, "%s is %s", name, val);
} }
} }

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: view.c,v 1.53 2001/01/24 19:42:53 momjian Exp $ * $Id: view.c,v 1.54 2001/03/22 03:59:25 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -211,12 +211,12 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
*rt_entry2; *rt_entry2;
/* /*
* Make a copy of the given parsetree. It's not so much that we * Make a copy of the given parsetree. It's not so much that we don't
* don't want to scribble on our input, it's that the parser has * want to scribble on our input, it's that the parser has a bad habit
* a bad habit of outputting multiple links to the same subtree * of outputting multiple links to the same subtree for constructs
* for constructs like BETWEEN, and we mustn't have OffsetVarNodes * like BETWEEN, and we mustn't have OffsetVarNodes increment the
* increment the varno of a Var node twice. copyObject will expand * varno of a Var node twice. copyObject will expand any
* any multiply-referenced subtree into multiple copies. * multiply-referenced subtree into multiple copies.
*/ */
viewParse = (Query *) copyObject(viewParse); viewParse = (Query *) copyObject(viewParse);
@ -261,6 +261,7 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
void void
DefineView(char *viewName, Query *viewParse) DefineView(char *viewName, Query *viewParse)
{ {
/* /*
* Create the "view" relation NOTE: if it already exists, the xact * Create the "view" relation NOTE: if it already exists, the xact
* will be aborted. * will be aborted.
@ -295,9 +296,10 @@ DefineView(char *viewName, Query *viewParse)
void void
RemoveView(char *viewName) RemoveView(char *viewName)
{ {
/* /*
* We just have to drop the relation; the associated rules will * We just have to drop the relation; the associated rules will be
* be cleaned up automatically. * cleaned up automatically.
*/ */
heap_drop_with_catalog(viewName, allowSystemTableMods); heap_drop_with_catalog(viewName, allowSystemTableMods);
} }

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: execAmi.c,v 1.56 2001/01/24 19:42:53 momjian Exp $ * $Id: execAmi.c,v 1.57 2001/03/22 03:59:25 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.25 2001/01/29 00:39:17 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.26 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -265,6 +265,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
void void
ExecFreeJunkFilter(JunkFilter *junkfilter) ExecFreeJunkFilter(JunkFilter *junkfilter)
{ {
/* /*
* Since the junkfilter is inside its own context, we just have to * Since the junkfilter is inside its own context, we just have to
* delete the context and we're set. * delete the context and we're set.

View File

@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.138 2001/01/29 00:39:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.139 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -287,6 +287,7 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
static void static void
ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan) ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan)
{ {
/* /*
* Check RTEs in the query's primary rangetable. * Check RTEs in the query's primary rangetable.
*/ */
@ -405,12 +406,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
relName = rte->relname; relName = rte->relname;
/* /*
* userid to check as: current user unless we have a setuid indication. * userid to check as: current user unless we have a setuid
* indication.
* *
* Note: GetUserId() is presently fast enough that there's no harm * Note: GetUserId() is presently fast enough that there's no harm in
* in calling it separately for each RTE. If that stops being true, * calling it separately for each RTE. If that stops being true, we
* we could call it once in ExecCheckQueryPerms and pass the userid * could call it once in ExecCheckQueryPerms and pass the userid down
* down from there. But for now, no need for the extra clutter. * from there. But for now, no need for the extra clutter.
*/ */
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
@ -426,6 +428,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
if (rte->checkForWrite) if (rte->checkForWrite)
{ {
/* /*
* Note: write access in a SELECT context means SELECT FOR UPDATE. * Note: write access in a SELECT context means SELECT FOR UPDATE.
* Right now we don't distinguish that from true update as far as * Right now we don't distinguish that from true update as far as
@ -519,6 +522,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
if (resultRelations != NIL) if (resultRelations != NIL)
{ {
/* /*
* Multiple result relations (due to inheritance) * Multiple result relations (due to inheritance)
* parseTree->resultRelations identifies them all * parseTree->resultRelations identifies them all
@ -541,8 +545,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
} }
else else
{ {
/* /*
* Single result relation identified by parseTree->resultRelation * Single result relation identified by
* parseTree->resultRelation
*/ */
numResultRelations = 1; numResultRelations = 1;
resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo)); resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
@ -559,6 +565,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
} }
else else
{ {
/* /*
* if no result relation, then set state appropriately * if no result relation, then set state appropriately
*/ */
@ -616,10 +623,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
tupType = ExecGetTupType(plan); /* tuple descriptor */ tupType = ExecGetTupType(plan); /* tuple descriptor */
/* /*
* Initialize the junk filter if needed. SELECT and INSERT queries need * Initialize the junk filter if needed. SELECT and INSERT queries
* a filter if there are any junk attrs in the tlist. UPDATE and * need a filter if there are any junk attrs in the tlist. UPDATE and
* DELETE always need one, since there's always a junk 'ctid' attribute * DELETE always need one, since there's always a junk 'ctid'
* present --- no need to look first. * attribute present --- no need to look first.
*/ */
{ {
bool junk_filter_needed = false; bool junk_filter_needed = false;
@ -650,11 +657,12 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
if (junk_filter_needed) if (junk_filter_needed)
{ {
/* /*
* If there are multiple result relations, each one needs * If there are multiple result relations, each one needs its
* its own junk filter. Note this is only possible for * own junk filter. Note this is only possible for
* UPDATE/DELETE, so we can't be fooled by some needing * UPDATE/DELETE, so we can't be fooled by some needing a
* a filter and some not. * filter and some not.
*/ */
if (parseTree->resultRelations != NIL) if (parseTree->resultRelations != NIL)
{ {
@ -678,6 +686,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
resultRelInfo++; resultRelInfo++;
subplans = lnext(subplans); subplans = lnext(subplans);
} }
/* /*
* Set active junkfilter too; at this point ExecInitAppend * Set active junkfilter too; at this point ExecInitAppend
* has already selected an active result relation... * has already selected an active result relation...
@ -750,10 +759,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
CommandCounterIncrement(); CommandCounterIncrement();
/* /*
* If necessary, create a TOAST table for the into relation. * If necessary, create a TOAST table for the into
* Note that AlterTableCreateToastTable ends with * relation. Note that AlterTableCreateToastTable ends
* CommandCounterIncrement(), so that the TOAST table will * with CommandCounterIncrement(), so that the TOAST table
* be visible for insertion. * will be visible for insertion.
*/ */
AlterTableCreateToastTable(intoName, true); AlterTableCreateToastTable(intoName, true);
@ -817,9 +826,8 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
/* /*
* If there are indices on the result relation, open them and save * If there are indices on the result relation, open them and save
* descriptors in the result relation info, so that we can add new * descriptors in the result relation info, so that we can add new
* index entries for the tuples we add/update. We need not do * index entries for the tuples we add/update. We need not do this
* this for a DELETE, however, since deletion doesn't affect * for a DELETE, however, since deletion doesn't affect indexes.
* indexes.
*/ */
if (resultRelationDesc->rd_rel->relhasindex && if (resultRelationDesc->rd_rel->relhasindex &&
operation != CMD_DELETE) operation != CMD_DELETE)
@ -857,8 +865,8 @@ EndPlan(Plan *plan, EState *estate)
estate->es_tupleTable = NULL; estate->es_tupleTable = NULL;
/* /*
* close the result relation(s) if any, but hold locks * close the result relation(s) if any, but hold locks until xact
* until xact commit. Also clean up junkfilters if present. * commit. Also clean up junkfilters if present.
*/ */
resultRelInfo = estate->es_result_relations; resultRelInfo = estate->es_result_relations;
for (i = estate->es_num_result_relations; i > 0; i--) for (i = estate->es_num_result_relations; i > 0; i--)
@ -1227,11 +1235,12 @@ ExecAppend(TupleTableSlot *slot,
if (newtuple != tuple) /* modified by Trigger(s) */ if (newtuple != tuple) /* modified by Trigger(s) */
{ {
/* /*
* Insert modified tuple into tuple table slot, replacing the * Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple * original. We assume that it was allocated in per-tuple
* memory context, and therefore will go away by itself. * memory context, and therefore will go away by itself. The
* The tuple table slot should not try to clear it. * tuple table slot should not try to clear it.
*/ */
ExecStoreTuple(newtuple, slot, InvalidBuffer, false); ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
tuple = newtuple; tuple = newtuple;
@ -1411,11 +1420,12 @@ ExecReplace(TupleTableSlot *slot,
if (newtuple != tuple) /* modified by Trigger(s) */ if (newtuple != tuple) /* modified by Trigger(s) */
{ {
/* /*
* Insert modified tuple into tuple table slot, replacing the * Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple * original. We assume that it was allocated in per-tuple
* memory context, and therefore will go away by itself. * memory context, and therefore will go away by itself. The
* The tuple table slot should not try to clear it. * tuple table slot should not try to clear it.
*/ */
ExecStoreTuple(newtuple, slot, InvalidBuffer, false); ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
tuple = newtuple; tuple = newtuple;
@ -1469,10 +1479,10 @@ lreplace:;
/* /*
* Note: instead of having to update the old index tuples associated * Note: instead of having to update the old index tuples associated
* with the heap tuple, all we do is form and insert new index * with the heap tuple, all we do is form and insert new index tuples.
* tuples. This is because replaces are actually deletes and inserts * This is because replaces are actually deletes and inserts and index
* and index tuple deletion is done automagically by the vacuum * tuple deletion is done automagically by the vacuum daemon. All we
* daemon. All we do is insert new index tuples. -cim 9/27/89 * do is insert new index tuples. -cim 9/27/89
*/ */
/* /*
@ -1525,8 +1535,8 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
} }
/* /*
* We will use the EState's per-tuple context for evaluating constraint * We will use the EState's per-tuple context for evaluating
* expressions (creating it if it's not already there). * constraint expressions (creating it if it's not already there).
*/ */
econtext = GetPerTupleExprContext(estate); econtext = GetPerTupleExprContext(estate);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.83 2001/01/29 00:39:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.84 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -112,10 +112,11 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext, econtext,
isNull, isNull,
isDone)); isDone));
/* /*
* If refexpr yields NULL, result is always NULL, for now anyway. * If refexpr yields NULL, result is always NULL, for now anyway.
* (This means you cannot assign to an element or slice of an array * (This means you cannot assign to an element or slice of an
* that's NULL; it'll just stay NULL.) * array that's NULL; it'll just stay NULL.)
*/ */
if (*isNull) if (*isNull)
return (Datum) NULL; return (Datum) NULL;
@ -166,7 +167,11 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext, econtext,
isNull, isNull,
NULL)); NULL));
/* If any index expr yields NULL, result is NULL or source array */
/*
* If any index expr yields NULL, result is NULL or source
* array
*/
if (*isNull) if (*isNull)
{ {
if (!isAssignment || array_source == NULL) if (!isAssignment || array_source == NULL)
@ -189,9 +194,10 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext, econtext,
isNull, isNull,
NULL); NULL);
/* /*
* For now, can't cope with inserting NULL into an array, * For now, can't cope with inserting NULL into an array, so make
* so make it a no-op per discussion above... * it a no-op per discussion above...
*/ */
if (*isNull) if (*isNull)
{ {
@ -601,10 +607,12 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
if (thisArgIsDone != ExprSingleResult) if (thisArgIsDone != ExprSingleResult)
{ {
/* /*
* We allow only one argument to have a set value; we'd need * We allow only one argument to have a set value; we'd need
* much more complexity to keep track of multiple set arguments * much more complexity to keep track of multiple set
* (cf. ExecTargetList) and it doesn't seem worth it. * arguments (cf. ExecTargetList) and it doesn't seem worth
* it.
*/ */
if (argIsDone != ExprSingleResult) if (argIsDone != ExprSingleResult)
elog(ERROR, "Functions and operators can take only one set argument"); elog(ERROR, "Functions and operators can take only one set argument");
@ -639,8 +647,8 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
/* /*
* arguments is a list of expressions to evaluate before passing to * arguments is a list of expressions to evaluate before passing to
* the function manager. We skip the evaluation if it was already * the function manager. We skip the evaluation if it was already
* done in the previous call (ie, we are continuing the evaluation * done in the previous call (ie, we are continuing the evaluation of
* of a set-valued function). Otherwise, collect the current argument * a set-valued function). Otherwise, collect the current argument
* values into fcache->fcinfo. * values into fcache->fcinfo.
*/ */
if (fcache->fcinfo.nargs > 0 && !fcache->argsValid) if (fcache->fcinfo.nargs > 0 && !fcache->argsValid)
@ -664,6 +672,7 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
*/ */
if (fcache->func.fn_retset || fcache->hasSetArg) if (fcache->func.fn_retset || fcache->hasSetArg)
{ {
/* /*
* We need to return a set result. Complain if caller not ready * We need to return a set result. Complain if caller not ready
* to accept one. * to accept one.
@ -672,15 +681,16 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
elog(ERROR, "Set-valued function called in context that cannot accept a set"); elog(ERROR, "Set-valued function called in context that cannot accept a set");
/* /*
* This loop handles the situation where we have both a set argument * This loop handles the situation where we have both a set
* and a set-valued function. Once we have exhausted the function's * argument and a set-valued function. Once we have exhausted the
* value(s) for a particular argument value, we have to get the next * function's value(s) for a particular argument value, we have to
* argument value and start the function over again. We might have * get the next argument value and start the function over again.
* to do it more than once, if the function produces an empty result * We might have to do it more than once, if the function produces
* set for a particular input value. * an empty result set for a particular input value.
*/ */
for (;;) for (;;)
{ {
/* /*
* If function is strict, and there are any NULL arguments, * If function is strict, and there are any NULL arguments,
* skip calling the function (at least for this set of args). * skip calling the function (at least for this set of args).
@ -716,13 +726,15 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
if (*isDone != ExprEndResult) if (*isDone != ExprEndResult)
{ {
/* /*
* Got a result from current argument. If function itself * Got a result from current argument. If function itself
* returns set, flag that we want to reuse current argument * returns set, flag that we want to reuse current
* values on next call. * argument values on next call.
*/ */
if (fcache->func.fn_retset) if (fcache->func.fn_retset)
fcache->argsValid = true; fcache->argsValid = true;
/* /*
* Make sure we say we are returning a set, even if the * Make sure we say we are returning a set, even if the
* function itself doesn't return sets. * function itself doesn't return sets.
@ -762,11 +774,12 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
} }
else else
{ {
/* /*
* Non-set case: much easier. * Non-set case: much easier.
* *
* If function is strict, and there are any NULL arguments, * If function is strict, and there are any NULL arguments, skip
* skip calling the function and return NULL. * calling the function and return NULL.
*/ */
if (fcache->func.fn_strict) if (fcache->func.fn_strict)
{ {
@ -852,9 +865,9 @@ ExecEvalFunc(Expr *funcClause,
FunctionCachePtr fcache; FunctionCachePtr fcache;
/* /*
* we extract the oid of the function associated with the func node and * we extract the oid of the function associated with the func node
* then pass the work onto ExecMakeFunctionResult which evaluates the * and then pass the work onto ExecMakeFunctionResult which evaluates
* arguments and returns the result of calling the function on the * the arguments and returns the result of calling the function on the
* evaluated arguments. * evaluated arguments.
* *
* this is nearly identical to the ExecEvalOper code. * this is nearly identical to the ExecEvalOper code.
@ -1412,10 +1425,8 @@ ExecCleanTargetListLength(List *targetlist)
len++; len++;
} }
else else
{
len += curTle->fjoin->fj_nNodes; len += curTle->fjoin->fj_nNodes;
} }
}
return len; return len;
} }
@ -1440,6 +1451,7 @@ ExecTargetList(List *targetlist,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
MemoryContext oldContext; MemoryContext oldContext;
#define NPREALLOCDOMAINS 64 #define NPREALLOCDOMAINS 64
char nullsArray[NPREALLOCDOMAINS]; char nullsArray[NPREALLOCDOMAINS];
bool fjIsNullArray[NPREALLOCDOMAINS]; bool fjIsNullArray[NPREALLOCDOMAINS];
@ -1484,10 +1496,11 @@ ExecTargetList(List *targetlist,
* we have a really large targetlist. otherwise we use the stack. * we have a really large targetlist. otherwise we use the stack.
* *
* We also allocate a bool array that is used to hold fjoin result state, * We also allocate a bool array that is used to hold fjoin result state,
* and another array that holds the isDone status for each targetlist item. * and another array that holds the isDone status for each targetlist
* The isDone status is needed so that we can iterate, generating multiple * item. The isDone status is needed so that we can iterate,
* tuples, when one or more tlist items return sets. (We expect the caller * generating multiple tuples, when one or more tlist items return
* to call us again if we return *isDone = ExprMultipleResult.) * sets. (We expect the caller to call us again if we return *isDone
* = ExprMultipleResult.)
*/ */
if (nodomains > NPREALLOCDOMAINS) if (nodomains > NPREALLOCDOMAINS)
{ {
@ -1554,8 +1567,10 @@ ExecTargetList(List *targetlist,
ExecEvalFjoin(tle, econtext, fjIsNull, isDone); ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
/* XXX this is wrong, but since fjoin code is completely broken /*
* anyway, I'm not going to worry about it now --- tgl 8/23/00 * XXX this is wrong, but since fjoin code is completely
* broken anyway, I'm not going to worry about it now --- tgl
* 8/23/00
*/ */
if (isDone && *isDone == ExprEndResult) if (isDone && *isDone == ExprEndResult)
{ {
@ -1594,6 +1609,7 @@ ExecTargetList(List *targetlist,
if (haveDoneSets) if (haveDoneSets)
{ {
/* /*
* note: can't get here unless we verified isDone != NULL * note: can't get here unless we verified isDone != NULL
*/ */
@ -1601,7 +1617,8 @@ ExecTargetList(List *targetlist,
{ {
/* /*
* all sets are done, so report that tlist expansion is complete. * all sets are done, so report that tlist expansion is
* complete.
*/ */
*isDone = ExprEndResult; *isDone = ExprEndResult;
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
@ -1644,10 +1661,11 @@ ExecTargetList(List *targetlist,
} }
} }
} }
/* /*
* If we cannot make a tuple because some sets are empty, * If we cannot make a tuple because some sets are empty, we
* we still have to cycle the nonempty sets to completion, * still have to cycle the nonempty sets to completion, else
* else resources will not be released from subplans etc. * resources will not be released from subplans etc.
*/ */
if (*isDone == ExprEndResult) if (*isDone == ExprEndResult)
{ {

View File

@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.15 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.16 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.46 2001/01/29 00:39:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.47 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -542,10 +542,12 @@ TupleTableSlot *
ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
{ {
TupleTableSlot *slot = ExecInitExtraTupleSlot(estate); TupleTableSlot *slot = ExecInitExtraTupleSlot(estate);
/* /*
* Since heap_getattr() will treat attributes beyond a tuple's t_natts * Since heap_getattr() will treat attributes beyond a tuple's t_natts
* as being NULL, we can make an all-nulls tuple just by making it be of * as being NULL, we can make an all-nulls tuple just by making it be
* zero length. However, the slot descriptor must match the real tupType. * of zero length. However, the slot descriptor must match the real
* tupType.
*/ */
HeapTuple nullTuple; HeapTuple nullTuple;
Datum values[1]; Datum values[1];

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.73 2001/01/29 00:39:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.74 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -148,6 +148,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
econtext->ecxt_innertuple = NULL; econtext->ecxt_innertuple = NULL;
econtext->ecxt_outertuple = NULL; econtext->ecxt_outertuple = NULL;
econtext->ecxt_per_query_memory = CurrentMemoryContext; econtext->ecxt_per_query_memory = CurrentMemoryContext;
/* /*
* Create working memory for expression evaluation in this context. * Create working memory for expression evaluation in this context.
*/ */
@ -184,14 +185,16 @@ MakeExprContext(TupleTableSlot *slot,
econtext->ecxt_innertuple = NULL; econtext->ecxt_innertuple = NULL;
econtext->ecxt_outertuple = NULL; econtext->ecxt_outertuple = NULL;
econtext->ecxt_per_query_memory = queryContext; econtext->ecxt_per_query_memory = queryContext;
/* /*
* We make the temporary context a child of current working context, * We make the temporary context a child of current working context,
* not of the specified queryContext. This seems reasonable but I'm * not of the specified queryContext. This seems reasonable but I'm
* not totally sure about it... * not totally sure about it...
* *
* Expression contexts made via this routine typically don't live long * Expression contexts made via this routine typically don't live long
* enough to get reset, so specify a minsize of 0. That avoids alloc'ing * enough to get reset, so specify a minsize of 0. That avoids
* any memory in the common case where expr eval doesn't use any. * alloc'ing any memory in the common case where expr eval doesn't use
* any.
*/ */
econtext->ecxt_per_tuple_memory = econtext->ecxt_per_tuple_memory =
AllocSetContextCreate(CurrentMemoryContext, AllocSetContextCreate(CurrentMemoryContext,
@ -635,8 +638,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
heapDescriptor = RelationGetDescr(heapRelation); heapDescriptor = RelationGetDescr(heapRelation);
/* /*
* We will use the EState's per-tuple context for evaluating predicates * We will use the EState's per-tuple context for evaluating
* and functional-index functions (creating it if it's not already there). * predicates and functional-index functions (creating it if it's not
* already there).
*/ */
econtext = GetPerTupleExprContext(estate); econtext = GetPerTupleExprContext(estate);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.43 2001/01/29 00:39:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.44 2001/03/22 03:59:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -235,9 +235,7 @@ init_sql_fcache(FmgrInfo *finfo)
nargs * sizeof(Oid)); nargs * sizeof(Oid));
} }
else else
{
argOidVect = (Oid *) NULL; argOidVect = (Oid *) NULL;
}
tmp = SysCacheGetAttr(PROCOID, tmp = SysCacheGetAttr(PROCOID,
procedureTuple, procedureTuple,
@ -346,8 +344,8 @@ copy_function_result(SQLFunctionCachePtr fcache,
return resultSlot; /* no need to copy result */ return resultSlot; /* no need to copy result */
/* /*
* If first time through, we have to initialize the funcSlot's * If first time through, we have to initialize the funcSlot's tuple
* tuple descriptor. * descriptor.
*/ */
if (funcSlot->ttc_tupleDescriptor == NULL) if (funcSlot->ttc_tupleDescriptor == NULL)
{ {
@ -415,12 +413,14 @@ postquel_execute(execution_state *es,
/* /*
* If we are supposed to return a tuple, we return the tuple slot * If we are supposed to return a tuple, we return the tuple slot
* pointer converted to Datum. If we are supposed to return a simple * pointer converted to Datum. If we are supposed to return a
* value, then project out the first attribute of the result tuple * simple value, then project out the first attribute of the
* (ie, take the first result column of the final SELECT). * result tuple (ie, take the first result column of the final
* SELECT).
*/ */
if (fcache->returnsTuple) if (fcache->returnsTuple)
{ {
/* /*
* XXX do we need to remove junk attrs from the result tuple? * XXX do we need to remove junk attrs from the result tuple?
* Probably OK to leave them, as long as they are at the end. * Probably OK to leave them, as long as they are at the end.
@ -434,6 +434,7 @@ postquel_execute(execution_state *es,
1, 1,
resSlot->ttc_tupleDescriptor, resSlot->ttc_tupleDescriptor,
&(fcinfo->isnull)); &(fcinfo->isnull));
/* /*
* Note: if result type is pass-by-reference then we are * Note: if result type is pass-by-reference then we are
* returning a pointer into the tuple copied by * returning a pointer into the tuple copied by

View File

@ -46,7 +46,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.75 2001/02/16 03:16:57 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.76 2001/03/22 03:59:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -130,8 +130,8 @@ typedef struct AggStatePerAggData
* an input tuple group and updated for each input tuple. * an input tuple group and updated for each input tuple.
* *
* For a simple (non DISTINCT) aggregate, we just feed the input values * For a simple (non DISTINCT) aggregate, we just feed the input values
* straight to the transition function. If it's DISTINCT, we pass * straight to the transition function. If it's DISTINCT, we pass the
* the input values into a Tuplesort object; then at completion of the * input values into a Tuplesort object; then at completion of the
* input tuple group, we scan the sorted values, eliminate duplicates, * input tuple group, we scan the sorted values, eliminate duplicates,
* and run the transition function on the rest. * and run the transition function on the rest.
*/ */
@ -144,11 +144,12 @@ typedef struct AggStatePerAggData
bool noTransValue; /* true if transValue not set yet */ bool noTransValue; /* true if transValue not set yet */
/* /*
* Note: noTransValue initially has the same value as transValueIsNull, * Note: noTransValue initially has the same value as
* and if true both are cleared to false at the same time. They are * transValueIsNull, and if true both are cleared to false at the same
* not the same though: if transfn later returns a NULL, we want to * time. They are not the same though: if transfn later returns a
* keep that NULL and not auto-replace it with a later input value. * NULL, we want to keep that NULL and not auto-replace it with a
* Only the first non-NULL input will be auto-substituted. * later input value. Only the first non-NULL input will be
* auto-substituted.
*/ */
} AggStatePerAggData; } AggStatePerAggData;
@ -195,8 +196,8 @@ initialize_aggregate(AggStatePerAgg peraggstate)
* (Re)set transValue to the initial value. * (Re)set transValue to the initial value.
* *
* Note that when the initial value is pass-by-ref, we just reuse it * Note that when the initial value is pass-by-ref, we just reuse it
* without copying for each group. Hence, transition function * without copying for each group. Hence, transition function had
* had better not scribble on its input, or it will fail for GROUP BY! * better not scribble on its input, or it will fail for GROUP BY!
*/ */
peraggstate->transValue = peraggstate->initValue; peraggstate->transValue = peraggstate->initValue;
peraggstate->transValueIsNull = peraggstate->initValueIsNull; peraggstate->transValueIsNull = peraggstate->initValueIsNull;
@ -228,11 +229,12 @@ advance_transition_function(AggStatePerAgg peraggstate,
{ {
if (isNull) if (isNull)
{ {
/* /*
* For a strict transfn, nothing happens at a NULL input tuple; * For a strict transfn, nothing happens at a NULL input
* we just keep the prior transValue. However, if the transtype * tuple; we just keep the prior transValue. However, if the
* is pass-by-ref, we have to copy it into the new context * transtype is pass-by-ref, we have to copy it into the new
* because the old one is going to get reset. * context because the old one is going to get reset.
*/ */
if (!peraggstate->transValueIsNull) if (!peraggstate->transValueIsNull)
peraggstate->transValue = datumCopy(peraggstate->transValue, peraggstate->transValue = datumCopy(peraggstate->transValue,
@ -242,15 +244,17 @@ advance_transition_function(AggStatePerAgg peraggstate,
} }
if (peraggstate->noTransValue) if (peraggstate->noTransValue)
{ {
/* /*
* transValue has not been initialized. This is the first non-NULL * transValue has not been initialized. This is the first
* input value. We use it as the initial value for transValue. * non-NULL input value. We use it as the initial value for
* (We already checked that the agg's input type is binary- * transValue. (We already checked that the agg's input type
* compatible with its transtype, so straight copy here is OK.) * is binary- compatible with its transtype, so straight copy
* here is OK.)
* *
* We had better copy the datum if it is pass-by-ref, since * We had better copy the datum if it is pass-by-ref, since the
* the given pointer may be pointing into a scan tuple that * given pointer may be pointing into a scan tuple that will
* will be freed on the next iteration of the scan. * be freed on the next iteration of the scan.
*/ */
peraggstate->transValue = datumCopy(newVal, peraggstate->transValue = datumCopy(newVal,
peraggstate->transtypeByVal, peraggstate->transtypeByVal,
@ -261,11 +265,13 @@ advance_transition_function(AggStatePerAgg peraggstate,
} }
if (peraggstate->transValueIsNull) if (peraggstate->transValueIsNull)
{ {
/* /*
* Don't call a strict function with NULL inputs. Note it is * Don't call a strict function with NULL inputs. Note it is
* possible to get here despite the above tests, if the transfn * possible to get here despite the above tests, if the
* is strict *and* returned a NULL on a prior cycle. If that * transfn is strict *and* returned a NULL on a prior cycle.
* happens we will propagate the NULL all the way to the end. * If that happens we will propagate the NULL all the way to
* the end.
*/ */
return; return;
} }
@ -283,10 +289,10 @@ advance_transition_function(AggStatePerAgg peraggstate,
newVal = FunctionCallInvoke(&fcinfo); newVal = FunctionCallInvoke(&fcinfo);
/* /*
* If the transition function was uncooperative, it may have * If the transition function was uncooperative, it may have given us
* given us a pass-by-ref result that points at the scan tuple * a pass-by-ref result that points at the scan tuple or the
* or the prior-cycle working memory. Copy it into the active * prior-cycle working memory. Copy it into the active context if it
* context if it doesn't look right. * doesn't look right.
*/ */
if (!peraggstate->transtypeByVal && !fcinfo.isnull && if (!peraggstate->transtypeByVal && !fcinfo.isnull &&
!MemoryContextContains(CurrentMemoryContext, !MemoryContextContains(CurrentMemoryContext,
@ -321,19 +327,21 @@ process_sorted_aggregate(AggState *aggstate,
/* /*
* Note: if input type is pass-by-ref, the datums returned by the sort * Note: if input type is pass-by-ref, the datums returned by the sort
* are freshly palloc'd in the per-query context, so we must be careful * are freshly palloc'd in the per-query context, so we must be
* to pfree them when they are no longer needed. * careful to pfree them when they are no longer needed.
*/ */
while (tuplesort_getdatum(peraggstate->sortstate, true, while (tuplesort_getdatum(peraggstate->sortstate, true,
&newVal, &isNull)) &newVal, &isNull))
{ {
/* /*
* DISTINCT always suppresses nulls, per SQL spec, regardless of * DISTINCT always suppresses nulls, per SQL spec, regardless of
* the transition function's strictness. * the transition function's strictness.
*/ */
if (isNull) if (isNull)
continue; continue;
/* /*
* Clear and select the current working context for evaluation of * Clear and select the current working context for evaluation of
* the equality function and transition function. * the equality function and transition function.
@ -349,6 +357,7 @@ process_sorted_aggregate(AggState *aggstate,
/* equal to prior, so forget this one */ /* equal to prior, so forget this one */
if (!peraggstate->inputtypeByVal) if (!peraggstate->inputtypeByVal)
pfree(DatumGetPointer(newVal)); pfree(DatumGetPointer(newVal));
/* /*
* note we do NOT flip contexts in this case, so no need to * note we do NOT flip contexts in this case, so no need to
* copy prior transValue to other context. * copy prior transValue to other context.
@ -357,6 +366,7 @@ process_sorted_aggregate(AggState *aggstate,
else else
{ {
advance_transition_function(peraggstate, newVal, false); advance_transition_function(peraggstate, newVal, false);
/* /*
* Make the other context current so that this transition * Make the other context current so that this transition
* result is preserved. * result is preserved.
@ -389,6 +399,7 @@ static void
finalize_aggregate(AggStatePerAgg peraggstate, finalize_aggregate(AggStatePerAgg peraggstate,
Datum *resultVal, bool *resultIsNull) Datum *resultVal, bool *resultIsNull)
{ {
/* /*
* Apply the agg's finalfn if one is provided, else return transValue. * Apply the agg's finalfn if one is provided, else return transValue.
*/ */
@ -480,7 +491,8 @@ ExecAgg(Agg *node)
peragg = aggstate->peragg; peragg = aggstate->peragg;
/* /*
* We loop retrieving groups until we find one matching node->plan.qual * We loop retrieving groups until we find one matching
* node->plan.qual
*/ */
do do
{ {
@ -578,12 +590,12 @@ ExecAgg(Agg *node)
* calculation, and stash results in the per-output-tuple context. * calculation, and stash results in the per-output-tuple context.
* *
* This is a bit tricky when there are both DISTINCT and plain * This is a bit tricky when there are both DISTINCT and plain
* aggregates: we must first finalize all the plain aggs and then all * aggregates: we must first finalize all the plain aggs and then
* the DISTINCT ones. This is needed because the last transition * all the DISTINCT ones. This is needed because the last
* values for the plain aggs are stored in the not-current working * transition values for the plain aggs are stored in the
* context, and we have to evaluate those aggs (and stash the results * not-current working context, and we have to evaluate those aggs
* in the output tup_cxt!) before we start flipping contexts again * (and stash the results in the output tup_cxt!) before we start
* in process_sorted_aggregate. * flipping contexts again in process_sorted_aggregate.
*/ */
oldContext = MemoryContextSwitchTo(aggstate->tup_cxt); oldContext = MemoryContextSwitchTo(aggstate->tup_cxt);
for (aggno = 0; aggno < aggstate->numaggs; aggno++) for (aggno = 0; aggno < aggstate->numaggs; aggno++)
@ -766,11 +778,12 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
ExecAssignExprContext(estate, &aggstate->csstate.cstate); ExecAssignExprContext(estate, &aggstate->csstate.cstate);
/* /*
* We actually need three separate expression memory contexts: one * We actually need three separate expression memory contexts: one for
* for calculating per-output-tuple values (ie, the finished aggregate * calculating per-output-tuple values (ie, the finished aggregate
* results), and two that we ping-pong between for per-input-tuple * results), and two that we ping-pong between for per-input-tuple
* evaluation of input expressions and transition functions. The * evaluation of input expressions and transition functions. The
* context made by ExecAssignExprContext() is used as the output context. * context made by ExecAssignExprContext() is used as the output
* context.
*/ */
aggstate->tup_cxt = aggstate->tup_cxt =
aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory; aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory;
@ -882,15 +895,16 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
/* /*
* If the transfn is strict and the initval is NULL, make sure * If the transfn is strict and the initval is NULL, make sure
* input type and transtype are the same (or at least binary- * input type and transtype are the same (or at least binary-
* compatible), so that it's OK to use the first input value * compatible), so that it's OK to use the first input value as
* as the initial transValue. This should have been checked at * the initial transValue. This should have been checked at agg
* agg definition time, but just in case... * definition time, but just in case...
*/ */
if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull) if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
{ {
/* /*
* Note: use the type from the input expression here, * Note: use the type from the input expression here, not
* not aggform->aggbasetype, because the latter might be 0. * aggform->aggbasetype, because the latter might be 0.
* (Consider COUNT(*).) * (Consider COUNT(*).)
*/ */
Oid inputType = exprType(aggref->target); Oid inputType = exprType(aggref->target);
@ -903,9 +917,10 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
if (aggref->aggdistinct) if (aggref->aggdistinct)
{ {
/* /*
* Note: use the type from the input expression here, * Note: use the type from the input expression here, not
* not aggform->aggbasetype, because the latter might be 0. * aggform->aggbasetype, because the latter might be 0.
* (Consider COUNT(*).) * (Consider COUNT(*).)
*/ */
Oid inputType = exprType(aggref->target); Oid inputType = exprType(aggref->target);
@ -947,12 +962,14 @@ ExecEndAgg(Agg *node)
Plan *outerPlan; Plan *outerPlan;
ExecFreeProjectionInfo(&aggstate->csstate.cstate); ExecFreeProjectionInfo(&aggstate->csstate.cstate);
/* /*
* Make sure ExecFreeExprContext() frees the right expr context... * Make sure ExecFreeExprContext() frees the right expr context...
*/ */
aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory = aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory =
aggstate->tup_cxt; aggstate->tup_cxt;
ExecFreeExprContext(&aggstate->csstate.cstate); ExecFreeExprContext(&aggstate->csstate.cstate);
/* /*
* ... and I free the others. * ... and I free the others.
*/ */

View File

@ -15,7 +15,7 @@
* locate group boundaries. * locate group boundaries.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.41 2001/02/16 03:16:57 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.42 2001/03/22 03:59:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -88,8 +88,8 @@ ExecGroupEveryTuple(Group *node)
tupdesc = ExecGetScanType(&grpstate->csstate); tupdesc = ExecGetScanType(&grpstate->csstate);
/* /*
* We need not call ResetExprContext here because execTuplesMatch * We need not call ResetExprContext here because execTuplesMatch will
* will reset the per-tuple memory context once per input tuple. * reset the per-tuple memory context once per input tuple.
*/ */
/* if we haven't returned first tuple of a new group yet ... */ /* if we haven't returned first tuple of a new group yet ... */
@ -199,8 +199,8 @@ ExecGroupOneTuple(Group *node)
tupdesc = ExecGetScanType(&grpstate->csstate); tupdesc = ExecGetScanType(&grpstate->csstate);
/* /*
* We need not call ResetExprContext here because execTuplesMatch * We need not call ResetExprContext here because execTuplesMatch will
* will reset the per-tuple memory context once per input tuple. * reset the per-tuple memory context once per input tuple.
*/ */
firsttuple = grpstate->grp_firstTuple; firsttuple = grpstate->grp_firstTuple;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* $Id: nodeHash.c,v 1.54 2001/01/24 19:42:54 momjian Exp $ * $Id: nodeHash.c,v 1.55 2001/03/22 03:59:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -540,9 +540,7 @@ ExecHashGetBucket(HashJoinTable hashtable,
* ------------------ * ------------------
*/ */
if (isNull) if (isNull)
{
bucketno = 0; bucketno = 0;
}
else else
{ {
bucketno = hashFunc(keyval, bucketno = hashFunc(keyval,

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