Standard pgindent run for 8.1.

This commit is contained in:
Bruce Momjian 2005-10-15 02:49:52 +00:00
parent 790c01d280
commit 1dc3498251
770 changed files with 34334 additions and 32507 deletions

View File

@ -236,8 +236,8 @@ gbt_ts_penalty(PG_FUNCTION_ARGS)
newdbl[2]; newdbl[2];
/* /*
We are allways using "double" timestamps here. * We are allways using "double" timestamps here. Precision should be good
Precision should be good enough. * enough.
*/ */
orgdbl[0] = ((double) origentry->lower); orgdbl[0] = ((double) origentry->lower);
orgdbl[1] = ((double) origentry->upper); orgdbl[1] = ((double) origentry->upper);

View File

@ -120,7 +120,9 @@ gbt_var_node_cp_len(const GBT_VARKEY * node, const gbtree_vinfo * tinfo)
if (tinfo->eml > 1) if (tinfo->eml > 1)
{ {
return (i - l + 1); return (i - l + 1);
} else { }
else
{
return i; return i;
} }
} }
@ -154,7 +156,9 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo * tin
if (tinfo->eml > 1) if (tinfo->eml > 1)
{ {
out = (varstr_cmp(q, nlen, n, nlen) == 0); out = (varstr_cmp(q, nlen, n, nlen) == 0);
} else { }
else
{
out = TRUE; out = TRUE;
for (k = 0; k < nlen; k++) for (k = 0; k < nlen; k++)
{ {

View File

@ -28,7 +28,8 @@ typedef struct
/* Attribs */ /* Attribs */
enum gbtree_type t; /* data type */ enum gbtree_type t; /* data type */
int32 eml; /* cached pg_database_encoding_max_length (0: undefined) */ int32 eml; /* cached pg_database_encoding_max_length (0:
* undefined) */
bool trnc; /* truncate (=compress) key */ bool trnc; /* truncate (=compress) key */
/* Methods */ /* Methods */

View File

@ -4,7 +4,7 @@
* darcy@druid.net * darcy@druid.net
* http://www.druid.net/darcy/ * http://www.druid.net/darcy/
* *
* $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.13 2005/01/29 22:35:01 tgl Exp $ * $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.14 2005/10/15 02:49:04 momjian Exp $
* best viewed with tabs set to 4 * best viewed with tabs set to 4
*/ */
@ -90,8 +90,8 @@ chkpass_in(PG_FUNCTION_ARGS)
mysalt[0] = salt_chars[random() & 0x3f]; mysalt[0] = salt_chars[random() & 0x3f];
mysalt[1] = salt_chars[random() & 0x3f]; mysalt[1] = salt_chars[random() & 0x3f];
mysalt[2] = 0; /* technically the terminator is not mysalt[2] = 0; /* technically the terminator is not necessary
* necessary but I like to play safe */ * but I like to play safe */
strcpy(result->password, crypt(str, mysalt)); strcpy(result->password, crypt(str, mysalt));
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }

View File

@ -329,8 +329,7 @@ g_cube_picksplit(GistEntryVector *entryvec,
size_waste = size_union - size_inter; size_waste = size_union - size_inter;
/* /*
* are these a more promising split than what we've already * are these a more promising split than what we've already seen?
* seen?
*/ */
if (size_waste > waste || firsttime) if (size_waste > waste || firsttime)
@ -356,24 +355,24 @@ g_cube_picksplit(GistEntryVector *entryvec,
rt_cube_size(datum_r, &size_r); rt_cube_size(datum_r, &size_r);
/* /*
* Now split up the regions between the two seeds. An important * Now split up the regions between the two seeds. An important property
* property of this split algorithm is that the split vector v has the * of this split algorithm is that the split vector v has the indices of
* indices of items to be split in order in its left and right * items to be split in order in its left and right vectors. We exploit
* vectors. We exploit this property by doing a merge in the code * this property by doing a merge in the code that actually splits the
* that actually splits the page. * page.
* *
* For efficiency, we also place the new index tuple in this loop. This * For efficiency, we also place the new index tuple in this loop. This is
* is handled at the very end, when we have placed all the existing * handled at the very end, when we have placed all the existing tuples
* tuples and i == maxoff + 1. * 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 put it * If we've already decided where to place this item, just put it on
* on the right list. Otherwise, we need to figure out which page * the right list. Otherwise, we need to figure out which page needs
* needs the least enlargement in order to store the item. * the least enlargement in order to store the item.
*/ */
if (i == seed_1) if (i == seed_1)
@ -542,8 +541,8 @@ cube_union(NDBOX * a, NDBOX * b)
} }
/* /*
* use the potentially smaller of the two boxes (b) to fill in the * use the potentially smaller of the two boxes (b) to fill in the result,
* result, padding absent dimensions with zeroes * padding absent dimensions with zeroes
*/ */
for (i = 0; i < b->dim; i++) for (i = 0; i < b->dim; i++)
{ {
@ -624,8 +623,7 @@ cube_inter(NDBOX * a, NDBOX * b)
} }
/* /*
* Is it OK to return a non-null intersection for non-overlapping * Is it OK to return a non-null intersection for non-overlapping boxes?
* boxes?
*/ */
return (result); return (result);
} }
@ -713,8 +711,8 @@ cube_cmp(NDBOX * a, NDBOX * b)
} }
/* /*
* if all common dimensions are equal, the cube with more * if all common dimensions are equal, the cube with more dimensions
* dimensions wins * wins
*/ */
return 1; return 1;
} }
@ -736,8 +734,8 @@ cube_cmp(NDBOX * a, NDBOX * b)
} }
/* /*
* if all common dimensions are equal, the cube with more * if all common dimensions are equal, the cube with more dimensions
* dimensions wins * wins
*/ */
return -1; return -1;
} }
@ -797,10 +795,9 @@ cube_contains(NDBOX * a, NDBOX * b)
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
/* /*
* the further comparisons will make sense if the excess * the further comparisons will make sense if the excess dimensions of
* dimensions of (b) were zeroes Since both UL and UR coordinates * (b) were zeroes Since both UL and UR coordinates must be zero, we
* must be zero, we can check them all without worrying about * can check them all without worrying about which is which.
* which is which.
*/ */
for (i = a->dim; i < b->dim; i++) for (i = a->dim; i < b->dim; i++)
{ {

View File

@ -88,10 +88,10 @@ dbf_open(char *file, int flags)
dbh->db_nfields = (dbh->db_hlen - sizeof(dbf_header)) / sizeof(dbf_field); dbh->db_nfields = (dbh->db_hlen - sizeof(dbf_header)) / sizeof(dbf_field);
/* /*
* dbh->db_hlen - sizeof(dbf_header) isn't the correct size, cos * dbh->db_hlen - sizeof(dbf_header) isn't the correct size, cos dbh->hlen
* dbh->hlen is in fact a little more cos of the 0x0D (and possibly * is in fact a little more cos of the 0x0D (and possibly another byte,
* another byte, 0x4E, I have seen this somewhere). Because of * 0x4E, I have seen this somewhere). Because of rounding everything turns
* rounding everything turns out right :) * out right :)
*/ */
if ((fields = (f_descr *) calloc(dbh->db_nfields, sizeof(f_descr))) if ((fields = (f_descr *) calloc(dbh->db_nfields, sizeof(f_descr)))
@ -155,8 +155,7 @@ dbf_write_head(dbhead * dbh)
now = time((time_t *) NULL); now = time((time_t *) NULL);
dbf_time = localtime(&now); dbf_time = localtime(&now);
head.dbh_year = dbf_time->tm_year; head.dbh_year = dbf_time->tm_year;
head.dbh_month = dbf_time->tm_mon + 1; /* Months since January + head.dbh_month = dbf_time->tm_mon + 1; /* Months since January + 1 */
* 1 */
head.dbh_day = dbf_time->tm_mday; head.dbh_day = dbf_time->tm_mday;
put_long(head.dbh_records, dbh->db_records); put_long(head.dbh_records, dbh->db_records);

View File

@ -64,8 +64,7 @@ typedef struct
u_char dbf_type; /* field-type */ u_char dbf_type; /* field-type */
u_char dbf_reserved[4]; /* some reserved stuff */ u_char dbf_reserved[4]; /* some reserved stuff */
u_char dbf_flen; /* field-length */ u_char dbf_flen; /* field-length */
u_char dbf_dec; /* number of decimal positions if type is u_char dbf_dec; /* number of decimal positions if type is 'N' */
* 'N' */
u_char dbf_stub[14]; /* stuff we don't need */ u_char dbf_stub[14]; /* stuff we don't need */
} dbf_field; } dbf_field;
@ -89,15 +88,14 @@ typedef struct
u_char db_year; /* last update as YYMMDD */ u_char db_year; /* last update as YYMMDD */
u_char db_month; u_char db_month;
u_char db_day; u_char db_day;
u_long db_hlen; /* length of the diskheader, for u_long db_hlen; /* length of the diskheader, for calculating
* calculating the offsets */ * the offsets */
u_long db_records; /* number of records */ u_long db_records; /* number of records */
u_long db_currec; /* current record-number starting at 0 */ u_long db_currec; /* current record-number starting at 0 */
u_short db_rlen; /* length of the record */ u_short db_rlen; /* length of the record */
u_char db_nfields; /* number of fields */ u_char db_nfields; /* number of fields */
u_char *db_buff; /* record-buffer to save malloc()'s */ u_char *db_buff; /* record-buffer to save malloc()'s */
f_descr *db_fields; /* pointer to an array of field- f_descr *db_fields; /* pointer to an array of field- descriptions */
* descriptions */
} dbhead; } dbhead;
/* structure that contains everything a user wants from a field, including /* structure that contains everything a user wants from a field, including

View File

@ -359,9 +359,8 @@ do_inserts(PGconn *conn, char *table, dbhead * dbh)
} }
/* /*
* make sure we can build the COPY query, note that we don't need to * make sure we can build the COPY query, note that we don't need to just
* just add this value, since the COPY query is a separate query (see * add this value, since the COPY query is a separate query (see below)
* below)
*/ */
if (h < 17 + strlen(table)) if (h < 17 + strlen(table))
h = 17 + strlen(table); h = 17 + strlen(table);
@ -386,12 +385,10 @@ do_inserts(PGconn *conn, char *table, dbhead * dbh)
exit(1); exit(1);
} }
if (end == 0) /* "end" is a user option, if not if (end == 0) /* "end" is a user option, if not specified, */
* specified, */
end = dbh->db_records; /* then all records are processed. */ end = dbh->db_records; /* then all records are processed. */
if (t_block == 0) /* user not specified transaction block if (t_block == 0) /* user not specified transaction block size */
* size */
t_block = end - begin; /* then we set it to be the full data */ t_block = end - begin; /* then we set it to be the full data */
for (i = begin; i < end; i++) for (i = begin; i < end; i++)
@ -426,9 +423,8 @@ do_inserts(PGconn *conn, char *table, dbhead * dbh)
j = 0; /* counter for fields in the output */ j = 0; /* counter for fields in the output */
for (h = 0; h < dbh->db_nfields; h++) for (h = 0; h < dbh->db_nfields; h++)
{ {
if (!strlen(fields[h].db_name)) /* When the new fieldname if (!strlen(fields[h].db_name)) /* When the new fieldname is
* is empty, the field is * empty, the field is skipped */
* skipped */
continue; continue;
else else
j++; j++;
@ -639,8 +635,8 @@ main(int argc, char **argv)
usage(); usage();
/* /*
* FIXME: Ivan thinks this is bad: printf("unknown * FIXME: Ivan thinks this is bad: printf("unknown argument:
* argument: %s\n", argv[0]); * %s\n", argv[0]);
*/ */
exit(1); exit(1);
break; break;

View File

@ -62,8 +62,7 @@ typedef struct remoteConn
{ {
PGconn *conn; /* Hold the remote connection */ PGconn *conn; /* Hold the remote connection */
int autoXactCursors;/* Indicates the number of open cursors, int autoXactCursors;/* Indicates the number of open cursors,
* non-zero means we opened the xact * non-zero means we opened the xact ourselves */
* ourselves */
} remoteConn; } remoteConn;
/* /*
@ -514,8 +513,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT(); funcctx = SRF_FIRSTCALL_INIT();
/* /*
* switch to memory context appropriate for multiple function * switch to memory context appropriate for multiple function calls
* calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -664,8 +662,7 @@ dblink_record(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT(); funcctx = SRF_FIRSTCALL_INIT();
/* /*
* switch to memory context appropriate for multiple function * switch to memory context appropriate for multiple function calls
* calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -730,8 +727,8 @@ dblink_record(PG_FUNCTION_ARGS)
TEXTOID, -1, 0); TEXTOID, -1, 0);
/* /*
* and save a copy of the command status string to return as * and save a copy of the command status string to return as our
* our result tuple * result tuple
*/ */
sql_cmd_status = PQcmdStatus(res); sql_cmd_status = PQcmdStatus(res);
funcctx->max_calls = 1; funcctx->max_calls = 1;
@ -975,8 +972,7 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT(); funcctx = SRF_FIRSTCALL_INIT();
/* /*
* switch to memory context appropriate for multiple function * switch to memory context appropriate for multiple function calls
* calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -989,8 +985,7 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
GET_STR(PG_GETARG_TEXT_P(0))))); GET_STR(PG_GETARG_TEXT_P(0)))));
/* /*
* need a tuple descriptor representing one INT and one TEXT * need a tuple descriptor representing one INT and one TEXT column
* column
*/ */
tupdesc = CreateTemplateTupleDesc(2, false); tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "position", TupleDescInitEntry(tupdesc, (AttrNumber) 1, "position",
@ -999,8 +994,8 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
TEXTOID, -1, 0); TEXTOID, -1, 0);
/* /*
* Generate attribute metadata needed later to produce tuples from * Generate attribute metadata needed later to produce tuples from raw
* raw C strings * C strings
*/ */
attinmeta = TupleDescGetAttInMetadata(tupdesc); attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta; funcctx->attinmeta = attinmeta;
@ -1145,8 +1140,8 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4); tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
/* /*
* Source array is made up of key values that will be used to locate * Source array is made up of key values that will be used to locate the
* the tuple of interest from the local system. * tuple of interest from the local system.
*/ */
src_ndim = ARR_NDIM(src_pkattvals_arry); src_ndim = ARR_NDIM(src_pkattvals_arry);
src_dim = ARR_DIMS(src_pkattvals_arry); src_dim = ARR_DIMS(src_pkattvals_arry);
@ -1178,8 +1173,8 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
} }
/* /*
* Target array is made up of key values that will be used to build * Target array is made up of key values that will be used to build the
* the SQL string for use on the remote system. * SQL string for use on the remote system.
*/ */
tgt_ndim = ARR_NDIM(tgt_pkattvals_arry); tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
tgt_dim = ARR_DIMS(tgt_pkattvals_arry); tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
@ -1291,8 +1286,8 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3); tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
/* /*
* Target array is made up of key values that will be used to build * Target array is made up of key values that will be used to build the
* the SQL string for use on the remote system. * SQL string for use on the remote system.
*/ */
tgt_ndim = ARR_NDIM(tgt_pkattvals_arry); tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
tgt_dim = ARR_DIMS(tgt_pkattvals_arry); tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
@ -1414,8 +1409,8 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4); tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
/* /*
* Source array is made up of key values that will be used to locate * Source array is made up of key values that will be used to locate the
* the tuple of interest from the local system. * tuple of interest from the local system.
*/ */
src_ndim = ARR_NDIM(src_pkattvals_arry); src_ndim = ARR_NDIM(src_pkattvals_arry);
src_dim = ARR_DIMS(src_pkattvals_arry); src_dim = ARR_DIMS(src_pkattvals_arry);
@ -1447,8 +1442,8 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
} }
/* /*
* Target array is made up of key values that will be used to build * Target array is made up of key values that will be used to build the
* the SQL string for use on the remote system. * SQL string for use on the remote system.
*/ */
tgt_ndim = ARR_NDIM(tgt_pkattvals_arry); tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
tgt_dim = ARR_DIMS(tgt_pkattvals_arry); tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
@ -1894,8 +1889,8 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
elog(ERROR, "SPI connect failure - returned %d", ret); elog(ERROR, "SPI connect failure - returned %d", ret);
/* /*
* Build sql statement to look up tuple of interest Use src_pkattvals * Build sql statement to look up tuple of interest Use src_pkattvals as
* as the criteria. * the criteria.
*/ */
appendStringInfo(str, "SELECT * FROM %s WHERE ", relname); appendStringInfo(str, "SELECT * FROM %s WHERE ", relname);

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* pending.c * pending.c
* $Id: pending.c,v 1.22 2005/10/02 23:50:05 tgl Exp $ * $Id: pending.c,v 1.23 2005/10/15 02:49:04 momjian Exp $
* $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.22 2005/10/02 23:50:05 tgl Exp $ * $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.23 2005/10/15 02:49:04 momjian Exp $
* *
* This file contains a trigger for Postgresql-7.x to record changes to tables * This file contains a trigger for Postgresql-7.x to record changes to tables
* to a pending table for mirroring. * to a pending table for mirroring.

View File

@ -367,9 +367,8 @@ breakup(char *string, char *substring)
while (cur_pos > string) /* don't read before start of 'string' */ while (cur_pos > string) /* don't read before start of 'string' */
{ {
/* /*
* skip pieces at the end of a string that are not alfa-numeric * skip pieces at the end of a string that are not alfa-numeric (ie.
* (ie. 'string$%^&', last_start first points to '&', and after * 'string$%^&', last_start first points to '&', and after this to 'g'
* this to 'g'
*/ */
if (!isalnum((unsigned char) *last_start)) if (!isalnum((unsigned char) *last_start))
{ {
@ -379,8 +378,7 @@ breakup(char *string, char *substring)
cur_pos = last_start; cur_pos = last_start;
} }
cur_pos--; /* substrings are at minimum 2 characters cur_pos--; /* substrings are at minimum 2 characters long */
* long */
if (isalnum((unsigned char) *cur_pos)) if (isalnum((unsigned char) *cur_pos))
{ {

View File

@ -48,8 +48,8 @@
/* /*
* $Revision: 1.5 $ * $Revision: 1.6 $
* $Id: dmetaphone.c,v 1.5 2005/09/30 22:38:44 momjian Exp $ * $Id: dmetaphone.c,v 1.6 2005/10/15 02:49:05 momjian Exp $
*/ */
@ -154,10 +154,10 @@ dmetaphone(PG_FUNCTION_ARGS)
alen = VARSIZE(arg) - VARHDRSZ; alen = VARSIZE(arg) - VARHDRSZ;
/* /*
* Postgres' string values might not have trailing nuls. The VARSIZE * Postgres' string values might not have trailing nuls. The VARSIZE will
* will not include the nul in any case so we copy things out and add * not include the nul in any case so we copy things out and add a
* a trailing nul. When we copy back we ignore the nul (and we don't * trailing nul. When we copy back we ignore the nul (and we don't make
* make space for it). * space for it).
*/ */
aptr = palloc(alen + 1); aptr = palloc(alen + 1);
@ -236,7 +236,6 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
*/ */
#define META_FREE(x) /* pfree((x)) */ #define META_FREE(x) /* pfree((x)) */
#else /* not defined DMETAPHONE_MAIN */ #else /* not defined DMETAPHONE_MAIN */
/* use the standard malloc library when not running in PostgreSQL */ /* use the standard malloc library when not running in PostgreSQL */
@ -787,8 +786,8 @@ DoubleMetaphone(char *str, char **codes)
} }
/* /*
* Parker's rule (with some further refinements) - * Parker's rule (with some further refinements) - e.g.,
* e.g., 'hugh' * 'hugh'
*/ */
if ( if (
((current > 1) ((current > 1)
@ -1187,8 +1186,8 @@ DoubleMetaphone(char *str, char **codes)
/* /*
* german & anglicisations, e.g. 'smith' match 'schmidt', * german & anglicisations, e.g. 'smith' match 'schmidt',
* 'snider' match 'schneider' also, -sz- in slavic * 'snider' match 'schneider' also, -sz- in slavic language
* language although in hungarian it is pronounced 's' * although in hungarian it is pronounced 's'
*/ */
if (((current == 0) if (((current == 0)
&& StringAt(original, (current + 1), 1, && StringAt(original, (current + 1), 1,
@ -1442,8 +1441,8 @@ DoubleMetaphone(char *str, char **codes)
} }
/* /*
* printf("PRIMARY: %s\n", primary->str); printf("SECONDARY: * printf("PRIMARY: %s\n", primary->str); printf("SECONDARY: %s\n",
* %s\n", secondary->str); * secondary->str);
*/ */
} }

View File

@ -65,10 +65,10 @@ levenshtein(PG_FUNCTION_ARGS)
int j; int j;
/* /*
* Fetch the arguments. str_s is referred to as the "source" cols = * Fetch the arguments. str_s is referred to as the "source" cols = length
* length of source + 1 to allow for the initialization column str_t * of source + 1 to allow for the initialization column str_t is referred
* is referred to as the "target", rows = length of target + 1 rows = * to as the "target", rows = length of target + 1 rows = length of target
* length of target + 1 to allow for the initialization row * + 1 to allow for the initialization row
*/ */
str_s = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0)))); str_s = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
str_t = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1)))); str_t = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1))));
@ -78,10 +78,9 @@ levenshtein(PG_FUNCTION_ARGS)
/* /*
* Restrict the length of the strings being compared to something * Restrict the length of the strings being compared to something
* reasonable because we will have to perform rows * cols * reasonable because we will have to perform rows * cols calculations. If
* calculations. If longer strings need to be compared, increase * longer strings need to be compared, increase MAX_LEVENSHTEIN_STRLEN to
* MAX_LEVENSHTEIN_STRLEN to suit (but within your tolerance for speed * suit (but within your tolerance for speed and memory usage).
* and memory usage).
*/ */
if ((cols > MAX_LEVENSHTEIN_STRLEN + 1) || (rows > MAX_LEVENSHTEIN_STRLEN + 1)) if ((cols > MAX_LEVENSHTEIN_STRLEN + 1) || (rows > MAX_LEVENSHTEIN_STRLEN + 1))
ereport(ERROR, ereport(ERROR,
@ -90,9 +89,9 @@ levenshtein(PG_FUNCTION_ARGS)
MAX_LEVENSHTEIN_STRLEN))); MAX_LEVENSHTEIN_STRLEN)));
/* /*
* If either rows or cols is 0, the answer is the other value. This * If either rows or cols is 0, the answer is the other value. This makes
* makes sense since it would take that many insertions the build a * sense since it would take that many insertions the build a matching
* matching string * string
*/ */
if (cols == 0) if (cols == 0)
@ -102,9 +101,8 @@ levenshtein(PG_FUNCTION_ARGS)
PG_RETURN_INT32(cols); PG_RETURN_INT32(cols);
/* /*
* Allocate two vectors of integers. One will be used for the "upper" * Allocate two vectors of integers. One will be used for the "upper" row,
* row, the other for the "lower" row. Initialize the "upper" row to * the other for the "lower" row. Initialize the "upper" row to 0..cols
* 0..cols
*/ */
u_cells = palloc(sizeof(int) * cols); u_cells = palloc(sizeof(int) * cols);
for (i = 0; i < cols; i++) for (i = 0; i < cols; i++)
@ -119,14 +117,13 @@ levenshtein(PG_FUNCTION_ARGS)
str_s0 = str_s; str_s0 = str_s;
/* /*
* Loop through the rows, starting at row 1. Row 0 is used for the * Loop through the rows, starting at row 1. Row 0 is used for the initial
* initial "upper" row. * "upper" row.
*/ */
for (j = 1; j < rows; j++) for (j = 1; j < rows; j++)
{ {
/* /*
* We'll always start with col 1, and initialize lower row col 0 * We'll always start with col 1, and initialize lower row col 0 to j
* to j
*/ */
l_cells[0] = j; l_cells[0] = j;
@ -140,8 +137,7 @@ levenshtein(PG_FUNCTION_ARGS)
/* /*
* The "cost" value is 0 if the character at the current col * The "cost" value is 0 if the character at the current col
* position in the source string, matches the character at the * position in the source string, matches the character at the
* current row position in the target string; cost is 1 * current row position in the target string; cost is 1 otherwise.
* otherwise.
*/ */
c = ((CHAREQ(str_s, str_t)) ? 0 : 1); c = ((CHAREQ(str_s, str_t)) ? 0 : 1);
@ -172,8 +168,8 @@ levenshtein(PG_FUNCTION_ARGS)
} }
/* /*
* Lower row now becomes the upper row, and the upper row gets * Lower row now becomes the upper row, and the upper row gets reused
* reused as the new lower row. * as the new lower row.
*/ */
tmp = u_cells; tmp = u_cells;
u_cells = l_cells; u_cells = l_cells;
@ -301,8 +297,8 @@ Lookahead(char *word, int how_far)
for (idx = 0; word[idx] != '\0' && idx < how_far; idx++); for (idx = 0; word[idx] != '\0' && idx < how_far; idx++);
/* Edge forward in the string... */ /* Edge forward in the string... */
letter_ahead = word[idx]; /* idx will be either == to how_far or at letter_ahead = word[idx]; /* idx will be either == to how_far or at the
* the end of the string */ * end of the string */
return letter_ahead; return letter_ahead;
} }
@ -453,11 +449,11 @@ _metaphone(
/* /*
* THOUGHT: It would be nice if, rather than having things * THOUGHT: It would be nice if, rather than having things like...
* like... well, SCI. For SCI you encode the S, then have to * well, SCI. For SCI you encode the S, then have to remember to skip
* remember to skip the C. So the phonome SCI invades both S and * the C. So the phonome SCI invades both S and C. It would be
* C. It would be better, IMHO, to skip the C from the S part of * better, IMHO, to skip the C from the S part of the encoding. Hell,
* the encoding. Hell, I'm trying it. * I'm trying it.
*/ */
/* Ignore non-alphas */ /* Ignore non-alphas */
@ -478,9 +474,9 @@ _metaphone(
break; break;
/* /*
* 'sh' if -CIA- or -CH, but not SCH, except SCHW. (SCHW * 'sh' if -CIA- or -CH, but not SCH, except SCHW. (SCHW is
* is handled in S) S if -CI-, -CE- or -CY- dropped if * handled in S) S if -CI-, -CE- or -CY- dropped if -SCI-,
* -SCI-, SCE-, -SCY- (handed in S) else K * SCE-, -SCY- (handed in S) else K
*/ */
case 'C': case 'C':
if (MAKESOFT(Next_Letter)) if (MAKESOFT(Next_Letter))
@ -534,8 +530,8 @@ _metaphone(
/* /*
* F if in -GH and not B--GH, D--GH, -H--GH, -H---GH else * F if in -GH and not B--GH, D--GH, -H--GH, -H---GH else
* dropped if -GNED, -GN, else dropped if -DGE-, -DGI- or * dropped if -GNED, -GN, else dropped if -DGE-, -DGI- or
* -DGY- (handled in D) else J if in -GE-, -GI, -GY and * -DGY- (handled in D) else J if in -GE-, -GI, -GY and not GG
* not GG else K * else K
*/ */
case 'G': case 'G':
if (Next_Letter == 'H') if (Next_Letter == 'H')
@ -761,14 +757,17 @@ PG_FUNCTION_INFO_V1(difference);
Datum Datum
difference(PG_FUNCTION_ARGS) difference(PG_FUNCTION_ARGS)
{ {
char sndx1[SOUNDEX_LEN+1], sndx2[SOUNDEX_LEN+1]; char sndx1[SOUNDEX_LEN + 1],
int i, result; sndx2[SOUNDEX_LEN + 1];
int i,
result;
_soundex(_textout(PG_GETARG_TEXT_P(0)), sndx1); _soundex(_textout(PG_GETARG_TEXT_P(0)), sndx1);
_soundex(_textout(PG_GETARG_TEXT_P(1)), sndx2); _soundex(_textout(PG_GETARG_TEXT_P(1)), sndx2);
result = 0; result = 0;
for (i=0; i<SOUNDEX_LEN; i++) { for (i = 0; i < SOUNDEX_LEN; i++)
{
if (sndx1[i] == sndx2[i]) if (sndx1[i] == sndx2[i])
result++; result++;
} }

View File

@ -120,6 +120,7 @@ static PGARRAY *
ShrinkPGArray(PGARRAY * p) ShrinkPGArray(PGARRAY * p)
{ {
PGARRAY *pnew; PGARRAY *pnew;
/* get target size */ /* get target size */
int cb = PGARRAY_SIZE(p->items); int cb = PGARRAY_SIZE(p->items);
@ -250,7 +251,8 @@ int_enum(PG_FUNCTION_ARGS)
fcinfo->flinfo->fn_extra = (void *) pc; fcinfo->flinfo->fn_extra = (void *) pc;
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
} }
else /* use existing working state */ else
/* use existing working state */
pc = (CTX *) fcinfo->flinfo->fn_extra; pc = (CTX *) fcinfo->flinfo->fn_extra;
/* Are we done yet? */ /* Are we done yet? */

View File

@ -378,8 +378,7 @@ g_int_picksplit(PG_FUNCTION_ARGS)
pfree(inter_d); pfree(inter_d);
/* /*
* are these a more promising split that what we've already * are these a more promising split that what we've already seen?
* seen?
*/ */
if (size_waste > waste || firsttime) if (size_waste > waste || firsttime)
@ -430,15 +429,15 @@ g_int_picksplit(PG_FUNCTION_ARGS)
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost); qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
/* /*
* Now split up the regions between the two seeds. An important * Now split up the regions between the two seeds. An important property
* property of this split algorithm is that the split vector v has the * of this split algorithm is that the split vector v has the indices of
* indices of items to be split in order in its left and right * items to be split in order in its left and right vectors. We exploit
* vectors. We exploit this property by doing a merge in the code * this property by doing a merge in the code that actually splits the
* that actually splits the page. * page.
* *
* For efficiency, we also place the new index tuple in this loop. This * For efficiency, we also place the new index tuple in this loop. This is
* is handled at the very end, when we have placed all the existing * handled at the very end, when we have placed all the existing tuples
* tuples and i == maxoff + 1. * and i == maxoff + 1.
*/ */
@ -447,9 +446,9 @@ g_int_picksplit(PG_FUNCTION_ARGS)
i = costvector[j].pos; i = costvector[j].pos;
/* /*
* 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
* on the right list. Otherwise, we need to figure out which page * the right list. Otherwise, we need to figure out which page needs
* needs the least enlargement in order to store the item. * the least enlargement in order to store the item.
*/ */
if (i == seed_1) if (i == seed_1)

View File

@ -176,6 +176,7 @@ void *
myalloc(size_t size) myalloc(size_t size)
{ {
void *ptr = malloc(size); void *ptr = malloc(size);
if (!ptr) if (!ptr)
{ {
fprintf(stderr, "out of memory"); fprintf(stderr, "out of memory");
@ -188,6 +189,7 @@ char *
mystrdup(const char *str) mystrdup(const char *str)
{ {
char *result = strdup(str); char *result = strdup(str);
if (!result) if (!result)
{ {
fprintf(stderr, "out of memory"); fprintf(stderr, "out of memory");
@ -237,7 +239,8 @@ get_comma_elts(eary *eary)
{ {
char *ret, char *ret,
*ptr; *ptr;
int i, length = 0; int i,
length = 0;
if (eary->num == 0) if (eary->num == 0)
return mystrdup(""); return mystrdup("");
@ -303,7 +306,9 @@ sql_exec(PGconn *conn, const char *todo, bool quiet)
int nfields; int nfields;
int nrows; int nrows;
int i, j, l; int i,
j,
l;
int *length; int *length;
char *pad; char *pad;
@ -425,8 +430,11 @@ void
sql_exec_searchtables(PGconn *conn, struct options * opts) sql_exec_searchtables(PGconn *conn, struct options * opts)
{ {
char *todo; char *todo;
char *qualifiers, *ptr; char *qualifiers,
char *comma_oids, *comma_filenodes, *comma_tables; *ptr;
char *comma_oids,
*comma_filenodes,
*comma_tables;
bool written = false; bool written = false;
char *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" "; char *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" ";

View File

@ -3,7 +3,7 @@
* pg_buffercache_pages.c * pg_buffercache_pages.c
* display some contents of the buffer cache * display some contents of the buffer cache
* *
* $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.5 2005/10/12 16:45:13 tgl Exp $ * $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.6 2005/10/15 02:49:05 momjian Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
@ -99,8 +99,8 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
funcctx->attinmeta = TupleDescGetAttInMetadata(tupledesc); funcctx->attinmeta = TupleDescGetAttInMetadata(tupledesc);
/* /*
* Create a function context for cross-call persistence * Create a function context for cross-call persistence and initialize
* and initialize the buffer counters. * the buffer counters.
*/ */
fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext)); fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
funcctx->max_calls = NBuffers; funcctx->max_calls = NBuffers;
@ -171,9 +171,9 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
int j; int j;
/* /*
* Use a temporary values array, initially pointing to * Use a temporary values array, initially pointing to fctx->values,
* fctx->values, so it can be reassigned w/o losing the storage * so it can be reassigned w/o losing the storage for subsequent
* for subsequent calls. * calls.
*/ */
for (j = 0; j < NUM_BUFFERCACHE_PAGES_ELEM; j++) for (j = 0; j < NUM_BUFFERCACHE_PAGES_ELEM; j++)
{ {
@ -182,8 +182,8 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
/* /*
* Set all fields except the bufferid to null if the buffer is * Set all fields except the bufferid to null if the buffer is unused
* unused or not valid. * or not valid.
*/ */
if (fctx->record[i].blocknum == InvalidBlockNumber || if (fctx->record[i].blocknum == InvalidBlockNumber ||
fctx->record[i].isvalid == false) fctx->record[i].isvalid == false)
@ -228,4 +228,3 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx); SRF_RETURN_DONE(funcctx);
} }

View File

@ -1,5 +1,5 @@
/* /*
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.42 2005/10/07 15:34:17 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.43 2005/10/15 02:49:06 momjian Exp $
* *
* pgbench: a simple benchmark program for PostgreSQL * pgbench: a simple benchmark program for PostgreSQL
* written by Tatsuo Ishii * written by Tatsuo Ishii
@ -55,8 +55,7 @@ extern int optind;
#define MAXCLIENTS 1024 /* max number of clients allowed */ #define MAXCLIENTS 1024 /* max number of clients allowed */
int nclients = 1; /* default number of simulated clients */ int nclients = 1; /* default number of simulated clients */
int nxacts = 10; /* default number of transactions per int nxacts = 10; /* default number of transactions per clients */
* clients */
/* /*
* scaling factor. for example, tps = 10 will make 1000000 tuples of * scaling factor. for example, tps = 10 will make 1000000 tuples of
@ -78,8 +77,7 @@ bool use_log; /* log transaction latencies to a file */
int remains; /* number of remaining clients */ int remains; /* number of remaining clients */
int is_connect; /* establish connection for each int is_connect; /* establish connection for each transaction */
* transaction */
char *pghost = ""; char *pghost = "";
char *pgport = NULL; char *pgport = NULL;
@ -107,8 +105,8 @@ typedef struct
int state; /* state No. */ int state; /* state No. */
int cnt; /* xacts count */ int cnt; /* xacts count */
int ecnt; /* error count */ int ecnt; /* error count */
int listen; /* 0 indicates that an async query has int listen; /* 0 indicates that an async query has been
* been sent */ * sent */
Variable *variables; /* array of variable definitions */ Variable *variables; /* array of variable definitions */
int nvariables; int nvariables;
struct timeval txn_begin; /* used for measuring latencies */ struct timeval txn_begin; /* used for measuring latencies */
@ -341,15 +339,19 @@ putVariable(CState * st, char *name, char *value)
static char * static char *
assignVariables(CState * st, char *sql) assignVariables(CState * st, char *sql)
{ {
int i, j; int i,
char *p, *name, *val; j;
char *p,
*name,
*val;
void *tmp; void *tmp;
i = 0; i = 0;
while ((p = strchr(&sql[i], ':')) != NULL) while ((p = strchr(&sql[i], ':')) != NULL)
{ {
i = j = p - sql; i = j = p - sql;
do { do
{
i++; i++;
} while (isalnum((unsigned char) sql[i]) || sql[i] == '_'); } while (isalnum((unsigned char) sql[i]) || sql[i] == '_');
if (i == j + 1) if (i == j + 1)
@ -426,8 +428,7 @@ doCustom(CState * state, int n, int debug)
} }
/* /*
* transaction finished: record the time it took in the * transaction finished: record the time it took in the log
* log
*/ */
if (use_log && commands[st->state + 1] == NULL) if (use_log && commands[st->state + 1] == NULL)
{ {
@ -531,7 +532,8 @@ doCustom(CState * state, int n, int debug)
} }
else if (commands[st->state]->type == META_COMMAND) else if (commands[st->state]->type == META_COMMAND)
{ {
int argc = commands[st->state]->argc, i; int argc = commands[st->state]->argc,
i;
char **argv = commands[st->state]->argv; char **argv = commands[st->state]->argv;
if (debug) if (debug)
@ -755,7 +757,8 @@ process_commands(char *buf)
Command *my_commands; Command *my_commands;
int j; int j;
char *p, *tok; char *p,
*tok;
if ((p = strchr(buf, '\n')) != NULL) if ((p = strchr(buf, '\n')) != NULL)
*p = '\0'; *p = '\0';
@ -797,7 +800,8 @@ process_commands(char *buf)
if (strcasecmp(my_commands->argv[0], "setrandom") == 0) if (strcasecmp(my_commands->argv[0], "setrandom") == 0)
{ {
int min, max; int min,
max;
if (my_commands->argc < 4) if (my_commands->argc < 4)
{ {
@ -1016,20 +1020,18 @@ main(int argc, char **argv)
{ {
int c; int c;
int is_init_mode = 0; /* initialize mode? */ int is_init_mode = 0; /* initialize mode? */
int is_no_vacuum = 0; /* no vacuum at all before int is_no_vacuum = 0; /* no vacuum at all before testing? */
* testing? */
int is_full_vacuum = 0; /* do full vacuum before testing? */ int is_full_vacuum = 0; /* do full vacuum before testing? */
int debug = 0; /* debug flag */ int debug = 0; /* debug flag */
int ttype = 0; /* transaction type. 0: TPC-B, 1: SELECT int ttype = 0; /* transaction type. 0: TPC-B, 1: SELECT only,
* only, 2: skip update of branches and * 2: skip update of branches and tellers */
* tellers */
char *filename = NULL; char *filename = NULL;
static CState *state; /* status of clients */ static CState *state; /* status of clients */
struct timeval tv1; /* start up time */ struct timeval tv1; /* start up time */
struct timeval tv2; /* after establishing all connections to struct timeval tv2; /* after establishing all connections to the
* the backend */ * backend */
struct timeval tv3; /* end time */ struct timeval tv3; /* end time */
int i; int i;
@ -1105,7 +1107,8 @@ main(int argc, char **argv)
fprintf(stderr, "Use limit/ulimt to increase the limit before using pgbench.\n"); fprintf(stderr, "Use limit/ulimt to increase the limit before using pgbench.\n");
exit(1); exit(1);
} }
#endif /* #if !(defined(__CYGWIN__) || defined(__MINGW32__)) */ #endif /* #if !(defined(__CYGWIN__) ||
* defined(__MINGW32__)) */
break; break;
case 'C': case 'C':
is_connect = 1; is_connect = 1;

View File

@ -520,7 +520,6 @@ extern void _BF_body_r(BF_ctx * ctx);
#define BF_body() \ #define BF_body() \
_BF_body_r(&data.ctx); _BF_body_r(&data.ctx);
#else #else
#define BF_body() \ #define BF_body() \

View File

@ -246,8 +246,8 @@ des_init(void)
} }
/* /*
* Convert the inverted S-boxes into 4 arrays of 8 bits. Each will * Convert the inverted S-boxes into 4 arrays of 8 bits. Each will handle
* handle 12 bits of the S-box input. * 12 bits of the S-box input.
*/ */
for (b = 0; b < 4; b++) for (b = 0; b < 4; b++)
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
@ -267,8 +267,8 @@ des_init(void)
} }
/* /*
* Invert the key permutation and initialise the inverted key * Invert the key permutation and initialise the inverted key compression
* compression permutation. * permutation.
*/ */
for (i = 0; i < 56; i++) for (i = 0; i < 56; i++)
{ {
@ -284,8 +284,8 @@ des_init(void)
inv_comp_perm[comp_perm[i] - 1] = i; inv_comp_perm[comp_perm[i] - 1] = i;
/* /*
* Set up the OR-mask arrays for the initial and final permutations, * Set up the OR-mask arrays for the initial and final permutations, and
* and for the key initial and compression permutations. * for the key initial and compression permutations.
*/ */
for (k = 0; k < 8; k++) for (k = 0; k < 8; k++)
{ {
@ -347,8 +347,8 @@ des_init(void)
} }
/* /*
* Invert the P-box permutation, and convert into OR-masks for * Invert the P-box permutation, and convert into OR-masks for handling
* handling the output of the S-box arrays setup above. * the output of the S-box arrays setup above.
*/ */
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
un_pbox[pbox[i] - 1] = i; un_pbox[pbox[i] - 1] = i;
@ -411,9 +411,9 @@ des_setkey(const char *key)
&& rawkey1 == old_rawkey1) && rawkey1 == old_rawkey1)
{ {
/* /*
* Already setup for this key. This optimisation fails on a zero * Already setup for this key. This optimisation fails on a zero key
* key (which is weak and has bad parity anyway) in order to * (which is weak and has bad parity anyway) in order to simplify the
* simplify the starting conditions. * starting conditions.
*/ */
return (0); return (0);
} }
@ -560,16 +560,16 @@ do_des(uint32 l_in, uint32 r_in, uint32 *l_out, uint32 *r_out, int count)
| ((r & 0x80000000) >> 31); | ((r & 0x80000000) >> 31);
/* /*
* Do salting for crypt() and friends, and XOR with the * Do salting for crypt() and friends, and XOR with the permuted
* permuted key. * key.
*/ */
f = (r48l ^ r48r) & saltbits; f = (r48l ^ r48r) & saltbits;
r48l ^= f ^ *kl++; r48l ^= f ^ *kl++;
r48r ^= f ^ *kr++; r48r ^= f ^ *kr++;
/* /*
* Do sbox lookups (which shrink it back to 32 bits) and do * Do sbox lookups (which shrink it back to 32 bits) and do the
* the pbox permutation at the same time. * pbox permutation at the same time.
*/ */
f = psbox[0][m_sbox[0][r48l >> 12]] f = psbox[0][m_sbox[0][r48l >> 12]]
| psbox[1][m_sbox[1][r48l & 0xfff]] | psbox[1][m_sbox[1][r48l & 0xfff]]
@ -660,8 +660,8 @@ px_crypt_des(const char *key, const char *setting)
/* /*
* Copy the key, shifting each character up by one bit and padding * Copy the key, shifting each character up by one bit and padding with
* with zeros. * zeros.
*/ */
q = (uint8 *) keybuf; q = (uint8 *) keybuf;
while (q - (uint8 *) keybuf - 8) while (q - (uint8 *) keybuf - 8)
@ -706,10 +706,10 @@ px_crypt_des(const char *key, const char *setting)
strncpy(output, setting, 9); strncpy(output, setting, 9);
/* /*
* Double check that we weren't given a short setting. If we were, * Double check that we weren't given a short setting. If we were, the
* the above code will probably have created wierd values for * above code will probably have created wierd values for count and
* count and salt, but we don't really care. Just make sure the * salt, but we don't really care. Just make sure the output string
* output string doesn't have an extra NUL in it. * doesn't have an extra NUL in it.
*/ */
output[9] = '\0'; output[9] = '\0';
p = output + strlen(output); p = output + strlen(output);
@ -728,9 +728,9 @@ px_crypt_des(const char *key, const char *setting)
output[0] = setting[0]; output[0] = setting[0];
/* /*
* If the encrypted password that the salt was extracted from is * If the encrypted password that the salt was extracted from is only
* only 1 character long, the salt will be corrupted. We need to * 1 character long, the salt will be corrupted. We need to ensure
* ensure that the output string doesn't have an extra NUL in it! * that the output string doesn't have an extra NUL in it!
*/ */
output[1] = setting[1] ? setting[1] : output[0]; output[1] = setting[1] ? setting[1] : output[0];

View File

@ -8,7 +8,7 @@
* *
* $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $ * $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-md5.c,v 1.5 2005/09/24 19:14:04 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/crypt-md5.c,v 1.6 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -24,9 +24,9 @@
char * char *
px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen) px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
{ {
static char *magic = "$1$"; /* This string is magic for this static char *magic = "$1$"; /* This string is magic for this algorithm.
* algorithm. Having it this way, we can * Having it this way, we can get get better
* get get better later on */ * later on */
static char *p; static char *p;
static const char *sp, static const char *sp,
*ep; *ep;

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.4 2005/07/18 17:12:54 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.5 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -114,7 +114,8 @@
#define MD_CTX SHA256_CTX #define MD_CTX SHA256_CTX
#define CIPH_CTX rijndael_ctx #define CIPH_CTX rijndael_ctx
struct fortuna_state { struct fortuna_state
{
uint8 counter[CIPH_BLOCK]; uint8 counter[CIPH_BLOCK];
uint8 result[CIPH_BLOCK]; uint8 result[CIPH_BLOCK];
uint8 key[BLOCK]; uint8 key[BLOCK];
@ -137,29 +138,35 @@ typedef struct fortuna_state FState;
* - No memory allocations. * - No memory allocations.
*/ */
static void ciph_init(CIPH_CTX *ctx, const uint8 *key, int klen) static void
ciph_init(CIPH_CTX * ctx, const uint8 *key, int klen)
{ {
rijndael_set_key(ctx, (const uint32 *) key, klen, 1); rijndael_set_key(ctx, (const uint32 *) key, klen, 1);
} }
static void ciph_encrypt(CIPH_CTX *ctx, const uint8 *in, uint8 *out) static void
ciph_encrypt(CIPH_CTX * ctx, const uint8 *in, uint8 *out)
{ {
rijndael_encrypt(ctx, (const uint32 *) in, (uint32 *) out); rijndael_encrypt(ctx, (const uint32 *) in, (uint32 *) out);
} }
static void md_init(MD_CTX *ctx) static void
md_init(MD_CTX * ctx)
{ {
SHA256_Init(ctx); SHA256_Init(ctx);
} }
static void md_update(MD_CTX *ctx, const uint8 *data, int len) static void
md_update(MD_CTX * ctx, const uint8 *data, int len)
{ {
SHA256_Update(ctx, data, len); SHA256_Update(ctx, data, len);
} }
static void md_result(MD_CTX *ctx, uint8 *dst) static void
md_result(MD_CTX * ctx, uint8 *dst)
{ {
SHA256_CTX tmp; SHA256_CTX tmp;
memcpy(&tmp, ctx, sizeof(*ctx)); memcpy(&tmp, ctx, sizeof(*ctx));
SHA256_Final(dst, &tmp); SHA256_Final(dst, &tmp);
memset(&tmp, 0, sizeof(tmp)); memset(&tmp, 0, sizeof(tmp));
@ -168,9 +175,11 @@ static void md_result(MD_CTX *ctx, uint8 *dst)
/* /*
* initialize state * initialize state
*/ */
static void init_state(FState *st) static void
init_state(FState * st)
{ {
int i; int i;
memset(st, 0, sizeof(*st)); memset(st, 0, sizeof(*st));
for (i = 0; i < NUM_POOLS; i++) for (i = 0; i < NUM_POOLS; i++)
md_init(&st->pool[i]); md_init(&st->pool[i]);
@ -180,9 +189,11 @@ static void init_state(FState *st)
* Endianess does not matter. * Endianess does not matter.
* It just needs to change without repeating. * It just needs to change without repeating.
*/ */
static void inc_counter(FState *st) static void
inc_counter(FState * st)
{ {
uint32 *val = (uint32 *) st->counter; uint32 *val = (uint32 *) st->counter;
if (++val[0]) if (++val[0])
return; return;
if (++val[1]) if (++val[1])
@ -195,7 +206,8 @@ static void inc_counter(FState *st)
/* /*
* This is called 'cipher in counter mode'. * This is called 'cipher in counter mode'.
*/ */
static void encrypt_counter(FState *st, uint8 *dst) static void
encrypt_counter(FState * st, uint8 *dst)
{ {
ciph_encrypt(&st->ciph, st->counter, dst); ciph_encrypt(&st->ciph, st->counter, dst);
inc_counter(st); inc_counter(st);
@ -206,7 +218,8 @@ static void encrypt_counter(FState *st, uint8 *dst)
* The time between reseed must be at least RESEED_INTERVAL * The time between reseed must be at least RESEED_INTERVAL
* microseconds. * microseconds.
*/ */
static int too_often(FState *st) static int
too_often(FState * st)
{ {
int ok; int ok;
struct timeval tv; struct timeval tv;
@ -229,7 +242,8 @@ static int too_often(FState *st)
/* /*
* generate new key from all the pools * generate new key from all the pools
*/ */
static void reseed(FState *st) static void
reseed(FState * st)
{ {
unsigned k; unsigned k;
unsigned n; unsigned n;
@ -240,8 +254,7 @@ static void reseed(FState *st)
st->pool0_bytes = 0; st->pool0_bytes = 0;
/* /*
* Both #0 and #1 reseed would use only pool 0. * Both #0 and #1 reseed would use only pool 0. Just skip #0 then.
* Just skip #0 then.
*/ */
n = ++st->reseed_count; n = ++st->reseed_count;
@ -249,7 +262,8 @@ static void reseed(FState *st)
* The goal: use k-th pool only 1/(2^k) of the time. * The goal: use k-th pool only 1/(2^k) of the time.
*/ */
md_init(&key_md); md_init(&key_md);
for (k = 0; k < NUM_POOLS; k++) { for (k = 0; k < NUM_POOLS; k++)
{
md_result(&st->pool[k], buf); md_result(&st->pool[k], buf);
md_update(&key_md, buf, BLOCK); md_update(&key_md, buf, BLOCK);
@ -274,7 +288,8 @@ static void reseed(FState *st)
/* /*
* Pick a random pool. This uses key bytes as random source. * Pick a random pool. This uses key bytes as random source.
*/ */
static unsigned get_rand_pool(FState *st) static unsigned
get_rand_pool(FState * st)
{ {
unsigned rnd; unsigned rnd;
@ -293,7 +308,8 @@ static unsigned get_rand_pool(FState *st)
/* /*
* update pools * update pools
*/ */
static void add_entropy(FState *st, const uint8 *data, unsigned len) static void
add_entropy(FState * st, const uint8 *data, unsigned len)
{ {
unsigned pos; unsigned pos;
uint8 hash[BLOCK]; uint8 hash[BLOCK];
@ -305,8 +321,7 @@ static void add_entropy(FState *st, const uint8 *data, unsigned len)
md_result(&md, hash); md_result(&md, hash);
/* /*
* Make sure the pool 0 is initialized, * Make sure the pool 0 is initialized, then update randomly.
* then update randomly.
*/ */
if (st->reseed_count == 0 && st->pool0_bytes < POOL0_FILL) if (st->reseed_count == 0 && st->pool0_bytes < POOL0_FILL)
pos = 0; pos = 0;
@ -324,7 +339,8 @@ static void add_entropy(FState *st, const uint8 *data, unsigned len)
/* /*
* Just take 2 next blocks as new key * Just take 2 next blocks as new key
*/ */
static void rekey(FState *st) static void
rekey(FState * st)
{ {
encrypt_counter(st, st->key); encrypt_counter(st, st->key);
encrypt_counter(st, st->key + CIPH_BLOCK); encrypt_counter(st, st->key + CIPH_BLOCK);
@ -336,7 +352,8 @@ static void rekey(FState *st)
* In case it does not, slow down the attacker by initialising * In case it does not, slow down the attacker by initialising
* the couter to random value. * the couter to random value.
*/ */
static void init_counter(FState *st) static void
init_counter(FState * st)
{ {
/* Use next block as counter. */ /* Use next block as counter. */
encrypt_counter(st, st->counter); encrypt_counter(st, st->counter);
@ -348,7 +365,8 @@ static void init_counter(FState *st)
st->counter_init = 1; st->counter_init = 1;
} }
static void extract_data(FState *st, unsigned count, uint8 *dst) static void
extract_data(FState * st, unsigned count, uint8 *dst)
{ {
unsigned n; unsigned n;
unsigned block_nr = 0; unsigned block_nr = 0;
@ -361,7 +379,8 @@ static void extract_data(FState *st, unsigned count, uint8 *dst)
if (!st->counter_init) if (!st->counter_init)
init_counter(st); init_counter(st);
while (count > 0) { while (count > 0)
{
/* produce bytes */ /* produce bytes */
encrypt_counter(st, st->result); encrypt_counter(st, st->result);
@ -393,7 +412,8 @@ static void extract_data(FState *st, unsigned count, uint8 *dst)
static FState main_state; static FState main_state;
static int init_done = 0; static int init_done = 0;
void fortuna_add_entropy(const uint8 *data, unsigned len) void
fortuna_add_entropy(const uint8 *data, unsigned len)
{ {
if (!init_done) if (!init_done)
{ {
@ -405,7 +425,8 @@ void fortuna_add_entropy(const uint8 *data, unsigned len)
add_entropy(&main_state, data, len); add_entropy(&main_state, data, len);
} }
void fortuna_get_bytes(unsigned len, uint8 *dst) void
fortuna_get_bytes(unsigned len, uint8 *dst)
{ {
if (!init_done) if (!init_done)
{ {
@ -416,4 +437,3 @@ void fortuna_get_bytes(unsigned len, uint8 *dst)
return; return;
extract_data(&main_state, len, dst); extract_data(&main_state, len, dst);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.2 2005/07/18 17:12:54 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#ifndef __FORTUNA_H #ifndef __FORTUNA_H
@ -36,4 +36,3 @@ void fortuna_get_bytes(unsigned len, uint8 *dst);
void fortuna_add_entropy(const uint8 *data, unsigned len); void fortuna_add_entropy(const uint8 *data, unsigned len);
#endif #endif

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.22 2005/07/18 17:12:54 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.23 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -240,6 +240,7 @@ int_sha256_free(PX_MD * h)
px_free(ctx); px_free(ctx);
px_free(h); px_free(h);
} }
/* SHA384 */ /* SHA384 */
static unsigned static unsigned
@ -838,7 +839,8 @@ px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
static time_t seed_time = 0; static time_t seed_time = 0;
static time_t check_time = 0; static time_t check_time = 0;
static void system_reseed(void) static void
system_reseed(void)
{ {
uint8 buf[1024]; uint8 buf[1024];
int n; int n;
@ -890,4 +892,3 @@ px_add_entropy(const uint8 *data, unsigned count)
fortuna_add_entropy(data, count); fortuna_add_entropy(data, count);
return 0; return 0;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.c,v 1.2 2005/07/11 15:07:59 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -166,7 +166,8 @@ mbuf_grab(MBuf * mbuf, int len, uint8 **data_p)
return len; return len;
} }
int mbuf_rewind(MBuf *mbuf) int
mbuf_rewind(MBuf * mbuf)
{ {
mbuf->read_pos = mbuf->data; mbuf->read_pos = mbuf->data;
return 0; return 0;
@ -261,6 +262,7 @@ int
pullf_read(PullFilter * pf, int len, uint8 **data_p) pullf_read(PullFilter * pf, int len, uint8 **data_p)
{ {
int res; int res;
if (pf->op->pull) if (pf->op->pull)
{ {
if (pf->buflen && len > pf->buflen) if (pf->buflen && len > pf->buflen)
@ -276,7 +278,8 @@ pullf_read(PullFilter * pf, int len, uint8 **data_p)
int int
pullf_read_max(PullFilter * pf, int len, uint8 **data_p, uint8 *tmpbuf) pullf_read_max(PullFilter * pf, int len, uint8 **data_p, uint8 *tmpbuf)
{ {
int res, total; int res,
total;
uint8 *tmp; uint8 *tmp;
res = pullf_read(pf, len, data_p); res = pullf_read(pf, len, data_p);
@ -289,7 +292,8 @@ pullf_read_max(PullFilter * pf, int len, uint8 **data_p, uint8 *tmpbuf)
len -= res; len -= res;
total = res; total = res;
while (len > 0) { while (len > 0)
{
res = pullf_read(pf, len, &tmp); res = pullf_read(pf, len, &tmp);
if (res < 0) if (res < 0)
{ {
@ -308,10 +312,12 @@ pullf_read_max(PullFilter * pf, int len, uint8 **data_p, uint8 *tmpbuf)
/* /*
* caller wants exatly len bytes and dont bother with references * caller wants exatly len bytes and dont bother with references
*/ */
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst) int
pullf_read_fixed(PullFilter * src, int len, uint8 *dst)
{ {
int res; int res;
uint8 *p; uint8 *p;
res = pullf_read_max(src, len, &p, dst); res = pullf_read_max(src, len, &p, dst);
if (res < 0) if (res < 0)
return res; return res;
@ -333,6 +339,7 @@ pull_from_mbuf(void *arg, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
MBuf *mbuf = arg; MBuf *mbuf = arg;
return mbuf_grab(mbuf, len, data_p); return mbuf_grab(mbuf, len, data_p);
} }
@ -549,8 +556,8 @@ static const struct PushFilterOps mbuf_filter = {
NULL, push_into_mbuf, NULL, NULL NULL, push_into_mbuf, NULL, NULL
}; };
int pushf_create_mbuf_writer(PushFilter **res, MBuf *dst) int
pushf_create_mbuf_writer(PushFilter ** res, MBuf * dst)
{ {
return pushf_create(res, &mbuf_filter, dst, NULL); return pushf_create(res, &mbuf_filter, dst, 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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.h,v 1.1 2005/07/10 13:46:28 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.h,v 1.2 2005/10/15 02:49:06 momjian Exp $
*/ */
#ifndef __PX_MBUF_H #ifndef __PX_MBUF_H
@ -40,13 +40,15 @@ typedef struct PullFilterOps PullFilterOps;
struct PushFilterOps struct PushFilterOps
{ {
/* should return needed buffer size, 0- no buffering, <0 on error /*
* if NULL, no buffering, and priv=init_arg * should return needed buffer size, 0- no buffering, <0 on error if NULL,
* no buffering, and priv=init_arg
*/ */
int (*init) (PushFilter * next, void *init_arg, void **priv_p); int (*init) (PushFilter * next, void *init_arg, void **priv_p);
/* send data to next. should consume all?
* if null, it will be simply copied (in-place) /*
* returns 0 on error * send data to next. should consume all? if null, it will be simply
* copied (in-place) returns 0 on error
*/ */
int (*push) (PushFilter * next, void *priv, int (*push) (PushFilter * next, void *priv,
const uint8 *src, int len); const uint8 *src, int len);
@ -56,13 +58,15 @@ struct PushFilterOps
struct PullFilterOps struct PullFilterOps
{ {
/* should return needed buffer size, 0- no buffering, <0 on error /*
* if NULL, no buffering, and priv=init_arg * should return needed buffer size, 0- no buffering, <0 on error if NULL,
* no buffering, and priv=init_arg
*/ */
int (*init) (void **priv_p, void *init_arg, PullFilter * src); int (*init) (void **priv_p, void *init_arg, PullFilter * src);
/* request data from src, put result ptr to data_p
* can use ptr from src or use buf as work area /*
* if NULL in-place copy * request data from src, put result ptr to data_p can use ptr from src or
* use buf as work area if NULL in-place copy
*/ */
int (*pull) (void *priv, PullFilter * src, int len, int (*pull) (void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen); uint8 **data_p, uint8 *buf, int buflen);
@ -118,4 +122,3 @@ int pullf_create_mbuf_reader(PullFilter ** pf_p, MBuf * mbuf);
} while (0) } while (0)
#endif /* __PX_MBUF_H */ #endif /* __PX_MBUF_H */

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/contrib/pgcrypto/md5.h,v 1.8 2003/11/29 22:39:28 pgsql Exp $ */ /* $PostgreSQL: pgsql/contrib/pgcrypto/md5.h,v 1.9 2005/10/15 02:49:06 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 $ */
/* /*

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.25 2005/07/12 20:27:42 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.26 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -53,7 +53,6 @@
/* Yes, it does. */ /* Yes, it does. */
#include <openssl/aes.h> #include <openssl/aes.h>
#else /* old OPENSSL */ #else /* old OPENSSL */
/* /*
@ -91,7 +90,6 @@
memcpy(iv, (src) + (len) - 16, 16); \ memcpy(iv, (src) + (len) - 16, 16); \
} \ } \
} while (0) } while (0)
#endif /* old OPENSSL */ #endif /* old OPENSSL */
/* /*
@ -157,8 +155,8 @@ digest_finish(PX_MD * h, uint8 *dst)
EVP_DigestFinal(ctx, dst, NULL); EVP_DigestFinal(ctx, dst, NULL);
/* /*
* Some builds of 0.9.7x clear all of ctx in EVP_DigestFinal. * Some builds of 0.9.7x clear all of ctx in EVP_DigestFinal. Fix it by
* Fix it by reinitializing ctx. * reinitializing ctx.
*/ */
EVP_DigestInit(ctx, md); EVP_DigestInit(ctx, md);
} }
@ -246,7 +244,9 @@ typedef struct
} des; } des;
struct struct
{ {
DES_key_schedule k1, k2, k3; DES_key_schedule k1,
k2,
k3;
} des3; } des3;
CAST_KEY cast_key; CAST_KEY cast_key;
AES_KEY aes_key; AES_KEY aes_key;
@ -825,7 +825,8 @@ static int openssl_random_init = 0;
* OpenSSL random should re-feeded occasionally. From /dev/urandom * OpenSSL random should re-feeded occasionally. From /dev/urandom
* preferably. * preferably.
*/ */
static void init_openssl_rand(void) static void
init_openssl_rand(void)
{ {
if (RAND_get_rand_method() == NULL) if (RAND_get_rand_method() == NULL)
RAND_set_rand_method(RAND_SSLeay()); RAND_set_rand_method(RAND_SSLeay());
@ -871,4 +872,3 @@ px_add_entropy(const uint8 *data, unsigned count)
RAND_add(data, count, 0); RAND_add(data, count, 0);
return 0; return 0;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.19 2005/09/24 19:14:04 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.20 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-armor.c,v 1.2 2005/07/11 15:07:59 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-armor.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -242,11 +242,13 @@ static const uint8 *
find_str(const uint8 *data, const uint8 *data_end, const char *str, int strlen) find_str(const uint8 *data, const uint8 *data_end, const char *str, int strlen)
{ {
const uint8 *p = data; const uint8 *p = data;
if (!strlen) if (!strlen)
return NULL; return NULL;
if (data_end - data < strlen) if (data_end - data < strlen)
return NULL; return NULL;
while (p < data_end) { while (p < data_end)
{
p = memchr(p, str[0], data_end - p); p = memchr(p, str[0], data_end - p);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
@ -313,7 +315,8 @@ pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst)
const uint8 *p = src; const uint8 *p = src;
const uint8 *data_end = src + len; const uint8 *data_end = src + len;
long crc; long crc;
const uint8 *base64_start, *armor_end; const uint8 *base64_start,
*armor_end;
const uint8 *base64_end = NULL; const uint8 *base64_end = NULL;
uint8 buf[4]; uint8 buf[4];
int hlen; int hlen;
@ -378,4 +381,3 @@ pgp_armor_dec_len(unsigned len)
{ {
return b64_dec_len(len); return b64_dec_len(len);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-cfb.c,v 1.2 2005/07/11 15:07:59 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-cfb.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -96,6 +96,7 @@ static int
mix_encrypt_normal(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) mix_encrypt_normal(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
int i; int i;
for (i = ctx->pos; i < ctx->pos + len; i++) for (i = ctx->pos; i < ctx->pos + len; i++)
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++); *dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
ctx->pos += len; ctx->pos += len;
@ -106,6 +107,7 @@ static int
mix_decrypt_normal(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) mix_decrypt_normal(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
int i; int i;
for (i = ctx->pos; i < ctx->pos + len; i++) for (i = ctx->pos; i < ctx->pos + len; i++)
{ {
ctx->encbuf[i] = *data++; ctx->encbuf[i] = *data++;
@ -124,7 +126,9 @@ mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
static int static int
mix_encrypt_resync(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) mix_encrypt_resync(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
int i,n; int i,
n;
/* block #2 is 2 bytes long */ /* block #2 is 2 bytes long */
if (ctx->block_no == 2) if (ctx->block_no == 2)
{ {
@ -154,7 +158,9 @@ mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
static int static int
mix_decrypt_resync(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) mix_decrypt_resync(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
int i,n; int i,
n;
/* block #2 is 2 bytes long */ /* block #2 is 2 bytes long */
if (ctx->block_no == 2) if (ctx->block_no == 2)
{ {
@ -246,6 +252,7 @@ int
pgp_cfb_encrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) pgp_cfb_encrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal; mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
return cfb_process(ctx, data, len, dst, mix); return cfb_process(ctx, data, len, dst, mix);
} }
@ -253,6 +260,6 @@ int
pgp_cfb_decrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst) pgp_cfb_decrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst)
{ {
mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal; mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
return cfb_process(ctx, data, len, dst, mix); return cfb_process(ctx, data, len, dst, mix);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-compress.c,v 1.4 2005/07/18 17:09:01 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-compress.c,v 1.5 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -236,7 +236,8 @@ decompress_init(void **priv_p, void *arg, PullFilter *src)
return 0; return 0;
} }
static int decompress_read(void *priv, PullFilter *src, int len, static int
decompress_read(void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
int res; int res;
@ -257,8 +258,10 @@ restart:
if (dec->eof) if (dec->eof)
return 0; return 0;
if (dec->stream.avail_in == 0) { if (dec->stream.avail_in == 0)
{
uint8 *tmp; uint8 *tmp;
res = pullf_read(src, 8192, &tmp); res = pullf_read(src, 8192, &tmp);
if (res < 0) if (res < 0)
return res; return res;
@ -271,9 +274,9 @@ restart:
dec->pos = dec->buf; dec->pos = dec->buf;
/* /*
* Z_SYNC_FLUSH is tell zlib to output as much as possible. * Z_SYNC_FLUSH is tell zlib to output as much as possible. It should do
* It should do it anyway (Z_NO_FLUSH), but seems to reserve * it anyway (Z_NO_FLUSH), but seems to reserve the right not to. So lets
* the right not to. So lets follow the API. * follow the API.
*/ */
flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH; flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
res = inflate(&dec->stream, flush); res = inflate(&dec->stream, flush);
@ -289,9 +292,11 @@ restart:
goto restart; goto restart;
} }
static void decompress_free(void *priv) static void
decompress_free(void *priv)
{ {
struct DecomprData *dec = priv; struct DecomprData *dec = priv;
inflateEnd(&dec->stream); inflateEnd(&dec->stream);
memset(dec, 0, sizeof(*dec)); memset(dec, 0, sizeof(*dec));
px_free(dec); px_free(dec);
@ -307,7 +312,6 @@ pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
{ {
return pullf_create(res, &decompress_filter, ctx, src); return pullf_create(res, &decompress_filter, ctx, src);
} }
#else /* DISABLE_ZLIB */ #else /* DISABLE_ZLIB */
int int
@ -323,5 +327,3 @@ pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
} }
#endif #endif

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-decrypt.c,v 1.5 2005/09/24 19:14:04 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-decrypt.c,v 1.6 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -165,12 +165,14 @@ pgp_parse_pkt_hdr(PullFilter * src, uint8 *tag, int *len_p, int allow_ctx)
/* /*
* Packet reader * Packet reader
*/ */
struct PktData { struct PktData
{
int type; int type;
int len; int len;
}; };
static int pktreader_pull(void *priv, PullFilter *src, int len, static int
pktreader_pull(void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
int res; int res;
@ -207,6 +209,7 @@ static void
pktreader_free(void *priv) pktreader_free(void *priv)
{ {
struct PktData *pkt = priv; struct PktData *pkt = priv;
memset(pkt, 0, sizeof(*pkt)); memset(pkt, 0, sizeof(*pkt));
px_free(pkt); px_free(pkt);
} }
@ -222,6 +225,7 @@ pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
{ {
int res; int res;
struct PktData *pkt = px_alloc(sizeof(*pkt)); struct PktData *pkt = px_alloc(sizeof(*pkt));
pkt->type = pkttype; pkt->type = pkttype;
pkt->len = len; pkt->len = len;
res = pullf_create(pf_p, &pktreader_filter, pkt, src); res = pullf_create(pf_p, &pktreader_filter, pkt, src);
@ -234,7 +238,8 @@ pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
* Prefix check filter * Prefix check filter
*/ */
static int prefix_init(void **priv_p, void *arg, PullFilter *src) static int
prefix_init(void **priv_p, void *arg, PullFilter * src)
{ {
PGP_Context *ctx = arg; PGP_Context *ctx = arg;
int len; int len;
@ -259,20 +264,19 @@ static int prefix_init(void **priv_p, void *arg, PullFilter *src)
if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1]) if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1])
{ {
px_debug("prefix_init: corrupt prefix"); px_debug("prefix_init: corrupt prefix");
/* /*
* The original purpose of the 2-byte check was * The original purpose of the 2-byte check was to show user a
* to show user a friendly "wrong key" message. * friendly "wrong key" message. This made following possible:
* This made following possible:
* *
* "An Attack on CFB Mode Encryption As Used By OpenPGP" * "An Attack on CFB Mode Encryption As Used By OpenPGP" by Serge Mister
* by Serge Mister and Robert Zuccherato * and Robert Zuccherato
* *
* To avoid being 'oracle', we delay reporting, which * To avoid being 'oracle', we delay reporting, which basically means we
* basically means we prefer to run into corrupt packet * prefer to run into corrupt packet header.
* header.
* *
* We _could_ throw PXE_PGP_CORRUPT_DATA here, but * We _could_ throw PXE_PGP_CORRUPT_DATA here, but there is possibility
* there is possibility of attack via timing, so we don't. * of attack via timing, so we don't.
*/ */
ctx->corrupt_prefix = 1; ctx->corrupt_prefix = 1;
} }
@ -289,7 +293,8 @@ static struct PullFilterOps prefix_filter = {
* Decrypt filter * Decrypt filter
*/ */
static int decrypt_init(void **priv_p, void *arg, PullFilter *src) static int
decrypt_init(void **priv_p, void *arg, PullFilter * src)
{ {
PGP_CFB *cfb = arg; PGP_CFB *cfb = arg;
@ -299,7 +304,8 @@ static int decrypt_init(void **priv_p, void *arg, PullFilter *src)
return 4096; return 4096;
} }
static int decrypt_read(void *priv, PullFilter *src, int len, static int
decrypt_read(void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
PGP_CFB *cfb = priv; PGP_CFB *cfb = priv;
@ -307,7 +313,8 @@ static int decrypt_read(void *priv, PullFilter *src, int len,
int res; int res;
res = pullf_read(src, len, &tmp); res = pullf_read(src, len, &tmp);
if (res > 0) { if (res > 0)
{
pgp_cfb_decrypt(cfb, tmp, res, buf); pgp_cfb_decrypt(cfb, tmp, res, buf);
*data_p = buf; *data_p = buf;
} }
@ -323,23 +330,28 @@ struct PullFilterOps pgp_decrypt_filter = {
* MDC hasher filter * MDC hasher filter
*/ */
static int mdc_init(void **priv_p, void *arg, PullFilter *src) static int
mdc_init(void **priv_p, void *arg, PullFilter * src)
{ {
PGP_Context *ctx = arg; PGP_Context *ctx = arg;
*priv_p = ctx; *priv_p = ctx;
return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx); return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx);
} }
static void mdc_free(void *priv) static void
mdc_free(void *priv)
{ {
PGP_Context *ctx = priv; PGP_Context *ctx = priv;
if (ctx->use_mdcbuf_filter) if (ctx->use_mdcbuf_filter)
return; return;
px_md_free(ctx->mdc_ctx); px_md_free(ctx->mdc_ctx);
ctx->mdc_ctx = NULL; ctx->mdc_ctx = NULL;
} }
static int mdc_finish(PGP_Context *ctx, PullFilter *src, static int
mdc_finish(PGP_Context * ctx, PullFilter * src,
int len, uint8 **data_p) int len, uint8 **data_p)
{ {
int res; int res;
@ -394,7 +406,8 @@ static int mdc_finish(PGP_Context *ctx, PullFilter *src,
return len; return len;
} }
static int mdc_read(void *priv, PullFilter *src, int len, static int
mdc_read(void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
int res; int res;
@ -434,7 +447,8 @@ static struct PullFilterOps mdc_filter = {
* packet, which is silly. * packet, which is silly.
*/ */
#define MDCBUF_LEN 8192 #define MDCBUF_LEN 8192
struct MDCBufData { struct MDCBufData
{
PGP_Context *ctx; PGP_Context *ctx;
int eof; int eof;
int buflen; int buflen;
@ -445,7 +459,8 @@ struct MDCBufData {
uint8 buf[MDCBUF_LEN]; uint8 buf[MDCBUF_LEN];
}; };
static int mdcbuf_init(void **priv_p, void *arg, PullFilter *src) static int
mdcbuf_init(void **priv_p, void *arg, PullFilter * src)
{ {
PGP_Context *ctx = arg; PGP_Context *ctx = arg;
struct MDCBufData *st; struct MDCBufData *st;
@ -462,7 +477,8 @@ static int mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
return 0; return 0;
} }
static int mdcbuf_finish(struct MDCBufData *st) static int
mdcbuf_finish(struct MDCBufData * st)
{ {
uint8 hash[20]; uint8 hash[20];
int res; int res;
@ -486,21 +502,25 @@ static int mdcbuf_finish(struct MDCBufData *st)
return res; return res;
} }
static void mdcbuf_load_data(struct MDCBufData *st, uint8 *src, int len) static void
mdcbuf_load_data(struct MDCBufData * st, uint8 *src, int len)
{ {
uint8 *dst = st->pos + st->avail; uint8 *dst = st->pos + st->avail;
memcpy(dst, src, len); memcpy(dst, src, len);
px_md_update(st->ctx->mdc_ctx, src, len); px_md_update(st->ctx->mdc_ctx, src, len);
st->avail += len; st->avail += len;
} }
static void mdcbuf_load_mdc(struct MDCBufData *st, uint8 *src, int len) static void
mdcbuf_load_mdc(struct MDCBufData * st, uint8 *src, int len)
{ {
memmove(st->mdc_buf + st->mdc_avail, src, len); memmove(st->mdc_buf + st->mdc_avail, src, len);
st->mdc_avail += len; st->mdc_avail += len;
} }
static int mdcbuf_refill(struct MDCBufData *st, PullFilter *src) static int
mdcbuf_refill(struct MDCBufData * st, PullFilter * src)
{ {
uint8 *data; uint8 *data;
int res; int res;
@ -531,6 +551,7 @@ static int mdcbuf_refill(struct MDCBufData *st, PullFilter *src)
else else
{ {
int canmove = st->mdc_avail + res - 22; int canmove = st->mdc_avail + res - 22;
if (canmove > 0) if (canmove > 0)
{ {
mdcbuf_load_data(st, st->mdc_buf, canmove); mdcbuf_load_data(st, st->mdc_buf, canmove);
@ -542,7 +563,8 @@ static int mdcbuf_refill(struct MDCBufData *st, PullFilter *src)
return 0; return 0;
} }
static int mdcbuf_read(void *priv, PullFilter *src, int len, static int
mdcbuf_read(void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen) uint8 **data_p, uint8 *buf, int buflen)
{ {
struct MDCBufData *st = priv; struct MDCBufData *st = priv;
@ -568,6 +590,7 @@ static void
mdcbuf_free(void *priv) mdcbuf_free(void *priv)
{ {
struct MDCBufData *st = priv; struct MDCBufData *st = priv;
px_md_free(st->ctx->mdc_ctx); px_md_free(st->ctx->mdc_ctx);
st->ctx->mdc_ctx = NULL; st->ctx->mdc_ctx = NULL;
memset(st, 0, sizeof(*st)); memset(st, 0, sizeof(*st));
@ -603,7 +626,8 @@ decrypt_key(PGP_Context *ctx, const uint8 *src, int len)
ctx->sess_key_len = len; ctx->sess_key_len = len;
ctx->cipher_algo = algo; ctx->cipher_algo = algo;
if (pgp_get_cipher_key_size(algo) != len) { if (pgp_get_cipher_key_size(algo) != len)
{
px_debug("sesskey bad len: algo=%d, expected=%d, got=%d", px_debug("sesskey bad len: algo=%d, expected=%d, got=%d",
algo, pgp_get_cipher_key_size(algo), len); algo, pgp_get_cipher_key_size(algo), len);
return PXE_PGP_CORRUPT_DATA; return PXE_PGP_CORRUPT_DATA;
@ -693,12 +717,14 @@ copy_crlf(MBuf *dst, uint8 *data, int len, int *got_cr)
int res; int res;
p = tmpbuf; p = tmpbuf;
if (*got_cr) { if (*got_cr)
{
if (*data != '\n') if (*data != '\n')
*p++ = '\r'; *p++ = '\r';
*got_cr = 0; *got_cr = 0;
} }
while (data < data_end) { while (data < data_end)
{
if (*data == '\r') if (*data == '\r')
{ {
if (data + 1 < data_end) if (data + 1 < data_end)
@ -779,7 +805,8 @@ parse_literal_data(PGP_Context * ctx, MBuf * dst, PullFilter * pkt)
ctx->unicode_mode = (type == 'u') ? 1 : 0; ctx->unicode_mode = (type == 'u') ? 1 : 0;
/* read data */ /* read data */
while (1) { while (1)
{
res = pullf_read(pkt, 32 * 1024, &buf); res = pullf_read(pkt, 32 * 1024, &buf);
if (res <= 0) if (res <= 0)
break; break;
@ -1038,6 +1065,7 @@ pgp_skip_packet(PullFilter *pkt)
{ {
int res = 1; int res = 1;
uint8 *tmp; uint8 *tmp;
while (res > 0) while (res > 0)
res = pullf_read(pkt, 32 * 1024, &tmp); res = pullf_read(pkt, 32 * 1024, &tmp);
return res < 0 ? res : 0; return res < 0 ? res : 0;
@ -1051,6 +1079,7 @@ pgp_expect_packet_end(PullFilter *pkt)
{ {
int res = 1; int res = 1;
uint8 *tmp; uint8 *tmp;
while (res > 0) while (res > 0)
{ {
res = pullf_read(pkt, 32 * 1024, &tmp); res = pullf_read(pkt, 32 * 1024, &tmp);
@ -1076,7 +1105,8 @@ pgp_decrypt(PGP_Context * ctx, MBuf * msrc, MBuf * mdst)
res = pullf_create_mbuf_reader(&src, msrc); res = pullf_create_mbuf_reader(&src, msrc);
while (res >= 0) { while (res >= 0)
{
res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE); res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE);
if (res <= 0) if (res <= 0)
break; break;
@ -1086,7 +1116,8 @@ pgp_decrypt(PGP_Context * ctx, MBuf * msrc, MBuf * mdst)
break; break;
res = PXE_PGP_CORRUPT_DATA; res = PXE_PGP_CORRUPT_DATA;
switch (tag) { switch (tag)
{
case PGP_PKT_MARKER: case PGP_PKT_MARKER:
res = pgp_skip_packet(pkt); res = pgp_skip_packet(pkt);
break; break;
@ -1097,10 +1128,11 @@ pgp_decrypt(PGP_Context * ctx, MBuf * msrc, MBuf * mdst)
break; break;
case PGP_PKT_SYMENCRYPTED_SESSKEY: case PGP_PKT_SYMENCRYPTED_SESSKEY:
if (got_key) if (got_key)
/* Theoretically, there could be several keys,
* both public and symmetric, all of which /*
* encrypt same session key. Decrypt should try * Theoretically, there could be several keys, both public
* with each one, before failing. * and symmetric, all of which encrypt same session key.
* Decrypt should try with each one, before failing.
*/ */
px_debug("pgp_decrypt: using first of several keys"); px_debug("pgp_decrypt: using first of several keys");
else else
@ -1154,4 +1186,3 @@ pgp_decrypt(PGP_Context * ctx, MBuf * msrc, MBuf * mdst)
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-encrypt.c,v 1.2 2005/07/11 15:07:59 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-encrypt.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -65,9 +65,11 @@ render_newlen(uint8 *h, int len)
return h; return h;
} }
static int write_tag_only(PushFilter *dst, int tag) static int
write_tag_only(PushFilter * dst, int tag)
{ {
uint8 hdr = 0xC0 | tag; uint8 hdr = 0xC0 | tag;
return pushf_write(dst, &hdr, 1); return pushf_write(dst, &hdr, 1);
} }
@ -166,6 +168,7 @@ encrypt_init(PushFilter * next, void *init_arg, void **priv_p)
if (ctx->disable_mdc == 0) if (ctx->disable_mdc == 0)
{ {
uint8 ver = 1; uint8 ver = 1;
resync = 0; resync = 0;
res = pushf_write(next, &ver, 1); res = pushf_write(next, &ver, 1);
if (res < 0) if (res < 0)
@ -194,6 +197,7 @@ encrypt_process(PushFilter * next, void *priv, const uint8 *data, int len)
while (avail > 0) while (avail > 0)
{ {
int tmplen = avail > ENCBUF ? ENCBUF : avail; int tmplen = avail > ENCBUF ? ENCBUF : avail;
res = pgp_cfb_encrypt(st->ciph, data, tmplen, st->buf); res = pgp_cfb_encrypt(st->ciph, data, tmplen, st->buf);
if (res < 0) if (res < 0)
return res; return res;
@ -303,9 +307,11 @@ static const PushFilterOps pkt_stream_filter = {
pkt_stream_init, pkt_stream_process, pkt_stream_flush, pkt_stream_free pkt_stream_init, pkt_stream_process, pkt_stream_flush, pkt_stream_free
}; };
int pgp_create_pkt_writer(PushFilter *dst, int tag, PushFilter **res_p) int
pgp_create_pkt_writer(PushFilter * dst, int tag, PushFilter ** res_p)
{ {
int res; int res;
res = write_tag_only(dst, tag); res = write_tag_only(dst, tag);
if (res < 0) if (res < 0)
return res; return res;
@ -321,10 +327,12 @@ static int
crlf_process(PushFilter * dst, void *priv, const uint8 *data, int len) crlf_process(PushFilter * dst, void *priv, const uint8 *data, int len)
{ {
const uint8 *data_end = data + len; const uint8 *data_end = data + len;
const uint8 * p2, * p1 = data; const uint8 *p2,
*p1 = data;
int line_len; int line_len;
static const uint8 crlf[] = {'\r', '\n'}; static const uint8 crlf[] = {'\r', '\n'};
int res = 0; int res = 0;
while (p1 < data_end) while (p1 < data_end)
{ {
p2 = memchr(p1, '\n', data_end - p1); p2 = memchr(p1, '\n', data_end - p1);
@ -382,8 +390,8 @@ init_litdata_packet(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
type = 'b'; type = 'b';
/* /*
* Store the creation time into packet. * Store the creation time into packet. The goal is to have as few known
* The goal is to have as few known bytes as possible. * bytes as possible.
*/ */
t = (uint32) time(NULL); t = (uint32) time(NULL);
@ -571,6 +579,7 @@ static int
init_sess_key(PGP_Context * ctx) init_sess_key(PGP_Context * ctx)
{ {
int res; int res;
if (ctx->use_sess_key || ctx->pub_key) if (ctx->use_sess_key || ctx->pub_key)
{ {
ctx->sess_key_len = pgp_get_cipher_key_size(ctx->cipher_algo); ctx->sess_key_len = pgp_get_cipher_key_size(ctx->cipher_algo);
@ -596,7 +605,8 @@ pgp_encrypt(PGP_Context * ctx, MBuf * src, MBuf * dst)
int res; int res;
int len; int len;
uint8 *buf; uint8 *buf;
PushFilter *pf, *pf_tmp; PushFilter *pf,
*pf_tmp;
/* /*
* do we have any key * do we have any key
@ -696,4 +706,3 @@ out:
pushf_free_all(pf); pushf_free_all(pf);
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -34,7 +34,8 @@
#include "mbuf.h" #include "mbuf.h"
#include "pgp.h" #include "pgp.h"
static int read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf) static int
read_pubkey_keyid(PullFilter * pkt, uint8 *keyid_buf)
{ {
int res; int res;
PGP_PubKey *pk = NULL; PGP_PubKey *pk = NULL;
@ -66,7 +67,8 @@ err:
return res; return res;
} }
static int read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf) static int
read_pubenc_keyid(PullFilter * pkt, uint8 *keyid_buf)
{ {
uint8 ver; uint8 ver;
int res; int res;
@ -89,7 +91,9 @@ print_key(uint8 *keyid, char *dst)
{ {
int i; int i;
unsigned c; unsigned c;
for (i = 0; i < 8; i++) {
for (i = 0; i < 8; i++)
{
c = keyid[i]; c = keyid[i];
*dst++ = hextbl[(c >> 4) & 0x0F]; *dst++ = hextbl[(c >> 4) & 0x0F];
*dst++ = hextbl[c & 0x0F]; *dst++ = hextbl[c & 0x0F];
@ -112,7 +116,9 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
PullFilter *pkt = NULL; PullFilter *pkt = NULL;
int len; int len;
uint8 tag; uint8 tag;
int got_pub_key=0, got_symenc_key=0, got_pubenc_key=0; int got_pub_key = 0,
got_symenc_key = 0,
got_pubenc_key = 0;
int got_data = 0; int got_data = 0;
uint8 keyid_buf[8]; uint8 keyid_buf[8];
int got_main_key = 0; int got_main_key = 0;
@ -122,7 +128,8 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
if (res < 0) if (res < 0)
return res; return res;
while (1) { while (1)
{
res = pgp_parse_pkt_hdr(src, &tag, &len, 0); res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
if (res <= 0) if (res <= 0)
break; break;
@ -226,4 +233,3 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -48,14 +48,14 @@ pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
return PXE_PGP_NO_BIGNUM; return PXE_PGP_NO_BIGNUM;
} }
int pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *m, PGP_MPI **c) int
pgp_rsa_encrypt(PGP_PubKey * pk, PGP_MPI * m, PGP_MPI ** c)
{ {
return PXE_PGP_NO_BIGNUM; return PXE_PGP_NO_BIGNUM;
} }
int pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *c, PGP_MPI **m) int
pgp_rsa_decrypt(PGP_PubKey * pk, PGP_MPI * c, PGP_MPI ** m)
{ {
return PXE_PGP_NO_BIGNUM; return PXE_PGP_NO_BIGNUM;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -40,6 +40,7 @@ static BIGNUM *
mpi_to_bn(PGP_MPI * n) mpi_to_bn(PGP_MPI * n)
{ {
BIGNUM *bn = BN_bin2bn(n->data, n->bytes, NULL); BIGNUM *bn = BN_bin2bn(n->data, n->bytes, NULL);
if (!bn) if (!bn)
return NULL; return NULL;
if (BN_num_bits(bn) != n->bits) if (BN_num_bits(bn) != n->bits)
@ -124,8 +125,7 @@ pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
goto err; goto err;
/* /*
* c1 = g^k * c1 = g^k c2 = m * y^k
* c2 = m * y^k
*/ */
if (!BN_mod_exp(c1, g, k, p, tmp)) if (!BN_mod_exp(c1, g, k, p, tmp))
goto err; goto err;
@ -140,15 +140,24 @@ pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
if (*c1_p && *c2_p) if (*c1_p && *c2_p)
res = 0; res = 0;
err: err:
if (tmp) BN_CTX_free(tmp); if (tmp)
if (c2) BN_clear_free(c2); BN_CTX_free(tmp);
if (c1) BN_clear_free(c1); if (c2)
if (yk) BN_clear_free(yk); BN_clear_free(c2);
if (k) BN_clear_free(k); if (c1)
if (y) BN_clear_free(y); BN_clear_free(c1);
if (g) BN_clear_free(g); if (yk)
if (p) BN_clear_free(p); BN_clear_free(yk);
if (m) BN_clear_free(m); if (k)
BN_clear_free(k);
if (y)
BN_clear_free(y);
if (g)
BN_clear_free(g);
if (p)
BN_clear_free(p);
if (m)
BN_clear_free(m);
return res; return res;
} }
@ -184,14 +193,22 @@ pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
if (*msg_p) if (*msg_p)
res = 0; res = 0;
err: err:
if (tmp) BN_CTX_free(tmp); if (tmp)
if (m) BN_clear_free(m); BN_CTX_free(tmp);
if (div) BN_clear_free(div); if (m)
if (c1x) BN_clear_free(c1x); BN_clear_free(m);
if (x) BN_clear_free(x); if (div)
if (p) BN_clear_free(p); BN_clear_free(div);
if (c2) BN_clear_free(c2); if (c1x)
if (c1) BN_clear_free(c1); BN_clear_free(c1x);
if (x)
BN_clear_free(x);
if (p)
BN_clear_free(p);
if (c2)
BN_clear_free(c2);
if (c1)
BN_clear_free(c1);
return res; return res;
} }
@ -218,11 +235,16 @@ pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *_m, PGP_MPI **c_p)
if (*c_p) if (*c_p)
res = 0; res = 0;
err: err:
if (tmp) BN_CTX_free(tmp); if (tmp)
if (c) BN_clear_free(c); BN_CTX_free(tmp);
if (n) BN_clear_free(n); if (c)
if (e) BN_clear_free(e); BN_clear_free(c);
if (m) BN_clear_free(m); if (n)
BN_clear_free(n);
if (e)
BN_clear_free(e);
if (m)
BN_clear_free(m);
return res; return res;
} }
@ -249,11 +271,15 @@ pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *_c, PGP_MPI **m_p)
if (*m_p) if (*m_p)
res = 0; res = 0;
err: err:
if (tmp) BN_CTX_free(tmp); if (tmp)
if (m) BN_clear_free(m); BN_CTX_free(tmp);
if (n) BN_clear_free(n); if (m)
if (d) BN_clear_free(d); BN_clear_free(m);
if (c) BN_clear_free(c); if (n)
BN_clear_free(n);
if (d)
BN_clear_free(d);
if (c)
BN_clear_free(c);
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -34,10 +34,12 @@
#include "mbuf.h" #include "mbuf.h"
#include "pgp.h" #include "pgp.h"
int pgp_mpi_alloc(int bits, PGP_MPI **mpi) int
pgp_mpi_alloc(int bits, PGP_MPI ** mpi)
{ {
PGP_MPI *n; PGP_MPI *n;
int len = (bits + 7) / 8; int len = (bits + 7) / 8;
if (bits < 0 || bits > 0xFFFF) if (bits < 0 || bits > 0xFFFF)
{ {
px_debug("pgp_mpi_alloc: unreasonable request: bits=%d", bits); px_debug("pgp_mpi_alloc: unreasonable request: bits=%d", bits);
@ -51,7 +53,8 @@ int pgp_mpi_alloc(int bits, PGP_MPI **mpi)
return 0; return 0;
} }
int pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi) int
pgp_mpi_create(uint8 *data, int bits, PGP_MPI ** mpi)
{ {
int res; int res;
PGP_MPI *n; PGP_MPI *n;
@ -64,7 +67,8 @@ int pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
return 0; return 0;
} }
int pgp_mpi_free(PGP_MPI *mpi) int
pgp_mpi_free(PGP_MPI * mpi)
{ {
if (mpi == NULL) if (mpi == NULL)
return 0; return 0;
@ -73,7 +77,8 @@ int pgp_mpi_free(PGP_MPI *mpi)
return 0; return 0;
} }
int pgp_mpi_read(PullFilter *src, PGP_MPI **mpi) int
pgp_mpi_read(PullFilter * src, PGP_MPI ** mpi)
{ {
int res; int res;
uint8 hdr[2]; uint8 hdr[2];
@ -97,7 +102,8 @@ int pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
return res; return res;
} }
int pgp_mpi_write(PushFilter *dst, PGP_MPI *n) int
pgp_mpi_write(PushFilter * dst, PGP_MPI * n)
{ {
int res; int res;
uint8 buf[2]; uint8 buf[2];
@ -110,7 +116,8 @@ int pgp_mpi_write(PushFilter *dst, PGP_MPI *n)
return res; return res;
} }
int pgp_mpi_hash(PX_MD *md, PGP_MPI *n) int
pgp_mpi_hash(PX_MD * md, PGP_MPI * n)
{ {
uint8 buf[2]; uint8 buf[2];
@ -122,7 +129,8 @@ int pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
return 0; return 0;
} }
unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n) unsigned
pgp_mpi_cksum(unsigned cksum, PGP_MPI * n)
{ {
int i; int i;
@ -133,4 +141,3 @@ unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
return cksum & 0xFFFF; return cksum & 0xFFFF;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pgsql.c,v 1.5 2005/09/24 19:14:04 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pgsql.c,v 1.6 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -89,7 +89,8 @@ PG_FUNCTION_INFO_V1(pg_dearmor);
/* /*
* Mix a block of data into RNG. * Mix a block of data into RNG.
*/ */
static void add_block_entropy(PX_MD *md, text *data) static void
add_block_entropy(PX_MD * md, text *data)
{ {
uint8 sha1[20]; uint8 sha1[20];
@ -106,7 +107,8 @@ static void add_block_entropy(PX_MD *md, text *data)
* Mix user data into RNG. It is for user own interests to have * Mix user data into RNG. It is for user own interests to have
* RNG state shuffled. * RNG state shuffled.
*/ */
static void add_entropy(text *data1, text *data2, text *data3) static void
add_entropy(text *data1, text *data2, text *data3)
{ {
PX_MD *md; PX_MD *md;
uint8 rnd[3]; uint8 rnd[3];
@ -123,8 +125,8 @@ static void add_entropy(text *data1, text *data2, text *data3)
/* /*
* Try to make the feeding unpredictable. * Try to make the feeding unpredictable.
* *
* Prefer data over keys, as it's rather likely * Prefer data over keys, as it's rather likely that key is same in several
* that key is same in several calls. * calls.
*/ */
/* chance: 7/8 */ /* chance: 7/8 */
@ -146,7 +148,8 @@ static void add_entropy(text *data1, text *data2, text *data3)
/* /*
* returns src in case of no conversion or error * returns src in case of no conversion or error
*/ */
static text *convert_charset(text *src, int cset_from, int cset_to) static text *
convert_charset(text *src, int cset_from, int cset_to)
{ {
int src_len = VARSIZE(src) - VARHDRSZ; int src_len = VARSIZE(src) - VARHDRSZ;
int dst_len; int dst_len;
@ -166,12 +169,14 @@ static text *convert_charset(text *src, int cset_from, int cset_to)
return res; return res;
} }
static text *convert_from_utf8(text *src) static text *
convert_from_utf8(text *src)
{ {
return convert_charset(src, PG_UTF8, GetDatabaseEncoding()); return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
} }
static text *convert_to_utf8(text *src) static text *
convert_to_utf8(text *src)
{ {
return convert_charset(src, GetDatabaseEncoding(), PG_UTF8); return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
} }
@ -186,7 +191,8 @@ clear_and_pfree(text *p)
/* /*
* expect-* arguments storage * expect-* arguments storage
*/ */
struct debug_expect { struct debug_expect
{
int debug; int debug;
int expect; int expect;
int cipher_algo; int cipher_algo;
@ -199,7 +205,8 @@ struct debug_expect {
int unicode_mode; int unicode_mode;
}; };
static void fill_expect(struct debug_expect *ex, int text_mode) static void
fill_expect(struct debug_expect * ex, int text_mode)
{ {
ex->debug = 0; ex->debug = 0;
ex->expect = 0; ex->expect = 0;
@ -222,7 +229,8 @@ static void fill_expect(struct debug_expect *ex, int text_mode)
if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \ if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
} while (0) } while (0)
static void check_expect(PGP_Context *ctx, struct debug_expect *ex) static void
check_expect(PGP_Context * ctx, struct debug_expect * ex)
{ {
EX_CHECK(cipher_algo); EX_CHECK(cipher_algo);
EX_CHECK(s2k_mode); EX_CHECK(s2k_mode);
@ -235,15 +243,18 @@ static void check_expect(PGP_Context *ctx, struct debug_expect *ex)
EX_CHECK(unicode_mode); EX_CHECK(unicode_mode);
} }
static void show_debug(const char *msg) static void
show_debug(const char *msg)
{ {
ereport(NOTICE, (errmsg("dbg: %s", msg))); ereport(NOTICE, (errmsg("dbg: %s", msg)));
} }
static int set_arg(PGP_Context *ctx, char *key, char*val, static int
set_arg(PGP_Context * ctx, char *key, char *val,
struct debug_expect * ex) struct debug_expect * ex)
{ {
int res = 0; int res = 0;
if (strcmp(key, "cipher-algo") == 0) if (strcmp(key, "cipher-algo") == 0)
res = pgp_set_cipher_algo(ctx, val); res = pgp_set_cipher_algo(ctx, val);
else if (strcmp(key, "disable-mdc") == 0) else if (strcmp(key, "disable-mdc") == 0)
@ -318,7 +329,8 @@ static int set_arg(PGP_Context *ctx, char *key, char*val,
* Put word info into res_p, res_len. * Put word info into res_p, res_len.
* Returns ptr to next word. * Returns ptr to next word.
*/ */
static char *getword(char *p, char **res_p, int *res_len) static char *
getword(char *p, char **res_p, int *res_len)
{ {
/* whitespace at start */ /* whitespace at start */
while (*p && (*p == ' ' || *p == '\t' || *p == '\n')) while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
@ -346,11 +358,15 @@ static char *getword(char *p, char **res_p, int *res_len)
/* /*
* Convert to lowercase asciiz string. * Convert to lowercase asciiz string.
*/ */
static char *downcase_convert(const uint8 *s, int len) static char *
downcase_convert(const uint8 *s, int len)
{ {
int c, i; int c,
i;
char *res = palloc(len + 1); char *res = palloc(len + 1);
for (i = 0; i < len; i++) {
for (i = 0; i < len; i++)
{
c = s[i]; c = s[i];
if (c >= 'A' && c <= 'Z') if (c >= 'A' && c <= 'Z')
c += 'a' - 'A'; c += 'a' - 'A';
@ -360,12 +376,15 @@ static char *downcase_convert(const uint8 *s, int len)
return res; return res;
} }
static int parse_args(PGP_Context *ctx, uint8 *args, int arg_len, static int
parse_args(PGP_Context * ctx, uint8 *args, int arg_len,
struct debug_expect * ex) struct debug_expect * ex)
{ {
char *str = downcase_convert(args, arg_len); char *str = downcase_convert(args, arg_len);
char *key, *val; char *key,
int key_len, val_len; *val;
int key_len,
val_len;
int res = 0; int res = 0;
char *p = str; char *p = str;
@ -431,7 +450,8 @@ static bytea *
encrypt_internal(int is_pubenc, int is_text, encrypt_internal(int is_pubenc, int is_text,
text *data, text *key, text *args) text *data, text *key, text *args)
{ {
MBuf *src, *dst; MBuf *src,
*dst;
uint8 tmp[VARHDRSZ]; uint8 tmp[VARHDRSZ];
uint8 *restmp; uint8 *restmp;
bytea *res; bytea *res;
@ -471,6 +491,7 @@ encrypt_internal(int is_pubenc, int is_text,
if (is_pubenc) if (is_pubenc)
{ {
MBuf *kbuf = create_mbuf_from_vardata(key); MBuf *kbuf = create_mbuf_from_vardata(key);
err = pgp_set_pubkey(ctx, kbuf, err = pgp_set_pubkey(ctx, kbuf,
NULL, 0, 0); NULL, 0, 0);
mbuf_free(kbuf); mbuf_free(kbuf);
@ -523,7 +544,8 @@ decrypt_internal(int is_pubenc, int need_text, text *data,
text *key, text *keypsw, text *args) text *key, text *keypsw, text *args)
{ {
int err; int err;
MBuf *src = NULL, *dst = NULL; MBuf *src = NULL,
*dst = NULL;
uint8 tmp[VARHDRSZ]; uint8 tmp[VARHDRSZ];
uint8 *restmp; uint8 *restmp;
bytea *res; bytea *res;
@ -552,6 +574,7 @@ decrypt_internal(int is_pubenc, int need_text, text *data,
uint8 *psw = NULL; uint8 *psw = NULL;
int psw_len = 0; int psw_len = 0;
MBuf *kbuf; MBuf *kbuf;
if (keypsw) if (keypsw)
{ {
psw = (uint8 *) VARDATA(keypsw); psw = (uint8 *) VARDATA(keypsw);
@ -609,6 +632,7 @@ out:
if (need_text && got_unicode) if (need_text && got_unicode)
{ {
text *utf = convert_from_utf8(res); text *utf = convert_from_utf8(res);
if (utf != res) if (utf != res)
{ {
clear_and_pfree(res); clear_and_pfree(res);
@ -927,4 +951,3 @@ pgp_key_id_w(PG_FUNCTION_ARGS)
PG_FREE_IF_COPY(data, 0); PG_FREE_IF_COPY(data, 0);
PG_RETURN_TEXT_P(res); PG_RETURN_TEXT_P(res);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.4 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.5 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -52,7 +52,8 @@ check_eme_pkcs1_v15(uint8 *data, int len)
if (*p++ != 2) if (*p++ != 2)
return NULL; return NULL;
while (p < data_end && *p) { while (p < data_end && *p)
{
p++; p++;
rnd++; rnd++;
} }
@ -74,7 +75,8 @@ static int
control_cksum(uint8 *msg, int msglen) control_cksum(uint8 *msg, int msglen)
{ {
int i; int i;
unsigned my_cksum, got_cksum; unsigned my_cksum,
got_cksum;
if (msglen < 3) if (msglen < 3)
return PXE_PGP_WRONG_KEY; return PXE_PGP_WRONG_KEY;
@ -84,7 +86,8 @@ control_cksum(uint8 *msg, int msglen)
my_cksum += msg[i]; my_cksum += msg[i];
my_cksum &= 0xFFFF; my_cksum &= 0xFFFF;
got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1]; got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
if (my_cksum != got_cksum) { if (my_cksum != got_cksum)
{
px_debug("pubenc cksum failed"); px_debug("pubenc cksum failed");
return PXE_PGP_WRONG_KEY; return PXE_PGP_WRONG_KEY;
} }
@ -157,13 +160,15 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
PGP_MPI *m; PGP_MPI *m;
pk = ctx->pub_key; pk = ctx->pub_key;
if (pk == NULL) { if (pk == NULL)
{
px_debug("no pubkey?"); px_debug("no pubkey?");
return PXE_BUG; return PXE_BUG;
} }
GETBYTE(pkt, ver); GETBYTE(pkt, ver);
if (ver != 3) { if (ver != 3)
{
px_debug("unknown pubenc_sesskey pkt ver=%d", ver); px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
return PXE_PGP_CORRUPT_DATA; return PXE_PGP_CORRUPT_DATA;
} }
@ -204,7 +209,8 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
* extract message * extract message
*/ */
msg = check_eme_pkcs1_v15(m->data, m->bytes); msg = check_eme_pkcs1_v15(m->data, m->bytes);
if (msg == NULL) { if (msg == NULL)
{
px_debug("check_eme_pkcs1_v15 failed"); px_debug("check_eme_pkcs1_v15 failed");
res = PXE_PGP_WRONG_KEY; res = PXE_PGP_WRONG_KEY;
goto out; goto out;
@ -228,5 +234,3 @@ out:
return res; return res;
return pgp_expect_packet_end(pkt); return pgp_expect_packet_end(pkt);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -41,7 +41,8 @@ static int
pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p) pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
{ {
int res; int res;
uint8 *buf, *p; uint8 *buf,
*p;
int pad_len = res_len - 2 - data_len; int pad_len = res_len - 2 - data_len;
if (pad_len < 8) if (pad_len < 8)
@ -88,7 +89,8 @@ static int
create_secmsg(PGP_Context * ctx, PGP_MPI ** msg_p, int full_bytes) create_secmsg(PGP_Context * ctx, PGP_MPI ** msg_p, int full_bytes)
{ {
uint8 *secmsg; uint8 *secmsg;
int res, i; int res,
i;
unsigned cksum = 0; unsigned cksum = 0;
int klen = ctx->sess_key_len; int klen = ctx->sess_key_len;
uint8 *padded = NULL; uint8 *padded = NULL;
@ -115,6 +117,7 @@ create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
{ {
/* first byte will be 0x02 */ /* first byte will be 0x02 */
int full_bits = full_bytes * 8 - 6; int full_bits = full_bytes * 8 - 6;
res = pgp_mpi_create(padded, full_bits, &m); res = pgp_mpi_create(padded, full_bits, &m);
} }
@ -136,7 +139,9 @@ static int
encrypt_and_write_elgamal(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt) encrypt_and_write_elgamal(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt)
{ {
int res; int res;
PGP_MPI *m = NULL, *c1 = NULL, *c2 = NULL; PGP_MPI *m = NULL,
*c1 = NULL,
*c2 = NULL;
/* create padded msg */ /* create padded msg */
res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1); res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
@ -165,7 +170,8 @@ static int
encrypt_and_write_rsa(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt) encrypt_and_write_rsa(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt)
{ {
int res; int res;
PGP_MPI *m = NULL, *c = NULL; PGP_MPI *m = NULL,
*c = NULL;
/* create padded msg */ /* create padded msg */
res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1); res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
@ -186,7 +192,8 @@ err:
return res; return res;
} }
int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst) int
pgp_write_pubenc_sesskey(PGP_Context * ctx, PushFilter * dst)
{ {
int res; int res;
PGP_PubKey *pk = ctx->pub_key; PGP_PubKey *pk = ctx->pub_key;
@ -194,7 +201,8 @@ int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
PushFilter *pkt = NULL; PushFilter *pkt = NULL;
uint8 algo = pk->algo; uint8 algo = pk->algo;
if (pk == NULL) { if (pk == NULL)
{
px_debug("no pubkey?\n"); px_debug("no pubkey?\n");
return PXE_BUG; return PXE_BUG;
} }
@ -238,5 +246,3 @@ err:
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -34,16 +34,19 @@
#include "mbuf.h" #include "mbuf.h"
#include "pgp.h" #include "pgp.h"
int pgp_key_alloc(PGP_PubKey **pk_p) int
pgp_key_alloc(PGP_PubKey ** pk_p)
{ {
PGP_PubKey *pk; PGP_PubKey *pk;
pk = px_alloc(sizeof(*pk)); pk = px_alloc(sizeof(*pk));
memset(pk, 0, sizeof(*pk)); memset(pk, 0, sizeof(*pk));
*pk_p = pk; *pk_p = pk;
return 0; return 0;
} }
void pgp_key_free(PGP_PubKey *pk) void
pgp_key_free(PGP_PubKey * pk)
{ {
if (pk == NULL) if (pk == NULL)
return; return;
@ -152,7 +155,8 @@ calc_key_id(PGP_PubKey *pk)
return 0; return 0;
} }
int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p) int
_pgp_read_public_key(PullFilter * pkt, PGP_PubKey ** pk_p)
{ {
int res; int res;
PGP_PubKey *pk; PGP_PubKey *pk;
@ -163,7 +167,8 @@ int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
/* get version */ /* get version */
GETBYTE(pkt, pk->ver); GETBYTE(pkt, pk->ver);
if (pk->ver != 4) { if (pk->ver != 4)
{
res = PXE_PGP_NOT_V4_KEYPKT; res = PXE_PGP_NOT_V4_KEYPKT;
goto out; goto out;
} }
@ -176,16 +181,21 @@ int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
/* pubkey algorithm */ /* pubkey algorithm */
GETBYTE(pkt, pk->algo); GETBYTE(pkt, pk->algo);
switch (pk->algo) { switch (pk->algo)
{
case PGP_PUB_DSA_SIGN: case PGP_PUB_DSA_SIGN:
res = pgp_mpi_read(pkt, &pk->pub.dsa.p); res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.dsa.q); res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.dsa.g); res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.dsa.y); res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
if (res < 0) break; if (res < 0)
break;
res = calc_key_id(pk); res = calc_key_id(pk);
break; break;
@ -194,9 +204,11 @@ int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT:
case PGP_PUB_RSA_ENCRYPT_SIGN: case PGP_PUB_RSA_ENCRYPT_SIGN:
res = pgp_mpi_read(pkt, &pk->pub.rsa.n); res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.rsa.e); res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
if (res < 0) break; if (res < 0)
break;
res = calc_key_id(pk); res = calc_key_id(pk);
@ -206,11 +218,14 @@ int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
case PGP_PUB_ELG_ENCRYPT: case PGP_PUB_ELG_ENCRYPT:
res = pgp_mpi_read(pkt, &pk->pub.elg.p); res = pgp_mpi_read(pkt, &pk->pub.elg.p);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.elg.g); res = pgp_mpi_read(pkt, &pk->pub.elg.g);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->pub.elg.y); res = pgp_mpi_read(pkt, &pk->pub.elg.y);
if (res < 0) break; if (res < 0)
break;
res = calc_key_id(pk); res = calc_key_id(pk);
@ -285,7 +300,8 @@ static int
check_key_cksum(PullFilter * src, PGP_PubKey * pk) check_key_cksum(PullFilter * src, PGP_PubKey * pk)
{ {
int res; int res;
unsigned got_cksum, my_cksum = 0; unsigned got_cksum,
my_cksum = 0;
uint8 buf[2]; uint8 buf[2];
res = pullf_read_fixed(src, 2, buf); res = pullf_read_fixed(src, 2, buf);
@ -318,7 +334,8 @@ check_key_cksum(PullFilter *src, PGP_PubKey *pk)
return 0; return 0;
} }
static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p, static int
process_secret_key(PullFilter * pkt, PGP_PubKey ** pk_p,
const uint8 *key, int key_len) const uint8 *key, int key_len)
{ {
int res; int res;
@ -326,7 +343,8 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
int cipher_algo; int cipher_algo;
int bs; int bs;
uint8 iv[512]; uint8 iv[512];
PullFilter *pf_decrypt = NULL, *pf_key; PullFilter *pf_decrypt = NULL,
*pf_key;
PGP_CFB *cfb = NULL; PGP_CFB *cfb = NULL;
PGP_S2K s2k; PGP_S2K s2k;
PGP_PubKey *pk; PGP_PubKey *pk;
@ -340,7 +358,8 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
* is secret key encrypted? * is secret key encrypted?
*/ */
GETBYTE(pkt, hide_type); GETBYTE(pkt, hide_type);
if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM) { if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
{
if (key == NULL) if (key == NULL)
return PXE_PGP_NEED_SECRET_PSW; return PXE_PGP_NEED_SECRET_PSW;
GETBYTE(pkt, cipher_algo); GETBYTE(pkt, cipher_algo);
@ -353,13 +372,15 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
return res; return res;
bs = pgp_get_cipher_block_size(cipher_algo); bs = pgp_get_cipher_block_size(cipher_algo);
if (bs == 0) { if (bs == 0)
{
px_debug("unknown cipher algo=%d", cipher_algo); px_debug("unknown cipher algo=%d", cipher_algo);
return PXE_PGP_UNSUPPORTED_CIPHER; return PXE_PGP_UNSUPPORTED_CIPHER;
} }
res = pullf_read_fixed(pkt, bs, iv); res = pullf_read_fixed(pkt, bs, iv);
if (res < 0) if (res < 0)
return res; return res;
/* /*
* create decrypt filter * create decrypt filter
*/ */
@ -370,26 +391,35 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
if (res < 0) if (res < 0)
return res; return res;
pf_key = pf_decrypt; pf_key = pf_decrypt;
} else if (hide_type == HIDE_CLEAR) { }
else if (hide_type == HIDE_CLEAR)
{
pf_key = pkt; pf_key = pkt;
} else { }
else
{
px_debug("unknown hide type"); px_debug("unknown hide type");
return PXE_PGP_KEYPKT_CORRUPT; return PXE_PGP_KEYPKT_CORRUPT;
} }
/* read secret key */ /* read secret key */
switch (pk->algo) { switch (pk->algo)
{
case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_SIGN:
case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT:
case PGP_PUB_RSA_ENCRYPT_SIGN: case PGP_PUB_RSA_ENCRYPT_SIGN:
res = pgp_mpi_read(pkt, &pk->sec.rsa.d); res = pgp_mpi_read(pkt, &pk->sec.rsa.d);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->sec.rsa.p); res = pgp_mpi_read(pkt, &pk->sec.rsa.p);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->sec.rsa.q); res = pgp_mpi_read(pkt, &pk->sec.rsa.q);
if (res < 0) break; if (res < 0)
break;
res = pgp_mpi_read(pkt, &pk->sec.rsa.u); res = pgp_mpi_read(pkt, &pk->sec.rsa.u);
if (res < 0) break; if (res < 0)
break;
break; break;
case PGP_PUB_ELG_ENCRYPT: case PGP_PUB_ELG_ENCRYPT:
res = pgp_mpi_read(pf_key, &pk->sec.elg.x); res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
@ -442,7 +472,8 @@ internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
* *
* Error out on anything fancy. * Error out on anything fancy.
*/ */
while (1) { while (1)
{
res = pgp_parse_pkt_hdr(src, &tag, &len, 0); res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
if (res <= 0) if (res <= 0)
break; break;
@ -450,7 +481,8 @@ internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
if (res < 0) if (res < 0)
break; break;
switch (tag) { switch (tag)
{
case PGP_PKT_PUBLIC_KEY: case PGP_PKT_PUBLIC_KEY:
case PGP_PKT_SECRET_KEY: case PGP_PKT_SECRET_KEY:
if (got_main_key) if (got_main_key)
@ -550,4 +582,3 @@ pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
return res < 0 ? res : 0; return res < 0 ? res : 0;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-s2k.c,v 1.3 2005/07/18 17:12:54 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-s2k.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -221,7 +221,8 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode,int digest_algo)
s2k->mode = mode; s2k->mode = mode;
s2k->digest_algo = digest_algo; s2k->digest_algo = digest_algo;
switch (s2k->mode) { switch (s2k->mode)
{
case 0: case 0:
break; break;
case 1: case 1:
@ -249,7 +250,8 @@ pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
GETBYTE(src, s2k->mode); GETBYTE(src, s2k->mode);
GETBYTE(src, s2k->digest_algo); GETBYTE(src, s2k->digest_algo);
switch (s2k->mode) { switch (s2k->mode)
{
case 0: case 0:
break; break;
case 1: case 1:
@ -267,7 +269,8 @@ pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
return res; return res;
} }
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len) int
pgp_s2k_process(PGP_S2K * s2k, int cipher, const uint8 *key, int key_len)
{ {
int res; int res;
PX_MD *md; PX_MD *md;
@ -280,7 +283,8 @@ int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
if (res < 0) if (res < 0)
return res; return res;
switch (s2k->mode) { switch (s2k->mode)
{
case 0: case 0:
res = calc_s2k_simple(s2k, md, key, key_len); res = calc_s2k_simple(s2k, md, key, key_len);
break; break;
@ -296,4 +300,3 @@ int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
px_md_free(md); px_md_free(md);
return res; return res;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp.c,v 1.2 2005/07/11 15:07:59 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -94,6 +94,7 @@ static const struct cipher_info *
get_cipher_info(int code) get_cipher_info(int code)
{ {
const struct cipher_info *i; const struct cipher_info *i;
for (i = cipher_list; i->name; i++) for (i = cipher_list; i->name; i++)
if (i->code == code) if (i->code == code)
return i; return i;
@ -104,6 +105,7 @@ int
pgp_get_digest_code(const char *name) pgp_get_digest_code(const char *name)
{ {
const struct digest_info *i; const struct digest_info *i;
for (i = digest_list; i->name; i++) for (i = digest_list; i->name; i++)
if (pg_strcasecmp(i->name, name) == 0) if (pg_strcasecmp(i->name, name) == 0)
return i->code; return i->code;
@ -114,6 +116,7 @@ int
pgp_get_cipher_code(const char *name) pgp_get_cipher_code(const char *name)
{ {
const struct cipher_info *i; const struct cipher_info *i;
for (i = cipher_list; i->name; i++) for (i = cipher_list; i->name; i++)
if (pg_strcasecmp(i->name, name) == 0) if (pg_strcasecmp(i->name, name) == 0)
return i->code; return i->code;
@ -124,6 +127,7 @@ const char *
pgp_get_digest_name(int code) pgp_get_digest_name(int code)
{ {
const struct digest_info *i; const struct digest_info *i;
for (i = digest_list; i->name; i++) for (i = digest_list; i->name; i++)
if (i->code == code) if (i->code == code)
return i->name; return i->name;
@ -134,6 +138,7 @@ const char *
pgp_get_cipher_name(int code) pgp_get_cipher_name(int code)
{ {
const struct cipher_info *i = get_cipher_info(code); const struct cipher_info *i = get_cipher_info(code);
if (i != NULL) if (i != NULL)
return i->name; return i->name;
return NULL; return NULL;
@ -143,6 +148,7 @@ int
pgp_get_cipher_key_size(int code) pgp_get_cipher_key_size(int code)
{ {
const struct cipher_info *i = get_cipher_info(code); const struct cipher_info *i = get_cipher_info(code);
if (i != NULL) if (i != NULL)
return i->key_len; return i->key_len;
return 0; return 0;
@ -152,6 +158,7 @@ int
pgp_get_cipher_block_size(int code) pgp_get_cipher_block_size(int code)
{ {
const struct cipher_info *i = get_cipher_info(code); const struct cipher_info *i = get_cipher_info(code);
if (i != NULL) if (i != NULL)
return i->block_len; return i->block_len;
return 0; return 0;
@ -300,6 +307,7 @@ int
pgp_set_cipher_algo(PGP_Context * ctx, const char *name) pgp_set_cipher_algo(PGP_Context * ctx, const char *name)
{ {
int code = pgp_get_cipher_code(name); int code = pgp_get_cipher_code(name);
if (code < 0) if (code < 0)
return code; return code;
ctx->cipher_algo = code; ctx->cipher_algo = code;
@ -310,6 +318,7 @@ int
pgp_set_s2k_cipher_algo(PGP_Context * ctx, const char *name) pgp_set_s2k_cipher_algo(PGP_Context * ctx, const char *name)
{ {
int code = pgp_get_cipher_code(name); int code = pgp_get_cipher_code(name);
if (code < 0) if (code < 0)
return code; return code;
ctx->s2k_cipher_algo = code; ctx->s2k_cipher_algo = code;
@ -320,6 +329,7 @@ int
pgp_set_s2k_digest_algo(PGP_Context * ctx, const char *name) pgp_set_s2k_digest_algo(PGP_Context * ctx, const char *name)
{ {
int code = pgp_get_digest_code(name); int code = pgp_get_digest_code(name);
if (code < 0) if (code < 0)
return code; return code;
ctx->s2k_digest_algo = code; ctx->s2k_digest_algo = code;
@ -348,4 +358,3 @@ pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len)
ctx->sym_key_len = len; ctx->sym_key_len = len;
return 0; return 0;
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp.h,v 1.3 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.h,v 1.4 2005/10/15 02:49:06 momjian Exp $
*/ */
enum enum
@ -114,7 +114,8 @@ typedef struct PGP_PubKey PGP_PubKey;
typedef struct PGP_Context PGP_Context; typedef struct PGP_Context PGP_Context;
typedef struct PGP_S2K PGP_S2K; typedef struct PGP_S2K PGP_S2K;
struct PGP_S2K { struct PGP_S2K
{
uint8 mode; uint8 mode;
uint8 digest_algo; uint8 digest_algo;
uint8 salt[8]; uint8 salt[8];
@ -163,29 +164,35 @@ struct PGP_Context
unsigned sess_key_len; unsigned sess_key_len;
}; };
struct PGP_MPI { struct PGP_MPI
{
uint8 *data; uint8 *data;
int bits; int bits;
int bytes; int bytes;
}; };
struct PGP_PubKey { struct PGP_PubKey
{
uint8 ver; uint8 ver;
uint8 time[4]; uint8 time[4];
uint8 algo; uint8 algo;
/* public part */ /* public part */
union { union
struct { {
struct
{
PGP_MPI *p; PGP_MPI *p;
PGP_MPI *g; PGP_MPI *g;
PGP_MPI *y; PGP_MPI *y;
} elg; } elg;
struct { struct
{
PGP_MPI *n; PGP_MPI *n;
PGP_MPI *e; PGP_MPI *e;
} rsa; } rsa;
struct { struct
{
PGP_MPI *p; PGP_MPI *p;
PGP_MPI *q; PGP_MPI *q;
PGP_MPI *g; PGP_MPI *g;
@ -194,17 +201,21 @@ struct PGP_PubKey {
} pub; } pub;
/* secret part */ /* secret part */
union { union
struct { {
struct
{
PGP_MPI *x; PGP_MPI *x;
} elg; } elg;
struct { struct
{
PGP_MPI *d; PGP_MPI *d;
PGP_MPI *p; PGP_MPI *p;
PGP_MPI *q; PGP_MPI *q;
PGP_MPI *u; PGP_MPI *u;
} rsa; } rsa;
struct { struct
{
PGP_MPI *x; PGP_MPI *x;
} dsa; } dsa;
} sec; } sec;
@ -254,7 +265,8 @@ int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k);
int pgp_s2k_process(PGP_S2K * s2k, int cipher, const uint8 *key, int klen); int pgp_s2k_process(PGP_S2K * s2k, int cipher, const uint8 *key, int klen);
typedef struct PGP_CFB PGP_CFB; typedef struct PGP_CFB PGP_CFB;
int pgp_cfb_create(PGP_CFB **ctx_p, int algo, int
pgp_cfb_create(PGP_CFB ** ctx_p, int algo,
const uint8 *key, int key_len, int recync, uint8 *iv); const uint8 *key, int key_len, int recync, uint8 *iv);
void pgp_cfb_free(PGP_CFB * ctx); void pgp_cfb_free(PGP_CFB * ctx);
int pgp_cfb_encrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst); int pgp_cfb_encrypt(PGP_CFB * ctx, const uint8 *data, int len, uint8 *dst);
@ -300,4 +312,3 @@ int pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *m, PGP_MPI **c);
int pgp_rsa_decrypt(PGP_PubKey * pk, PGP_MPI * c, PGP_MPI ** m); int pgp_rsa_decrypt(PGP_PubKey * pk, PGP_MPI * c, PGP_MPI ** m);
extern struct PullFilterOps pgp_decrypt_filter; extern struct PullFilterOps pgp_decrypt_filter;

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.c,v 1.14 2005/09/24 19:14:04 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.c,v 1.15 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -164,4 +164,3 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
return strlen(p); return strlen(p);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.8 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.9 2005/10/15 02:49:06 momjian Exp $
*/ */
#ifndef _PX_CRYPT_H #ifndef _PX_CRYPT_H

View File

@ -26,14 +26,15 @@
* 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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.14 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.15 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
#include "px.h" #include "px.h"
struct error_desc { struct error_desc
{
int err; int err;
const char *desc; const char *desc;
}; };
@ -91,9 +92,11 @@ static const struct error_desc px_err_list[] = {
{0, NULL}, {0, NULL},
}; };
const char *px_strerror(int err) const char *
px_strerror(int err)
{ {
const struct error_desc *e; const struct error_desc *e;
for (e = px_err_list; e->desc; e++) for (e = px_err_list; e->desc; e++)
if (e->err == err) if (e->err == err)
return e->desc; return e->desc;
@ -115,17 +118,22 @@ px_resolve_alias(const PX_Alias * list, const char *name)
static void (*debug_handler) (const char *) = NULL; static void (*debug_handler) (const char *) = NULL;
void px_set_debug_handler(void (*handler)(const char *)) void
px_set_debug_handler(void (*handler) (const char *))
{ {
debug_handler = handler; debug_handler = handler;
} }
void px_debug(const char *fmt, ...) void
px_debug(const char *fmt,...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if (debug_handler) { if (debug_handler)
{
char buf[512]; char buf[512];
vsnprintf(buf, sizeof(buf), fmt, ap); vsnprintf(buf, sizeof(buf), fmt, ap);
debug_handler(buf); debug_handler(buf);
} }

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.15 2005/08/13 02:06:20 momjian Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.16 2005/10/15 02:49:06 momjian Exp $
*/ */
#ifndef __PX_H #ifndef __PX_H
@ -208,6 +208,7 @@ const char *px_strerror(int err);
const char *px_resolve_alias(const PX_Alias * aliases, const char *name); const char *px_resolve_alias(const PX_Alias * aliases, const char *name);
void px_set_debug_handler(void (*handler) (const char *)); void px_set_debug_handler(void (*handler) (const char *));
#ifdef PX_DEBUG #ifdef PX_DEBUG
void px_debug(const char *fmt,...); void px_debug(const char *fmt,...);
#else #else

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.
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/random.c,v 1.15 2005/07/18 17:09:01 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/random.c,v 1.16 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -95,7 +95,6 @@ try_dev_random(uint8 *dst)
dst += res; dst += res;
return dst; return dst;
} }
#endif #endif
/* /*
@ -114,7 +113,8 @@ try_dev_random(uint8 *dst)
* *
* try to use Microsoft crypto API * try to use Microsoft crypto API
*/ */
static uint8 * try_win32_genrand(uint8 *dst) static uint8 *
try_win32_genrand(uint8 *dst)
{ {
int res; int res;
HCRYPTPROV h = 0; HCRYPTPROV h = 0;
@ -135,7 +135,8 @@ static uint8 * try_win32_genrand(uint8 *dst)
return dst; return dst;
} }
static uint8 * try_win32_perfc(uint8 *dst) static uint8 *
try_win32_perfc(uint8 *dst)
{ {
int res; int res;
LARGE_INTEGER time; LARGE_INTEGER time;
@ -147,7 +148,6 @@ static uint8 * try_win32_perfc(uint8 *dst)
memcpy(dst, &time, sizeof(time)); memcpy(dst, &time, sizeof(time));
return dst + sizeof(time); return dst + sizeof(time);
} }
#endif /* WIN32 */ #endif /* WIN32 */
@ -197,7 +197,8 @@ try_unix_std(uint8 *dst)
/* let's be desperate */ /* let's be desperate */
res = px_find_digest("sha1", &md); res = px_find_digest("sha1", &md);
if (res >= 0) { if (res >= 0)
{
uint8 *ptr; uint8 *ptr;
uint8 stack[8192]; uint8 stack[8192];
int alloc = 32 * 1024; int alloc = 32 * 1024;
@ -215,7 +216,6 @@ try_unix_std(uint8 *dst)
return dst; return dst;
} }
#endif #endif
/* /*
@ -223,9 +223,11 @@ try_unix_std(uint8 *dst)
* *
* dst should have room for 1024 bytes. * dst should have room for 1024 bytes.
*/ */
unsigned px_acquire_system_randomness(uint8 *dst) unsigned
px_acquire_system_randomness(uint8 *dst)
{ {
uint8 *p = dst; uint8 *p = dst;
#ifdef TRY_DEV_RANDOM #ifdef TRY_DEV_RANDOM
p = try_dev_random(p); p = try_dev_random(p);
#endif #endif
@ -240,4 +242,3 @@ unsigned px_acquire_system_randomness(uint8 *dst)
#endif #endif
return p - dst; return p - dst;
} }

View File

@ -1,6 +1,6 @@
/* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */ /* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */
/* $PostgreSQL: pgsql/contrib/pgcrypto/rijndael.c,v 1.11 2005/07/11 15:07:59 tgl Exp $ */ /* $PostgreSQL: pgsql/contrib/pgcrypto/rijndael.c,v 1.12 2005/10/15 02:49:06 momjian Exp $ */
/* This is an independent implementation of the encryption algorithm: */ /* This is an independent implementation of the encryption algorithm: */
/* */ /* */
@ -91,7 +91,6 @@ static void gen_tabs(void);
#include "rijndael.tbl" #include "rijndael.tbl"
#define tab_gen 1 #define tab_gen 1
#else /* !PRE_CALC_TABLES */ #else /* !PRE_CALC_TABLES */
static u1byte pow_tab[256]; static u1byte pow_tab[256];
@ -143,7 +142,6 @@ static u4byte tab_gen = 0;
il_tab[1][byte((bi)[((n) + 3) & 3],1)] ^ \ il_tab[1][byte((bi)[((n) + 3) & 3],1)] ^ \
il_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \ il_tab[2][byte((bi)[((n) + 2) & 3],2)] ^ \
il_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n)) il_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n))
#else #else
#define ls_box(x) \ #define ls_box(x) \

View File

@ -33,7 +33,7 @@
* *
* $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
* *
* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.c,v 1.4 2005/07/12 20:27:42 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgcrypto/sha2.c,v 1.5 2005/10/15 02:49:06 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -310,8 +310,18 @@ SHA256_Init(SHA256_CTX *context)
void void
SHA256_Transform(SHA256_CTX * context, const uint8 *data) SHA256_Transform(SHA256_CTX * context, const uint8 *data)
{ {
uint32 a, b, c, d, e, f, g, h, s0, s1; uint32 a,
uint32 T1, *W256; b,
c,
d,
e,
f,
g,
h,
s0,
s1;
uint32 T1,
*W256;
int j; int j;
W256 = (uint32 *) context->buffer; W256 = (uint32 *) context->buffer;
@ -327,7 +337,8 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
h = context->state[7]; h = context->state[7];
j = 0; j = 0;
do { do
{
/* Rounds 0 to 15 (unrolled): */ /* Rounds 0 to 15 (unrolled): */
ROUND256_0_TO_15(a, b, c, d, e, f, g, h); ROUND256_0_TO_15(a, b, c, d, e, f, g, h);
ROUND256_0_TO_15(h, a, b, c, d, e, f, g); ROUND256_0_TO_15(h, a, b, c, d, e, f, g);
@ -340,7 +351,8 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
} while (j < 16); } while (j < 16);
/* Now for the remaining rounds to 64: */ /* Now for the remaining rounds to 64: */
do { do
{
ROUND256(a, b, c, d, e, f, g, h); ROUND256(a, b, c, d, e, f, g, h);
ROUND256(h, a, b, c, d, e, f, g); ROUND256(h, a, b, c, d, e, f, g);
ROUND256(g, h, a, b, c, d, e, f); ROUND256(g, h, a, b, c, d, e, f);
@ -364,14 +376,24 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
/* Clean up */ /* Clean up */
a = b = c = d = e = f = g = h = T1 = 0; a = b = c = d = e = f = g = h = T1 = 0;
} }
#else /* SHA2_UNROLL_TRANSFORM */ #else /* SHA2_UNROLL_TRANSFORM */
void void
SHA256_Transform(SHA256_CTX * context, const uint8 *data) SHA256_Transform(SHA256_CTX * context, const uint8 *data)
{ {
uint32 a, b, c, d, e, f, g, h, s0, s1; uint32 a,
uint32 T1, T2, *W256; b,
c,
d,
e,
f,
g,
h,
s0,
s1;
uint32 T1,
T2,
*W256;
int j; int j;
W256 = (uint32 *) context->buffer; W256 = (uint32 *) context->buffer;
@ -387,7 +409,8 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
h = context->state[7]; h = context->state[7];
j = 0; j = 0;
do { do
{
W256[j] = (uint32) data[3] | ((uint32) data[2] << 8) | W256[j] = (uint32) data[3] | ((uint32) data[2] << 8) |
((uint32) data[1] << 16) | ((uint32) data[0] << 24); ((uint32) data[1] << 16) | ((uint32) data[0] << 24);
data += 4; data += 4;
@ -406,7 +429,8 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
j++; j++;
} while (j < 16); } while (j < 16);
do { do
{
/* Part of the message block expansion: */ /* Part of the message block expansion: */
s0 = W256[(j + 1) & 0x0f]; s0 = W256[(j + 1) & 0x0f];
s0 = sigma0_256(s0); s0 = sigma0_256(s0);
@ -442,31 +466,35 @@ SHA256_Transform(SHA256_CTX *context, const uint8 *data)
/* Clean up */ /* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0; a = b = c = d = e = f = g = h = T1 = T2 = 0;
} }
#endif /* SHA2_UNROLL_TRANSFORM */ #endif /* SHA2_UNROLL_TRANSFORM */
void void
SHA256_Update(SHA256_CTX * context, const uint8 *data, size_t len) SHA256_Update(SHA256_CTX * context, const uint8 *data, size_t len)
{ {
size_t freespace, usedspace; size_t freespace,
usedspace;
/* Calling with no data is valid (we do nothing) */ /* Calling with no data is valid (we do nothing) */
if (len == 0) if (len == 0)
return; return;
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) { if (usedspace > 0)
{
/* Calculate how much free space is available in the buffer */ /* Calculate how much free space is available in the buffer */
freespace = SHA256_BLOCK_LENGTH - usedspace; freespace = SHA256_BLOCK_LENGTH - usedspace;
if (len >= freespace) { if (len >= freespace)
{
/* Fill the buffer completely and process it */ /* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace); memcpy(&context->buffer[usedspace], data, freespace);
context->bitcount += freespace << 3; context->bitcount += freespace << 3;
len -= freespace; len -= freespace;
data += freespace; data += freespace;
SHA256_Transform(context, context->buffer); SHA256_Transform(context, context->buffer);
} else { }
else
{
/* The buffer is not yet full */ /* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len); memcpy(&context->buffer[usedspace], data, len);
context->bitcount += len << 3; context->bitcount += len << 3;
@ -475,14 +503,16 @@ SHA256_Update(SHA256_CTX *context, const uint8 *data, size_t len)
return; return;
} }
} }
while (len >= SHA256_BLOCK_LENGTH) { while (len >= SHA256_BLOCK_LENGTH)
{
/* Process as many complete blocks as we can */ /* Process as many complete blocks as we can */
SHA256_Transform(context, data); SHA256_Transform(context, data);
context->bitcount += SHA256_BLOCK_LENGTH << 3; context->bitcount += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH; len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH; data += SHA256_BLOCK_LENGTH;
} }
if (len > 0) { if (len > 0)
{
/* There's left-overs, so save 'em */ /* There's left-overs, so save 'em */
memcpy(context->buffer, data, len); memcpy(context->buffer, data, len);
context->bitcount += len << 3; context->bitcount += len << 3;
@ -497,21 +527,27 @@ SHA256_Final(uint8 digest[], SHA256_CTX *context)
unsigned int usedspace; unsigned int usedspace;
/* If no digest buffer is passed, we don't bother doing this: */ /* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL) { if (digest != NULL)
{
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */ /* Convert FROM host byte order */
REVERSE64(context->bitcount, context->bitcount); REVERSE64(context->bitcount, context->bitcount);
#endif #endif
if (usedspace > 0) { if (usedspace > 0)
{
/* Begin padding with a 1 bit: */ /* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80; context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { if (usedspace <= SHA256_SHORT_BLOCK_LENGTH)
{
/* Set-up for the last transform: */ /* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace);
} else { }
if (usedspace < SHA256_BLOCK_LENGTH) { else
{
if (usedspace < SHA256_BLOCK_LENGTH)
{
memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace);
} }
/* Do second-to-last transform: */ /* Do second-to-last transform: */
@ -520,7 +556,9 @@ SHA256_Final(uint8 digest[], SHA256_CTX *context)
/* And set-up for the last transform: */ /* And set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
} }
} else { }
else
{
/* Set-up for the last transform: */ /* Set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
@ -537,7 +575,9 @@ SHA256_Final(uint8 digest[], SHA256_CTX *context)
{ {
/* Convert TO host byte order */ /* Convert TO host byte order */
int j; int j;
for (j = 0; j < 8; j++) {
for (j = 0; j < 8; j++)
{
REVERSE32(context->state[j], context->state[j]); REVERSE32(context->state[j], context->state[j]);
} }
} }
@ -594,8 +634,18 @@ SHA512_Init(SHA512_CTX *context)
void void
SHA512_Transform(SHA512_CTX * context, const uint8 *data) SHA512_Transform(SHA512_CTX * context, const uint8 *data)
{ {
uint64 a, b, c, d, e, f, g, h, s0, s1; uint64 a,
uint64 T1, *W512 = (uint64 *)context->buffer; b,
c,
d,
e,
f,
g,
h,
s0,
s1;
uint64 T1,
*W512 = (uint64 *) context->buffer;
int j; int j;
/* Initialize registers with the prev. intermediate value */ /* Initialize registers with the prev. intermediate value */
@ -609,7 +659,8 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
h = context->state[7]; h = context->state[7];
j = 0; j = 0;
do { do
{
ROUND512_0_TO_15(a, b, c, d, e, f, g, h); ROUND512_0_TO_15(a, b, c, d, e, f, g, h);
ROUND512_0_TO_15(h, a, b, c, d, e, f, g); ROUND512_0_TO_15(h, a, b, c, d, e, f, g);
ROUND512_0_TO_15(g, h, a, b, c, d, e, f); ROUND512_0_TO_15(g, h, a, b, c, d, e, f);
@ -621,7 +672,8 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
} while (j < 16); } while (j < 16);
/* Now for the remaining rounds up to 79: */ /* Now for the remaining rounds up to 79: */
do { do
{
ROUND512(a, b, c, d, e, f, g, h); ROUND512(a, b, c, d, e, f, g, h);
ROUND512(h, a, b, c, d, e, f, g); ROUND512(h, a, b, c, d, e, f, g);
ROUND512(g, h, a, b, c, d, e, f); ROUND512(g, h, a, b, c, d, e, f);
@ -645,14 +697,24 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
/* Clean up */ /* Clean up */
a = b = c = d = e = f = g = h = T1 = 0; a = b = c = d = e = f = g = h = T1 = 0;
} }
#else /* SHA2_UNROLL_TRANSFORM */ #else /* SHA2_UNROLL_TRANSFORM */
void void
SHA512_Transform(SHA512_CTX * context, const uint8 *data) SHA512_Transform(SHA512_CTX * context, const uint8 *data)
{ {
uint64 a, b, c, d, e, f, g, h, s0, s1; uint64 a,
uint64 T1, T2, *W512 = (uint64 *)context->buffer; b,
c,
d,
e,
f,
g,
h,
s0,
s1;
uint64 T1,
T2,
*W512 = (uint64 *) context->buffer;
int j; int j;
/* Initialize registers with the prev. intermediate value */ /* Initialize registers with the prev. intermediate value */
@ -666,7 +728,8 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
h = context->state[7]; h = context->state[7];
j = 0; j = 0;
do { do
{
W512[j] = (uint64) data[7] | ((uint64) data[6] << 8) | W512[j] = (uint64) data[7] | ((uint64) data[6] << 8) |
((uint64) data[5] << 16) | ((uint64) data[4] << 24) | ((uint64) data[5] << 16) | ((uint64) data[4] << 24) |
((uint64) data[3] << 32) | ((uint64) data[2] << 40) | ((uint64) data[3] << 32) | ((uint64) data[2] << 40) |
@ -687,7 +750,8 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
j++; j++;
} while (j < 16); } while (j < 16);
do { do
{
/* Part of the message block expansion: */ /* Part of the message block expansion: */
s0 = W512[(j + 1) & 0x0f]; s0 = W512[(j + 1) & 0x0f];
s0 = sigma0_512(s0); s0 = sigma0_512(s0);
@ -723,31 +787,35 @@ SHA512_Transform(SHA512_CTX *context, const uint8 *data)
/* Clean up */ /* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0; a = b = c = d = e = f = g = h = T1 = T2 = 0;
} }
#endif /* SHA2_UNROLL_TRANSFORM */ #endif /* SHA2_UNROLL_TRANSFORM */
void void
SHA512_Update(SHA512_CTX * context, const uint8 *data, size_t len) SHA512_Update(SHA512_CTX * context, const uint8 *data, size_t len)
{ {
size_t freespace, usedspace; size_t freespace,
usedspace;
/* Calling with no data is valid (we do nothing) */ /* Calling with no data is valid (we do nothing) */
if (len == 0) if (len == 0)
return; return;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
if (usedspace > 0) { if (usedspace > 0)
{
/* Calculate how much free space is available in the buffer */ /* Calculate how much free space is available in the buffer */
freespace = SHA512_BLOCK_LENGTH - usedspace; freespace = SHA512_BLOCK_LENGTH - usedspace;
if (len >= freespace) { if (len >= freespace)
{
/* Fill the buffer completely and process it */ /* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace); memcpy(&context->buffer[usedspace], data, freespace);
ADDINC128(context->bitcount, freespace << 3); ADDINC128(context->bitcount, freespace << 3);
len -= freespace; len -= freespace;
data += freespace; data += freespace;
SHA512_Transform(context, context->buffer); SHA512_Transform(context, context->buffer);
} else { }
else
{
/* The buffer is not yet full */ /* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len); memcpy(&context->buffer[usedspace], data, len);
ADDINC128(context->bitcount, len << 3); ADDINC128(context->bitcount, len << 3);
@ -756,14 +824,16 @@ SHA512_Update(SHA512_CTX *context, const uint8 *data, size_t len)
return; return;
} }
} }
while (len >= SHA512_BLOCK_LENGTH) { while (len >= SHA512_BLOCK_LENGTH)
{
/* Process as many complete blocks as we can */ /* Process as many complete blocks as we can */
SHA512_Transform(context, data); SHA512_Transform(context, data);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH; len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH; data += SHA512_BLOCK_LENGTH;
} }
if (len > 0) { if (len > 0)
{
/* There's left-overs, so save 'em */ /* There's left-overs, so save 'em */
memcpy(context->buffer, data, len); memcpy(context->buffer, data, len);
ADDINC128(context->bitcount, len << 3); ADDINC128(context->bitcount, len << 3);
@ -783,15 +853,20 @@ SHA512_Last(SHA512_CTX *context)
REVERSE64(context->bitcount[0], context->bitcount[0]); REVERSE64(context->bitcount[0], context->bitcount[0]);
REVERSE64(context->bitcount[1], context->bitcount[1]); REVERSE64(context->bitcount[1], context->bitcount[1]);
#endif #endif
if (usedspace > 0) { if (usedspace > 0)
{
/* Begin padding with a 1 bit: */ /* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80; context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { if (usedspace <= SHA512_SHORT_BLOCK_LENGTH)
{
/* Set-up for the last transform: */ /* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace); memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace);
} else { }
if (usedspace < SHA512_BLOCK_LENGTH) { else
{
if (usedspace < SHA512_BLOCK_LENGTH)
{
memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace); memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace);
} }
/* Do second-to-last transform: */ /* Do second-to-last transform: */
@ -800,7 +875,9 @@ SHA512_Last(SHA512_CTX *context)
/* And set-up for the last transform: */ /* And set-up for the last transform: */
memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2); memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2);
} }
} else { }
else
{
/* Prepare for final transform: */ /* Prepare for final transform: */
memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH); memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH);
@ -819,7 +896,8 @@ void
SHA512_Final(uint8 digest[], SHA512_CTX * context) SHA512_Final(uint8 digest[], SHA512_CTX * context)
{ {
/* If no digest buffer is passed, we don't bother doing this: */ /* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL) { if (digest != NULL)
{
SHA512_Last(context); SHA512_Last(context);
/* Save the hash data for output: */ /* Save the hash data for output: */
@ -827,7 +905,9 @@ SHA512_Final(uint8 digest[], SHA512_CTX *context)
{ {
/* Convert TO host byte order */ /* Convert TO host byte order */
int j; int j;
for (j = 0; j < 8; j++) {
for (j = 0; j < 8; j++)
{
REVERSE64(context->state[j], context->state[j]); REVERSE64(context->state[j], context->state[j]);
} }
} }
@ -861,7 +941,8 @@ void
SHA384_Final(uint8 digest[], SHA384_CTX * context) SHA384_Final(uint8 digest[], SHA384_CTX * context)
{ {
/* If no digest buffer is passed, we don't bother doing this: */ /* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL) { if (digest != NULL)
{
SHA512_Last((SHA512_CTX *) context); SHA512_Last((SHA512_CTX *) context);
/* Save the hash data for output: */ /* Save the hash data for output: */
@ -869,7 +950,9 @@ SHA384_Final(uint8 digest[], SHA384_CTX *context)
{ {
/* Convert TO host byte order */ /* Convert TO host byte order */
int j; int j;
for (j = 0; j < 6; j++) {
for (j = 0; j < 6; j++)
{
REVERSE64(context->state[j], context->state[j]); REVERSE64(context->state[j], context->state[j]);
} }
} }

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.h,v 1.1 2005/07/10 13:46:29 momjian Exp $ */ /* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.h,v 1.2 2005/10/15 02:49:06 momjian Exp $ */
/* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */ /* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */
/* /*
@ -52,12 +52,14 @@
/*** SHA-256/384/512 Context Structures *******************************/ /*** SHA-256/384/512 Context Structures *******************************/
typedef struct _SHA256_CTX { typedef struct _SHA256_CTX
{
uint32 state[8]; uint32 state[8];
uint64 bitcount; uint64 bitcount;
uint8 buffer[SHA256_BLOCK_LENGTH]; uint8 buffer[SHA256_BLOCK_LENGTH];
} SHA256_CTX; } SHA256_CTX;
typedef struct _SHA512_CTX { typedef struct _SHA512_CTX
{
uint64 state[8]; uint64 state[8];
uint64 bitcount[2]; uint64 bitcount[2];
uint8 buffer[SHA512_BLOCK_LENGTH]; uint8 buffer[SHA512_BLOCK_LENGTH];

View File

@ -1,5 +1,5 @@
/* /*
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.19 2005/05/30 23:09:06 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.20 2005/10/15 02:49:06 momjian Exp $
* *
* Copyright (c) 2001,2002 Tatsuo Ishii * Copyright (c) 2001,2002 Tatsuo Ishii
* *
@ -123,8 +123,8 @@ pgstattuple_real(Relation rel, FunctionCallInfo fcinfo)
tupdesc = CreateTupleDescCopy(tupdesc); tupdesc = CreateTupleDescCopy(tupdesc);
/* /*
* Generate attribute metadata needed later to produce tuples from raw * Generate attribute metadata needed later to produce tuples from raw C
* C strings * strings
*/ */
attinmeta = TupleDescGetAttInMetadata(tupdesc); attinmeta = TupleDescGetAttInMetadata(tupdesc);
@ -197,9 +197,9 @@ pgstattuple_real(Relation rel, FunctionCallInfo fcinfo)
} }
/* /*
* Prepare a values array for constructing the tuple. This should be * Prepare a values array for constructing the tuple. This should be an
* an array of C strings which will be processed later by the * array of C strings which will be processed later by the appropriate
* appropriate "in" functions. * "in" functions.
*/ */
values = (char **) palloc(NCOLUMNS * sizeof(char *)); values = (char **) palloc(NCOLUMNS * sizeof(char *));
for (i = 0; i < NCOLUMNS; i++) for (i = 0; i < NCOLUMNS; i++)

View File

@ -124,8 +124,7 @@ seg_out(SEG * seg)
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 * indicates that this interval was built by seg_in off a single point
* point
*/ */
p += restore(p, seg->lower, seg->l_sigd); p += restore(p, seg->lower, seg->l_sigd);
} }
@ -349,8 +348,7 @@ gseg_picksplit(GistEntryVector *entryvec,
size_waste = size_union - size_inter; size_waste = size_union - size_inter;
/* /*
* are these a more promising split that what we've already * are these a more promising split that what we've already seen?
* seen?
*/ */
if (size_waste > waste || firsttime) if (size_waste > waste || firsttime)
{ {
@ -375,24 +373,24 @@ gseg_picksplit(GistEntryVector *entryvec,
rt_seg_size(datum_r, &size_r); rt_seg_size(datum_r, &size_r);
/* /*
* Now split up the regions between the two seeds. An important * Now split up the regions between the two seeds. An important property
* property of this split algorithm is that the split vector v has the * of this split algorithm is that the split vector v has the indices of
* indices of items to be split in order in its left and right * items to be split in order in its left and right vectors. We exploit
* vectors. We exploit this property by doing a merge in the code * this property by doing a merge in the code that actually splits the
* that actually splits the page. * page.
* *
* For efficiency, we also place the new index tuple in this loop. This * For efficiency, we also place the new index tuple in this loop. This is
* is handled at the very end, when we have placed all the existing * handled at the very end, when we have placed all the existing tuples
* tuples and i == maxoff + 1. * 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 put it * If we've already decided where to place this item, just put it on
* on the right list. Otherwise, we need to figure out which page * the right list. Otherwise, we need to figure out which page needs
* needs the least enlargement in order to store the item. * the least enlargement in order to store the item.
*/ */
if (i == seed_1) if (i == seed_1)
@ -742,8 +740,8 @@ seg_cmp(SEG * a, SEG * b)
* a->lower == b->lower, so consider type of boundary. * a->lower == b->lower, so consider type of boundary.
* *
* A '-' lower bound is < any other kind (this could only be relevant if * A '-' lower bound is < any other kind (this could only be relevant if
* -HUGE_VAL is used as a regular data value). A '<' lower bound is < * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any
* any other kind except '-'. A '>' lower bound is > any other kind. * other kind except '-'. A '>' lower bound is > any other kind.
*/ */
if (a->l_ext != b->l_ext) if (a->l_ext != b->l_ext)
{ {
@ -764,8 +762,7 @@ seg_cmp(SEG * a, SEG * b)
/* /*
* 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 if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */
* (b) */
return -1; return -1;
if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be
* included in (b) */ * included in (b) */
@ -800,8 +797,8 @@ seg_cmp(SEG * a, SEG * b)
* a->upper == b->upper, so consider type of boundary. * a->upper == b->upper, so consider type of boundary.
* *
* A '-' upper bound is > any other kind (this could only be relevant if * A '-' upper bound is > any other kind (this could only be relevant if
* HUGE_VAL is used as a regular data value). A '<' upper bound is < * HUGE_VAL is used as a regular data value). A '<' upper bound is < any
* any other kind. A '>' upper bound is > any other kind except '-'. * other kind. A '>' upper bound is > any other kind except '-'.
*/ */
if (a->u_ext != b->u_ext) if (a->u_ext != b->u_ext)
{ {
@ -820,11 +817,10 @@ seg_cmp(SEG * a, SEG * b)
} }
/* /*
* For other boundary types, consider # of significant digits first. * For other boundary types, consider # of significant digits first. Note
* Note result here is converse of the lower-boundary case. * result here is converse of the lower-boundary case.
*/ */
if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */
* (b) */
return 1; return 1;
if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be
* included in (b) */ * included in (b) */
@ -908,17 +904,17 @@ restore(char *result, float val, int n)
sign; sign;
/* /*
* put a cap on the number of siugnificant digits to avoid nonsense in * put a cap on the number of siugnificant digits to avoid nonsense in the
* the output * 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 efmt[5] = '0' + (n - 1) % 10; /* makes %-15.(n-1)e -- this format
* format guarantees that the * guarantees that the exponent is
* exponent is always present */ * always present */
sprintf(result, efmt, val); sprintf(result, efmt, val);
@ -940,8 +936,8 @@ restore(char *result, float val, int n)
if (Abs(exp) <= 4) if (Abs(exp) <= 4)
{ {
/* /*
* remove the decimal point from the mantyssa and write the * remove the decimal point from the mantyssa and write the digits
* digits to the buf array * to the buf array
*/ */
for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++) for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++)
{ {
@ -960,10 +956,9 @@ restore(char *result, float val, int n)
if (dp - 10 + exp >= n) if (dp - 10 + exp >= n)
{ {
/* /*
* the decimal point is behind the last significant * the decimal point is behind the last significant digit;
* digit; the digits in between must be converted to * the digits in between must be converted to the exponent
* the exponent and the decimal point placed after the * and the decimal point placed after the first digit
* first digit
*/ */
exp = dp - 10 + exp - n; exp = dp - 10 + exp - n;
buf[10 + n] = '\0'; buf[10 + n] = '\0';
@ -978,8 +973,8 @@ restore(char *result, float val, int n)
} }
/* /*
* adjust the exponent by the number of digits after * adjust the exponent by the number of digits after the
* the decimal point * decimal point
*/ */
if (n > 1) if (n > 1)
sprintf(&buf[11 + n], "e%d", exp + n - 1); sprintf(&buf[11 + n], "e%d", exp + n - 1);

View File

@ -76,9 +76,8 @@ moddatetime(PG_FUNCTION_ARGS)
Int32GetDatum(-1)); Int32GetDatum(-1));
/* /*
* This gets the position in the tuple of the field we want. args[0] * This gets the position in the tuple of the field we want. args[0] being
* being the name of the field to update, as passed in from the * the name of the field to update, as passed in from the trigger.
* trigger.
*/ */
attnum = SPI_fnumber(tupdesc, args[0]); attnum = SPI_fnumber(tupdesc, args[0]);

View File

@ -114,8 +114,8 @@ check_primary_key(PG_FUNCTION_ARGS)
kvals = (Datum *) palloc(nkeys * sizeof(Datum)); kvals = (Datum *) palloc(nkeys * sizeof(Datum));
/* /*
* Construct ident string as TriggerName $ TriggeredRelationId and try * Construct ident string as TriggerName $ TriggeredRelationId and try to
* to find prepared execution plan. * find prepared execution plan.
*/ */
snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id); snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id);
plan = find_plan(ident, &PPlans, &nPPlans); plan = find_plan(ident, &PPlans, &nPPlans);
@ -141,9 +141,9 @@ check_primary_key(PG_FUNCTION_ARGS)
kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull); kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull);
/* /*
* If it's NULL then nothing to do! DON'T FORGET call SPI_finish * If it's NULL then nothing to do! DON'T FORGET call SPI_finish ()!
* ()! DON'T FORGET return tuple! Executor inserts tuple you're * DON'T FORGET return tuple! Executor inserts tuple you're returning!
* returning! If you return NULL then nothing will be inserted! * If you return NULL then nothing will be inserted!
*/ */
if (isnull) if (isnull)
{ {
@ -164,8 +164,8 @@ check_primary_key(PG_FUNCTION_ARGS)
char sql[8192]; char sql[8192];
/* /*
* Construct query: SELECT 1 FROM _referenced_relation_ WHERE * Construct query: SELECT 1 FROM _referenced_relation_ WHERE Pkey1 =
* Pkey1 = $1 [AND Pkey2 = $2 [...]] * $1 [AND Pkey2 = $2 [...]]
*/ */
snprintf(sql, sizeof(sql), "select 1 from %s where ", relname); snprintf(sql, sizeof(sql), "select 1 from %s where ", relname);
for (i = 0; i < nkeys; i++) for (i = 0; i < nkeys; i++)
@ -181,9 +181,8 @@ check_primary_key(PG_FUNCTION_ARGS)
elog(ERROR, "check_primary_key: SPI_prepare returned %d", SPI_result); elog(ERROR, "check_primary_key: SPI_prepare returned %d", SPI_result);
/* /*
* Remember that SPI_prepare places plan in current memory context * Remember that SPI_prepare places plan in current memory context -
* - so, we have to save plan in Top memory context for latter * so, we have to save plan in Top memory context for latter use.
* use.
*/ */
pplan = SPI_saveplan(pplan); pplan = SPI_saveplan(pplan);
if (pplan == NULL) if (pplan == NULL)
@ -252,8 +251,7 @@ check_foreign_key(PG_FUNCTION_ARGS)
EPlan *plan; /* prepared plan(s) */ EPlan *plan; /* prepared plan(s) */
Oid *argtypes = NULL; /* key types to prepare execution plan */ Oid *argtypes = NULL; /* key types to prepare execution plan */
bool isnull; /* to know is some column NULL or not */ bool isnull; /* to know is some column NULL or not */
bool isequal = true; /* are keys in both tuples equal (in bool isequal = true; /* are keys in both tuples equal (in UPDATE) */
* UPDATE) */
char ident[2 * NAMEDATALEN]; /* to identify myself */ char ident[2 * NAMEDATALEN]; /* to identify myself */
int is_update = 0; int is_update = 0;
int ret; int ret;
@ -287,9 +285,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
trigtuple = trigdata->tg_trigtuple; trigtuple = trigdata->tg_trigtuple;
/* /*
* But if this is UPDATE then we have to return tg_newtuple. Also, if * But if this is UPDATE then we have to return tg_newtuple. Also, if key
* key in tg_newtuple is the same as in tg_trigtuple then nothing to * in tg_newtuple is the same as in tg_trigtuple then nothing to do.
* do.
*/ */
is_update = 0; is_update = 0;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
@ -337,8 +334,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
kvals = (Datum *) palloc(nkeys * sizeof(Datum)); kvals = (Datum *) palloc(nkeys * sizeof(Datum));
/* /*
* Construct ident string as TriggerName $ TriggeredRelationId and try * Construct ident string as TriggerName $ TriggeredRelationId and try to
* to find prepared execution plan(s). * find prepared execution plan(s).
*/ */
snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id); snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id);
plan = find_plan(ident, &FPlans, &nFPlans); plan = find_plan(ident, &FPlans, &nFPlans);
@ -372,9 +369,9 @@ check_foreign_key(PG_FUNCTION_ARGS)
kvals[i] = SPI_getbinval(trigtuple, tupdesc, fnumber, &isnull); kvals[i] = SPI_getbinval(trigtuple, tupdesc, fnumber, &isnull);
/* /*
* If it's NULL then nothing to do! DON'T FORGET call SPI_finish * If it's NULL then nothing to do! DON'T FORGET call SPI_finish ()!
* ()! DON'T FORGET return tuple! Executor inserts tuple you're * DON'T FORGET return tuple! Executor inserts tuple you're returning!
* returning! If you return NULL then nothing will be inserted! * If you return NULL then nothing will be inserted!
*/ */
if (isnull) if (isnull)
{ {
@ -383,9 +380,9 @@ check_foreign_key(PG_FUNCTION_ARGS)
} }
/* /*
* If UPDATE then get column value from new tuple being inserted * If UPDATE then get column value from new tuple being inserted and
* and compare is this the same as old one. For the moment we use * compare is this the same as old one. For the moment we use string
* string presentation of values... * presentation of values...
*/ */
if (newtuple != NULL) if (newtuple != NULL)
{ {
@ -482,8 +479,7 @@ check_foreign_key(PG_FUNCTION_ARGS)
#endif #endif
/* /*
* is_char_type =1 i set ' ' for define a new * is_char_type =1 i set ' ' for define a new value
* value
*/ */
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql),
" %s = %s%s%s %s ", " %s = %s%s%s %s ",
@ -503,8 +499,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
/* /*
* For 'S'etnull action we construct UPDATE query - UPDATE * For 'S'etnull action we construct UPDATE query - UPDATE
* _referencing_relation_ SET Fkey1 null [, Fkey2 null [...]] * _referencing_relation_ SET Fkey1 null [, Fkey2 null [...]]
* WHERE Fkey1 = $1 [AND Fkey2 = $2 [...]] - to set key * WHERE Fkey1 = $1 [AND Fkey2 = $2 [...]] - to set key columns in
* columns in all referencing tuples to NULL. * all referencing tuples to NULL.
*/ */
else if (action == 's') else if (action == 's')
{ {
@ -532,9 +528,9 @@ check_foreign_key(PG_FUNCTION_ARGS)
elog(ERROR, "check_foreign_key: SPI_prepare returned %d", SPI_result); elog(ERROR, "check_foreign_key: SPI_prepare returned %d", SPI_result);
/* /*
* Remember that SPI_prepare places plan in current memory * Remember that SPI_prepare places plan in current memory context
* context - so, we have to save plan in Top memory context * - so, we have to save plan in Top memory context for latter
* for latter use. * use.
*/ */
pplan = SPI_saveplan(pplan); pplan = SPI_saveplan(pplan);
if (pplan == NULL) if (pplan == NULL)
@ -566,8 +562,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
for (r = 0; r < nrefs; r++) for (r = 0; r < nrefs; r++)
{ {
/* /*
* For 'R'estrict we may to execute plan for one tuple only, for * For 'R'estrict we may to execute plan for one tuple only, for other
* other actions - for all tuples. * actions - for all tuples.
*/ */
int tcount = (action == 'r') ? 1 : 0; int tcount = (action == 'r') ? 1 : 0;

View File

@ -245,8 +245,8 @@ timetravel(PG_FUNCTION_ARGS)
elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_off]); elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_off]);
/* /*
* If DELETE/UPDATE of tuple with stop_date neq INFINITY then say * If DELETE/UPDATE of tuple with stop_date neq INFINITY then say upper
* upper Executor to skip operation for this tuple * Executor to skip operation for this tuple
*/ */
if (newtuple != NULL) if (newtuple != NULL)
{ /* UPDATE */ { /* UPDATE */
@ -263,8 +263,7 @@ timetravel(PG_FUNCTION_ARGS)
relname, args[a_time_on], args[a_time_off]); relname, args[a_time_on], args[a_time_off]);
} }
if (oldtimeoff != NOEND_ABSTIME) if (oldtimeoff != NOEND_ABSTIME)
{ /* current record is a deleted/updated { /* current record is a deleted/updated record */
* record */
pfree(relname); pfree(relname);
return PointerGetDatum(NULL); return PointerGetDatum(NULL);
} }
@ -285,8 +284,7 @@ timetravel(PG_FUNCTION_ARGS)
} }
/* change date column(s) */ /* change date column(s) */
cvals[attnum[a_time_off] - 1] = newtimeoff; /* stop_date eq current cvals[attnum[a_time_off] - 1] = newtimeoff; /* stop_date eq current date */
* date */
cnulls[attnum[a_time_off] - 1] = ' '; cnulls[attnum[a_time_off] - 1] = ' ';
if (!newtuple) if (!newtuple)
@ -299,8 +297,8 @@ timetravel(PG_FUNCTION_ARGS)
} }
/* /*
* Construct ident string as TriggerName $ TriggeredRelationId and try * Construct ident string as TriggerName $ TriggeredRelationId and try to
* to find prepared execution plan. * find prepared execution plan.
*/ */
snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id); snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id);
plan = find_plan(ident, &Plans, &nPlans); plan = find_plan(ident, &Plans, &nPlans);
@ -339,9 +337,8 @@ timetravel(PG_FUNCTION_ARGS)
elog(ERROR, "timetravel (%s): SPI_prepare returned %d", relname, SPI_result); elog(ERROR, "timetravel (%s): SPI_prepare returned %d", relname, SPI_result);
/* /*
* Remember that SPI_prepare places plan in current memory context * Remember that SPI_prepare places plan in current memory context -
* - so, we have to save plan in Top memory context for latter * so, we have to save plan in Top memory context for latter use.
* use.
*/ */
pplan = SPI_saveplan(pplan); pplan = SPI_saveplan(pplan);
if (pplan == NULL) if (pplan == NULL)
@ -398,8 +395,8 @@ timetravel(PG_FUNCTION_ARGS)
rettuple = SPI_modifytuple(rel, newtuple, chnattrs, chattrs, newvals, newnulls); rettuple = SPI_modifytuple(rel, newtuple, chnattrs, chattrs, newvals, newnulls);
/* /*
* SPI_copytuple allocates tmptuple in upper executor context - * SPI_copytuple allocates tmptuple in upper executor context - have
* have to free allocation using SPI_pfree * to free allocation using SPI_pfree
*/ */
/* SPI_pfree(tmptuple); */ /* SPI_pfree(tmptuple); */
} }

View File

@ -184,8 +184,7 @@ normal_rand(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT(); funcctx = SRF_FIRSTCALL_INIT();
/* /*
* switch to memory context appropriate for multiple function * switch to memory context appropriate for multiple function calls
* calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -196,10 +195,10 @@ normal_rand(PG_FUNCTION_ARGS)
fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx)); fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));
/* /*
* Use fctx to keep track of upper and lower bounds from call to * Use fctx to keep track of upper and lower bounds from call to call.
* call. It will also be used to carry over the spare value we get * It will also be used to carry over the spare value we get from the
* from the Box-Muller algorithm so that we only actually * Box-Muller algorithm so that we only actually calculate a new value
* calculate a new value every other call. * every other call.
*/ */
fctx->mean = PG_GETARG_FLOAT8(1); fctx->mean = PG_GETARG_FLOAT8(1);
fctx->stddev = PG_GETARG_FLOAT8(2); fctx->stddev = PG_GETARG_FLOAT8(2);
@ -368,8 +367,7 @@ crosstab(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT(); funcctx = SRF_FIRSTCALL_INIT();
/* /*
* switch to memory context appropriate for multiple function * switch to memory context appropriate for multiple function calls
* calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -439,8 +437,8 @@ crosstab(PG_FUNCTION_ARGS)
tupdesc = CreateTupleDescCopy(tupdesc); tupdesc = CreateTupleDescCopy(tupdesc);
/* /*
* Check that return tupdesc is compatible with the data we got * Check that return tupdesc is compatible with the data we got from
* from SPI, at least based on number and type of attributes * SPI, at least based on number and type of attributes
*/ */
if (!compatCrosstabTupleDescs(tupdesc, spi_tupdesc)) if (!compatCrosstabTupleDescs(tupdesc, spi_tupdesc))
ereport(ERROR, ereport(ERROR,
@ -449,8 +447,8 @@ crosstab(PG_FUNCTION_ARGS)
"incompatible"))); "incompatible")));
/* /*
* Generate attribute metadata needed later to produce tuples from * Generate attribute metadata needed later to produce tuples from raw
* raw C strings * C strings
*/ */
attinmeta = TupleDescGetAttInMetadata(tupdesc); attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta; funcctx->attinmeta = attinmeta;
@ -530,11 +528,10 @@ crosstab(PG_FUNCTION_ARGS)
rowid = SPI_getvalue(spi_tuple, spi_tupdesc, 1); rowid = SPI_getvalue(spi_tuple, spi_tupdesc, 1);
/* /*
* If this is the first pass through the values for this * If this is the first pass through the values for this rowid
* rowid set it, otherwise make sure it hasn't changed on * set it, otherwise make sure it hasn't changed on us. Also
* us. Also check to see if the rowid is the same as that * check to see if the rowid is the same as that of the last
* of the last tuple sent -- if so, skip this tuple * tuple sent -- if so, skip this tuple entirely
* entirely
*/ */
if (i == 0) if (i == 0)
values[0] = pstrdup(rowid); values[0] = pstrdup(rowid);
@ -550,16 +547,15 @@ crosstab(PG_FUNCTION_ARGS)
* Get the next category item value, which is alway * Get the next category item value, which is alway
* attribute number three. * attribute number three.
* *
* Be careful to sssign the value to the array index * Be careful to sssign the value to the array index based on
* based on which category we are presently * which category we are presently processing.
* processing.
*/ */
values[1 + i] = SPI_getvalue(spi_tuple, spi_tupdesc, 3); values[1 + i] = SPI_getvalue(spi_tuple, spi_tupdesc, 3);
/* /*
* increment the counter since we consume a row for * increment the counter since we consume a row for each
* each category, but not for last pass because the * category, but not for last pass because the API will do
* API will do that for us * that for us
*/ */
if (i < (num_categories - 1)) if (i < (num_categories - 1))
call_cntr = ++funcctx->call_cntr; call_cntr = ++funcctx->call_cntr;
@ -567,9 +563,9 @@ crosstab(PG_FUNCTION_ARGS)
else else
{ {
/* /*
* We'll fill in NULLs for the missing values, but we * We'll fill in NULLs for the missing values, but we need
* need to decrement the counter since this sql result * to decrement the counter since this sql result row
* row doesn't belong to the current output tuple. * doesn't belong to the current output tuple.
*/ */
call_cntr = --funcctx->call_cntr; call_cntr = --funcctx->call_cntr;
break; break;
@ -584,8 +580,8 @@ crosstab(PG_FUNCTION_ARGS)
if (values[0] != NULL) if (values[0] != NULL)
{ {
/* /*
* switch to memory context appropriate for multiple * switch to memory context appropriate for multiple function
* function calls * calls
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@ -612,8 +608,8 @@ crosstab(PG_FUNCTION_ARGS)
else else
{ {
/* /*
* Skipping this tuple entirely, but we need to advance * Skipping this tuple entirely, but we need to advance the
* the counter like the API would if we had returned one. * counter like the API would if we had returned one.
*/ */
call_cntr = ++funcctx->call_cntr; call_cntr = ++funcctx->call_cntr;
@ -730,10 +726,10 @@ crosstab_hash(PG_FUNCTION_ARGS)
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual
* tuples are in our tuplestore and passed back through * tuples are in our tuplestore and passed back through rsinfo->setResult.
* rsinfo->setResult. rsinfo->setDesc is set to the tuple description * rsinfo->setDesc is set to the tuple description that we actually used
* that we actually used to build our tuples with, so the caller can * to build our tuples with, so the caller can verify we did what it was
* verify we did what it was expecting. * expecting.
*/ */
rsinfo->setDesc = tupdesc; rsinfo->setDesc = tupdesc;
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
@ -758,8 +754,8 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
ctl.entrysize = sizeof(crosstab_HashEnt); ctl.entrysize = sizeof(crosstab_HashEnt);
/* /*
* use INIT_CATS, defined above as a guess of how many hash table * use INIT_CATS, defined above as a guess of how many hash table entries
* entries to create, initially * to create, initially
*/ */
crosstab_HashTable = hash_create("crosstab hash", INIT_CATS, &ctl, HASH_ELEM); crosstab_HashTable = hash_create("crosstab hash", INIT_CATS, &ctl, HASH_ELEM);
@ -780,8 +776,8 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
int i; int i;
/* /*
* The provided categories SQL query must always return one * The provided categories SQL query must always return one column:
* column: category - the label or identifier for each column * category - the label or identifier for each column
*/ */
if (spi_tupdesc->natts != 1) if (spi_tupdesc->natts != 1)
ereport(ERROR, ereport(ERROR,
@ -872,19 +868,17 @@ get_crosstab_tuplestore(char *sql,
} }
/* /*
* The provided SQL query must always return at least three * The provided SQL query must always return at least three columns:
* columns:
* *
* 1. rowname the label for each row - column 1 in the final result * 1. rowname the label for each row - column 1 in the final result 2.
* 2. category the label for each value-column in the final * category the label for each value-column in the final result 3.
* result 3. value the values used to populate the * value the values used to populate the value-columns
* value-columns
* *
* If there are more than three columns, the last two are taken as * If there are more than three columns, the last two are taken as
* "category" and "values". The first column is taken as * "category" and "values". The first column is taken as "rowname".
* "rowname". Additional columns (2 thru N-2) are assumed the same * Additional columns (2 thru N-2) are assumed the same for the same
* for the same "rowname", and are copied into the result tuple * "rowname", and are copied into the result tuple from the first time
* from the first time we encounter a particular rowname. * we encounter a particular rowname.
*/ */
if (ncols < 3) if (ncols < 3)
ereport(ERROR, ereport(ERROR,
@ -933,14 +927,13 @@ get_crosstab_tuplestore(char *sql,
if ((lastrowid == NULL) || (strcmp(rowid, lastrowid) != 0)) if ((lastrowid == NULL) || (strcmp(rowid, lastrowid) != 0))
{ {
/* /*
* a new row means we need to flush the old one first, * a new row means we need to flush the old one first, unless
* unless we're on the very first row * we're on the very first row
*/ */
if (lastrowid != NULL) if (lastrowid != NULL)
{ {
/* /*
* switch to appropriate context while storing the * switch to appropriate context while storing the tuple
* tuple
*/ */
SPIcontext = MemoryContextSwitchTo(per_query_ctx); SPIcontext = MemoryContextSwitchTo(per_query_ctx);
@ -1103,10 +1096,10 @@ connectby_text(PG_FUNCTION_ARGS)
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual
* tuples are in our tuplestore and passed back through * tuples are in our tuplestore and passed back through rsinfo->setResult.
* rsinfo->setResult. rsinfo->setDesc is set to the tuple description * rsinfo->setDesc is set to the tuple description that we actually used
* that we actually used to build our tuples with, so the caller can * to build our tuples with, so the caller can verify we did what it was
* verify we did what it was expecting. * expecting.
*/ */
return (Datum) 0; return (Datum) 0;
} }
@ -1182,10 +1175,10 @@ connectby_text_serial(PG_FUNCTION_ARGS)
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual
* tuples are in our tuplestore and passed back through * tuples are in our tuplestore and passed back through rsinfo->setResult.
* rsinfo->setResult. rsinfo->setDesc is set to the tuple description * rsinfo->setDesc is set to the tuple description that we actually used
* that we actually used to build our tuples with, so the caller can * to build our tuples with, so the caller can verify we did what it was
* verify we did what it was expecting. * expecting.
*/ */
return (Datum) 0; return (Datum) 0;
} }
@ -1382,8 +1375,8 @@ build_tuplestore_recursively(char *key_fld,
{ {
/* /*
* Check that return tupdesc is compatible with the one we got * Check that return tupdesc is compatible with the one we got
* from the query, but only at level 0 -- no need to check * from the query, but only at level 0 -- no need to check more
* more than once * than once
*/ */
if (!compatConnectbyTupleDescs(tupdesc, spi_tupdesc)) if (!compatConnectbyTupleDescs(tupdesc, spi_tupdesc))
@ -1605,9 +1598,9 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
"return rowid datatype."))); "return rowid datatype.")));
/* /*
* - attribute [1] of the sql tuple is the category; no need to check * - attribute [1] of the sql tuple is the category; no need to check it -
* it - attribute [2] of the sql tuple should match attributes [1] to * attribute [2] of the sql tuple should match attributes [1] to [natts]
* [natts] of the return tuple * of the return tuple
*/ */
sql_attr = sql_tupdesc->attrs[2]; sql_attr = sql_tupdesc->attrs[2];
for (i = 1; i < ret_tupdesc->natts; i++) for (i = 1; i < ret_tupdesc->natts; i++)

View File

@ -39,18 +39,14 @@ typedef struct
void parse_cfgdict(text *in, Map ** m); void parse_cfgdict(text *in, Map ** m);
/* return struct for any lexize function */ /* return struct for any lexize function */
typedef struct { typedef struct
/* number of variant of split word , for example {
Word 'fotballklubber' (norwegian) has two varian to split: /*
( fotball, klubb ) and ( fot, ball, klubb ). So, dictionary * number of variant of split word , for example Word 'fotballklubber'
should return: * (norwegian) has two varian to split: ( fotball, klubb ) and ( fot,
nvariant lexeme * ball, klubb ). So, dictionary should return: nvariant lexeme 1
1 fotball * fotball 1 klubb 2 fot 2 ball 2 klubb
1 klubb *
2 fot
2 ball
2 klubb
*/ */
uint16 nvariant; uint16 nvariant;

View File

@ -83,8 +83,10 @@ gtsvector_out(PG_FUNCTION_ARGS)
if (ISARRKEY(key)) if (ISARRKEY(key))
sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key)); sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key));
else { else
{
int cnttrue = (ISALLTRUE(key)) ? SIGLENBIT : sizebitvec(GETSIGN(key)); int cnttrue = (ISALLTRUE(key)) ? SIGLENBIT : sizebitvec(GETSIGN(key));
sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT - cnttrue); sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT - cnttrue);
} }
@ -165,8 +167,8 @@ gtsvector_compress(PG_FUNCTION_ARGS)
if (len != val->size) if (len != val->size)
{ {
/* /*
* there is a collision of hash-function; len is always less * there is a collision of hash-function; len is always less than
* than val->size * val->size
*/ */
len = CALCGTSIZE(ARRKEY, len); len = CALCGTSIZE(ARRKEY, len);
res = (GISTTYPE *) repalloc((void *) res, len); res = (GISTTYPE *) repalloc((void *) res, len);

View File

@ -10,8 +10,8 @@
*/ */
#define BITBYTE 8 #define BITBYTE 8
#define SIGLENINT 63 /* >121 => key will toast, so it will not #define SIGLENINT 63 /* >121 => key will toast, so it will not work
* work !!! */ * !!! */
#define SIGLEN ( sizeof(int4) * SIGLENINT ) #define SIGLEN ( sizeof(int4) * SIGLENINT )
#define SIGLENBIT (SIGLEN * BITBYTE) #define SIGLENBIT (SIGLEN * BITBYTE)

View File

@ -489,8 +489,8 @@ mkSPNode(IspellDict * Conf, int low, int high, int level)
if (data->isword && data->affix != Conf->Spell[i].p.d.affix) if (data->isword && data->affix != Conf->Spell[i].p.d.affix)
{ {
/* /*
* fprintf(stderr,"Word already exists: %s (affixes: * fprintf(stderr,"Word already exists: %s (affixes: '%s'
* '%s' and '%s')\n", Conf->Spell[i].word, * and '%s')\n", Conf->Spell[i].word,
* Conf->AffixData[data->affix], * Conf->AffixData[data->affix],
* Conf->AffixData[Conf->Spell[i].p.d.affix] ); * Conf->AffixData[Conf->Spell[i].p.d.affix] );
*/ */
@ -807,6 +807,7 @@ CheckAffix(const char *word, size_t len, AFFIX * Affix, char flagflags, char *ne
if (err) if (err)
{ {
char regerrstr[ERRSTRSIZE]; char regerrstr[ERRSTRSIZE];
pg_regerror(err, &(Affix->reg.regex), regerrstr, ERRSTRSIZE); pg_regerror(err, &(Affix->reg.regex), regerrstr, ERRSTRSIZE);
elog(ERROR, "Regex error in '%s': %s", Affix->mask, regerrstr); elog(ERROR, "Regex error in '%s': %s", Affix->mask, regerrstr);
} }
@ -1037,8 +1038,7 @@ SplitToVariants(IspellDict * Conf, SPNode * snode, SplitVar * orig, char *word,
while (level > startpos && (lenaff = CheckCompoundAffixes(&caff, word + level, wordlen - level)) > 0) while (level > startpos && (lenaff = CheckCompoundAffixes(&caff, word + level, wordlen - level)) > 0)
{ {
/* /*
* there is one of compound suffixes, so check word for * there is one of compound suffixes, so check word for existings
* existings
*/ */
char buf[MAXNORMLEN]; char buf[MAXNORMLEN];
char **subres; char **subres;
@ -1128,13 +1128,17 @@ TSLexeme *
NINormalizeWord(IspellDict * Conf, char *word) NINormalizeWord(IspellDict * Conf, char *word)
{ {
char **res = NormalizeSubWord(Conf, word, 0); char **res = NormalizeSubWord(Conf, word, 0);
TSLexeme *lcur=NULL, *lres=NULL; TSLexeme *lcur = NULL,
*lres = NULL;
uint16 NVariant = 1; uint16 NVariant = 1;
if (res) { if (res)
{
char **ptr = res; char **ptr = res;
lcur = lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme)); lcur = lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme));
while(*ptr) { while (*ptr)
{
lcur->lexeme = *ptr; lcur->lexeme = *ptr;
lcur->flags = 0; lcur->flags = 0;
lcur->nvariant = NVariant++; lcur->nvariant = NVariant++;
@ -1165,8 +1169,10 @@ NINormalizeWord(IspellDict * Conf, char *word)
if (!lcur) if (!lcur)
lcur = lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme)); lcur = lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme));
while(*subptr) { while (*subptr)
for(i=0;i<var->nstem-1;i++) { {
for (i = 0; i < var->nstem - 1; i++)
{
lcur->lexeme = (subptr == subres) ? var->stem[i] : pstrdup(var->stem[i]); lcur->lexeme = (subptr == subres) ? var->stem[i] : pstrdup(var->stem[i]);
lcur->flags = 0; lcur->flags = 0;
lcur->nvariant = NVariant; lcur->nvariant = NVariant;

View File

@ -265,7 +265,11 @@ pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval, int2 we
{ {
int4 count = 0; int4 count = 0;
PRSTEXT prs; PRSTEXT prs;
uint32 variant, pos, cntvar=0, cntpos=0, cnt=0; uint32 variant,
pos,
cntvar = 0,
cntpos = 0,
cnt = 0;
prs.lenwords = 32; prs.lenwords = 32;
prs.curwords = 0; prs.curwords = 0;
@ -274,16 +278,20 @@ pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval, int2 we
parsetext_v2(findcfg(state->cfg_id), &prs, strval, lenval); parsetext_v2(findcfg(state->cfg_id), &prs, strval, lenval);
if ( prs.curwords>0 ) { if (prs.curwords > 0)
{
while (count < prs.curwords) { while (count < prs.curwords)
{
pos = prs.words[count].pos.pos; pos = prs.words[count].pos.pos;
cntvar = 0; cntvar = 0;
while(count < prs.curwords && pos==prs.words[count].pos.pos) { while (count < prs.curwords && pos == prs.words[count].pos.pos)
{
variant = prs.words[count].nvariant; variant = prs.words[count].nvariant;
cnt = 0; cnt = 0;
while(count < prs.curwords && pos==prs.words[count].pos.pos && variant==prs.words[count].nvariant) { while (count < prs.curwords && pos == prs.words[count].pos.pos && variant == prs.words[count].nvariant)
{
pushval_asis(state, VAL, prs.words[count].word, prs.words[count].len, weight); pushval_asis(state, VAL, prs.words[count].word, prs.words[count].len, weight);
pfree(prs.words[count].word); pfree(prs.words[count].word);
@ -306,7 +314,8 @@ pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval, int2 we
pfree(prs.words); pfree(prs.words);
} else }
else
pushval_asis(state, VALSTOP, NULL, 0, 0); pushval_asis(state, VALSTOP, NULL, 0, 0);
} }

View File

@ -45,6 +45,7 @@ static float weights[] = {0.1, 0.2, 0.4, 1.0};
static float calc_rank_or(float *w, tsvector * t, QUERYTYPE * q); static float calc_rank_or(float *w, tsvector * t, QUERYTYPE * q);
static float calc_rank_and(float *w, tsvector * t, QUERYTYPE * q); static float calc_rank_and(float *w, tsvector * t, QUERYTYPE * q);
/* /*
* Returns a weight of a word collocation * Returns a weight of a word collocation
*/ */
@ -118,7 +119,8 @@ find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item)
static char *SortAndUniqOperand = NULL; static char *SortAndUniqOperand = NULL;
static int static int
compareITEM( const void * a, const void * b ) { compareITEM(const void *a, const void *b)
{
if ((*(ITEM **) a)->length == (*(ITEM **) b)->length) if ((*(ITEM **) a)->length == (*(ITEM **) b)->length)
return strncmp(SortAndUniqOperand + (*(ITEM **) a)->distance, return strncmp(SortAndUniqOperand + (*(ITEM **) a)->distance,
SortAndUniqOperand + (*(ITEM **) b)->distance, SortAndUniqOperand + (*(ITEM **) b)->distance,
@ -128,13 +130,18 @@ compareITEM( const void * a, const void * b ) {
} }
static ITEM ** static ITEM **
SortAndUniqItems( char *operand, ITEM *item, int *size ) { SortAndUniqItems(char *operand, ITEM * item, int *size)
ITEM **res, **ptr, **prevptr; {
ITEM **res,
**ptr,
**prevptr;
ptr = res = (ITEM **) palloc(sizeof(ITEM *) * *size); ptr = res = (ITEM **) palloc(sizeof(ITEM *) * *size);
while( (*size)-- ) { while ((*size)--)
if ( item->type == VAL ) { {
if (item->type == VAL)
{
*ptr = item; *ptr = item;
ptr++; ptr++;
} }
@ -151,8 +158,10 @@ SortAndUniqItems( char *operand, ITEM *item, int *size ) {
ptr = res + 1; ptr = res + 1;
prevptr = res; prevptr = res;
while( ptr - res < *size ) { while (ptr - res < *size)
if ( compareITEM( (void*) ptr, (void*) prevptr ) != 0 ) { {
if (compareITEM((void *) ptr, (void *) prevptr) != 0)
{
prevptr++; prevptr++;
*prevptr = *ptr; *prevptr = *ptr;
} }
@ -187,7 +196,8 @@ calc_rank_and(float *w, tsvector * t, QUERYTYPE * q)
int size = q->size; int size = q->size;
item = SortAndUniqItems(GETOPERAND(q), GETQUERY(q), &size); item = SortAndUniqItems(GETOPERAND(q), GETQUERY(q), &size);
if ( size < 2 ) { if (size < 2)
{
pfree(item); pfree(item);
return calc_rank_or(w, t, q); return calc_rank_or(w, t, q);
} }
@ -308,7 +318,8 @@ calc_rank(float *w, tsvector * t, QUERYTYPE * q, int4 method)
break; break;
case 2: case 2:
len = cnt_length(t); len = cnt_length(t);
if ( len > 0 ) res /= (float)len; if (len > 0)
res /= (float) len;
break; break;
default: default:
/* internal error */ /* internal error */
@ -500,8 +511,7 @@ Cover(DocRepresentation * doc, int len, QUERYTYPE * query, int *pos, int *p, int
if (TS_execute(GETQUERY(query), &ch, false, checkcondition_DR)) if (TS_execute(GETQUERY(query), &ch, false, checkcondition_DR))
{ {
/* /*
* elog(NOTICE,"OP:%d NP:%d P:%d Q:%d", *pos, lastpos, *p, * elog(NOTICE,"OP:%d NP:%d P:%d Q:%d", *pos, lastpos, *p, *q);
* *q);
*/ */
return true; return true;
} }
@ -615,7 +625,8 @@ rank_cd(PG_FUNCTION_ARGS)
break; break;
case 2: case 2:
len = cnt_length(txt); len = cnt_length(txt);
if ( len > 0 ) res /= (float)len; if (len > 0)
res /= (float) len;
break; break;
default: default:
/* internal error */ /* internal error */

View File

@ -2,22 +2,29 @@
#include <stdlib.h> /* for calloc, free */ #include <stdlib.h> /* for calloc, free */
#include "header.h" #include "header.h"
extern struct SN_env * SN_create_env(int S_size, int I_size, int B_size) extern struct SN_env *
SN_create_env(int S_size, int I_size, int B_size)
{ {
struct SN_env *z = (struct SN_env *) calloc(1, sizeof(struct SN_env)); struct SN_env *z = (struct SN_env *) calloc(1, sizeof(struct SN_env));
if (z == NULL) return NULL;
if (z == NULL)
return NULL;
z->p = create_s(); z->p = create_s();
if (z->p == NULL) goto error; if (z->p == NULL)
goto error;
if (S_size) if (S_size)
{ {
int i; int i;
z->S = (symbol * *) calloc(S_size, sizeof(symbol *)); z->S = (symbol * *) calloc(S_size, sizeof(symbol *));
if (z->S == NULL) goto error; if (z->S == NULL)
goto error;
for (i = 0; i < S_size; i++) for (i = 0; i < S_size; i++)
{ {
z->S[i] = create_s(); z->S[i] = create_s();
if (z->S[i] == NULL) goto error; if (z->S[i] == NULL)
goto error;
} }
z->S_size = S_size; z->S_size = S_size;
} }
@ -25,14 +32,16 @@ extern struct SN_env * SN_create_env(int S_size, int I_size, int B_size)
if (I_size) if (I_size)
{ {
z->I = (int *) calloc(I_size, sizeof(int)); z->I = (int *) calloc(I_size, sizeof(int));
if (z->I == NULL) goto error; if (z->I == NULL)
goto error;
z->I_size = I_size; z->I_size = I_size;
} }
if (B_size) if (B_size)
{ {
z->B = (symbol *) calloc(B_size, sizeof(symbol)); z->B = (symbol *) calloc(B_size, sizeof(symbol));
if (z->B == NULL) goto error; if (z->B == NULL)
goto error;
z->B_size = B_size; z->B_size = B_size;
} }
@ -42,28 +51,35 @@ error:
return NULL; return NULL;
} }
extern void SN_close_env(struct SN_env * z) extern void
SN_close_env(struct SN_env * z)
{ {
if (z == NULL) return; if (z == NULL)
return;
if (z->S_size) if (z->S_size)
{ {
int i; int i;
for (i = 0; i < z->S_size; i++) for (i = 0; i < z->S_size; i++)
{ {
lose_s(z->S[i]); lose_s(z->S[i]);
} }
free(z->S); free(z->S);
} }
if (z->I_size) free(z->I); if (z->I_size)
if (z->B_size) free(z->B); free(z->I);
if (z->p) lose_s(z->p); if (z->B_size)
free(z->B);
if (z->p)
lose_s(z->p);
free(z); free(z);
} }
extern int SN_set_current(struct SN_env * z, int size, const symbol * s) extern int
SN_set_current(struct SN_env * z, int size, const symbol * s)
{ {
int err = replace_s(z, 0, z->l, size, s, NULL); int err = replace_s(z, 0, z->l, size, s, NULL);
z->c = 0; z->c = 0;
return err; return err;
} }

View File

@ -11,10 +11,18 @@ typedef unsigned char symbol;
*/ */
struct SN_env { struct SN_env
{
symbol *p; symbol *p;
int c; int a; int l; int lb; int bra; int ket; int c;
int S_size; int I_size; int B_size; int a;
int l;
int lb;
int bra;
int ket;
int S_size;
int I_size;
int B_size;
symbol **S; symbol **S;
int *I; int *I;
symbol *B; symbol *B;
@ -24,4 +32,3 @@ extern struct SN_env * SN_create_env(int S_size, int I_size, int B_size);
extern void SN_close_env(struct SN_env * z); extern void SN_close_env(struct SN_env * z);
extern int SN_set_current(struct SN_env * z, int size, const symbol * s); extern int SN_set_current(struct SN_env * z, int size, const symbol * s);

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,8 @@
/* This file was generated automatically by the Snowball to ANSI C compiler */ /* This file was generated automatically by the Snowball to ANSI C compiler */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
extern struct SN_env *english_ISO_8859_1_create_env(void); extern struct SN_env *english_ISO_8859_1_create_env(void);
@ -12,5 +13,5 @@ extern int english_ISO_8859_1_stem(struct SN_env * z);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif
#endif

View File

@ -13,7 +13,8 @@
#define CAPACITY(p) ((int *)(p))[-2] #define CAPACITY(p) ((int *)(p))[-2]
struct among struct among
{ int s_size; /* number of chars in string */ {
int s_size; /* number of chars in string */
symbol *s; /* search string */ symbol *s; /* search string */
int substring_i; /* index to longest matching substring */ int substring_i; /* index to longest matching substring */
int result; /* result of the lookup */ int result; /* result of the lookup */
@ -55,4 +56,3 @@ extern symbol * slice_to(struct SN_env * z, symbol * p);
extern symbol *assign_to(struct SN_env * z, symbol * p); extern symbol *assign_to(struct SN_env * z, symbol * p);
extern void debug(struct SN_env * z, int number, int line_count); extern void debug(struct SN_env * z, int number, int line_count);

View File

@ -337,37 +337,53 @@ static symbol s_7[] = { 0xCE };
static symbol s_8[] = {0xCE}; static symbol s_8[] = {0xCE};
static symbol s_9[] = {0xC9}; static symbol s_9[] = {0xC9};
static int r_mark_regions(struct SN_env * z) { static int
r_mark_regions(struct SN_env * z)
{
z->I[0] = z->l; z->I[0] = z->l;
z->I[1] = z->l; z->I[1] = z->l;
{ int c = z->c; /* do, line 63 */ {
while(1) { /* gopast, line 64 */ int c = z->c; /* do, line 63 */
if (!(in_grouping(z, g_v, 192, 220))) goto lab1;
while (1)
{ /* gopast, line 64 */
if (!(in_grouping(z, g_v, 192, 220)))
goto lab1;
break; break;
lab1: lab1:
if (z->c >= z->l) goto lab0; if (z->c >= z->l)
goto lab0;
z->c++; /* gopast, line 64 */ z->c++; /* gopast, line 64 */
} }
z->I[0] = z->c; /* setmark pV, line 64 */ z->I[0] = z->c; /* setmark pV, line 64 */
while(1) { /* gopast, line 64 */ while (1)
if (!(out_grouping(z, g_v, 192, 220))) goto lab2; { /* gopast, line 64 */
if (!(out_grouping(z, g_v, 192, 220)))
goto lab2;
break; break;
lab2: lab2:
if (z->c >= z->l) goto lab0; if (z->c >= z->l)
goto lab0;
z->c++; /* gopast, line 64 */ z->c++; /* gopast, line 64 */
} }
while(1) { /* gopast, line 65 */ while (1)
if (!(in_grouping(z, g_v, 192, 220))) goto lab3; { /* gopast, line 65 */
if (!(in_grouping(z, g_v, 192, 220)))
goto lab3;
break; break;
lab3: lab3:
if (z->c >= z->l) goto lab0; if (z->c >= z->l)
goto lab0;
z->c++; /* gopast, line 65 */ z->c++; /* gopast, line 65 */
} }
while(1) { /* gopast, line 65 */ while (1)
if (!(out_grouping(z, g_v, 192, 220))) goto lab4; { /* gopast, line 65 */
if (!(out_grouping(z, g_v, 192, 220)))
goto lab4;
break; break;
lab4: lab4:
if (z->c >= z->l) goto lab0; if (z->c >= z->l)
goto lab0;
z->c++; /* gopast, line 65 */ z->c++; /* gopast, line 65 */
} }
z->I[1] = z->c; /* setmark p2, line 65 */ z->I[1] = z->c; /* setmark p2, line 65 */
@ -377,92 +393,154 @@ static int r_mark_regions(struct SN_env * z) {
return 1; return 1;
} }
static int r_R2(struct SN_env * z) { static int
if (!(z->I[1] <= z->c)) return 0; r_R2(struct SN_env * z)
{
if (!(z->I[1] <= z->c))
return 0;
return 1; return 1;
} }
static int r_perfective_gerund(struct SN_env * z) { static int
r_perfective_gerund(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 74 */ z->ket = z->c; /* [, line 74 */
among_var = find_among_b(z, a_0, 9); /* substring, line 74 */ among_var = find_among_b(z, a_0, 9); /* substring, line 74 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 74 */ z->bra = z->c; /* ], line 74 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int m = z->l - z->c; (void) m; /* or, line 78 */ {
if (!(eq_s_b(z, 1, s_0))) goto lab1; int m = z->l - z->c;
(void) m; /* or, line 78 */
if (!(eq_s_b(z, 1, s_0)))
goto lab1;
goto lab0; goto lab0;
lab1: lab1:
z->c = z->l - m; z->c = z->l - m;
if (!(eq_s_b(z, 1, s_1))) return 0; if (!(eq_s_b(z, 1, s_1)))
return 0;
} }
lab0: lab0:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 78 */ ret = slice_del(z); /* delete, line 78 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
case 2: case 2:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 85 */ ret = slice_del(z); /* delete, line 85 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_adjective(struct SN_env * z) { static int
r_adjective(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 90 */ z->ket = z->c; /* [, line 90 */
among_var = find_among_b(z, a_1, 26); /* substring, line 90 */ among_var = find_among_b(z, a_1, 26); /* substring, line 90 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 90 */ z->bra = z->c; /* ], line 90 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 99 */ ret = slice_del(z); /* delete, line 99 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_adjectival(struct SN_env * z) { static int
r_adjectival(struct SN_env * z)
{
int among_var; int among_var;
{ int ret = r_adjective(z);
if (ret == 0) return 0; /* call adjective, line 104 */ {
if (ret < 0) return ret; int ret = r_adjective(z);
if (ret == 0)
return 0; /* call adjective, line 104 */
if (ret < 0)
return ret;
} }
{ int m = z->l - z->c; (void) m; /* try, line 111 */ {
int m = z->l - z->c;
(void) m; /* try, line 111 */
z->ket = z->c; /* [, line 112 */ z->ket = z->c; /* [, line 112 */
among_var = find_among_b(z, a_2, 8); /* substring, line 112 */ among_var = find_among_b(z, a_2, 8); /* substring, line 112 */
if (!(among_var)) { z->c = z->l - m; goto lab0; } if (!(among_var))
{
z->c = z->l - m;
goto lab0;
}
z->bra = z->c; /* ], line 112 */ z->bra = z->c; /* ], line 112 */
switch(among_var) { switch (among_var)
case 0: { z->c = z->l - m; goto lab0; } {
case 0:
{
z->c = z->l - m;
goto lab0;
}
case 1: case 1:
{ int m = z->l - z->c; (void) m; /* or, line 117 */ {
if (!(eq_s_b(z, 1, s_2))) goto lab2; int m = z->l - z->c;
(void) m; /* or, line 117 */
if (!(eq_s_b(z, 1, s_2)))
goto lab2;
goto lab1; goto lab1;
lab2: lab2:
z->c = z->l - m; z->c = z->l - m;
if (!(eq_s_b(z, 1, s_3))) { z->c = z->l - m; goto lab0; } if (!(eq_s_b(z, 1, s_3)))
{
z->c = z->l - m;
goto lab0;
}
} }
lab1: lab1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 117 */ ret = slice_del(z); /* delete, line 117 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
case 2: case 2:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 124 */ ret = slice_del(z); /* delete, line 124 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
@ -472,187 +550,305 @@ static int r_adjectival(struct SN_env * z) {
return 1; return 1;
} }
static int r_reflexive(struct SN_env * z) { static int
r_reflexive(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 131 */ z->ket = z->c; /* [, line 131 */
among_var = find_among_b(z, a_3, 2); /* substring, line 131 */ among_var = find_among_b(z, a_3, 2); /* substring, line 131 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 131 */ z->bra = z->c; /* ], line 131 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 134 */ ret = slice_del(z); /* delete, line 134 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_verb(struct SN_env * z) { static int
r_verb(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 139 */ z->ket = z->c; /* [, line 139 */
among_var = find_among_b(z, a_4, 46); /* substring, line 139 */ among_var = find_among_b(z, a_4, 46); /* substring, line 139 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 139 */ z->bra = z->c; /* ], line 139 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int m = z->l - z->c; (void) m; /* or, line 145 */ {
if (!(eq_s_b(z, 1, s_4))) goto lab1; int m = z->l - z->c;
(void) m; /* or, line 145 */
if (!(eq_s_b(z, 1, s_4)))
goto lab1;
goto lab0; goto lab0;
lab1: lab1:
z->c = z->l - m; z->c = z->l - m;
if (!(eq_s_b(z, 1, s_5))) return 0; if (!(eq_s_b(z, 1, s_5)))
return 0;
} }
lab0: lab0:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 145 */ ret = slice_del(z); /* delete, line 145 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
case 2: case 2:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 153 */ ret = slice_del(z); /* delete, line 153 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_noun(struct SN_env * z) { static int
r_noun(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 162 */ z->ket = z->c; /* [, line 162 */
among_var = find_among_b(z, a_5, 36); /* substring, line 162 */ among_var = find_among_b(z, a_5, 36); /* substring, line 162 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 162 */ z->bra = z->c; /* ], line 162 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 169 */ ret = slice_del(z); /* delete, line 169 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_derivational(struct SN_env * z) { static int
r_derivational(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 178 */ z->ket = z->c; /* [, line 178 */
among_var = find_among_b(z, a_6, 2); /* substring, line 178 */ among_var = find_among_b(z, a_6, 2); /* substring, line 178 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 178 */ z->bra = z->c; /* ], line 178 */
{ int ret = r_R2(z); {
if (ret == 0) return 0; /* call R2, line 178 */ int ret = r_R2(z);
if (ret < 0) return ret;
if (ret == 0)
return 0; /* call R2, line 178 */
if (ret < 0)
return ret;
} }
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 181 */ ret = slice_del(z); /* delete, line 181 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
static int r_tidy_up(struct SN_env * z) { static int
r_tidy_up(struct SN_env * z)
{
int among_var; int among_var;
z->ket = z->c; /* [, line 186 */ z->ket = z->c; /* [, line 186 */
among_var = find_among_b(z, a_7, 4); /* substring, line 186 */ among_var = find_among_b(z, a_7, 4); /* substring, line 186 */
if (!(among_var)) return 0; if (!(among_var))
return 0;
z->bra = z->c; /* ], line 186 */ z->bra = z->c; /* ], line 186 */
switch(among_var) { switch (among_var)
case 0: return 0; {
case 0:
return 0;
case 1: case 1:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 190 */ ret = slice_del(z); /* delete, line 190 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
z->ket = z->c; /* [, line 191 */ z->ket = z->c; /* [, line 191 */
if (!(eq_s_b(z, 1, s_6))) return 0; if (!(eq_s_b(z, 1, s_6)))
return 0;
z->bra = z->c; /* ], line 191 */ z->bra = z->c; /* ], line 191 */
if (!(eq_s_b(z, 1, s_7))) return 0; if (!(eq_s_b(z, 1, s_7)))
{ int ret; return 0;
{
int ret;
ret = slice_del(z); /* delete, line 191 */ ret = slice_del(z); /* delete, line 191 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
case 2: case 2:
if (!(eq_s_b(z, 1, s_8))) return 0; if (!(eq_s_b(z, 1, s_8)))
{ int ret; return 0;
{
int ret;
ret = slice_del(z); /* delete, line 194 */ ret = slice_del(z); /* delete, line 194 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
case 3: case 3:
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 196 */ ret = slice_del(z); /* delete, line 196 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
break; break;
} }
return 1; return 1;
} }
extern int russian_KOI8_R_stem(struct SN_env * z) { extern int
{ int c = z->c; /* do, line 203 */ russian_KOI8_R_stem(struct SN_env * z)
{ int ret = r_mark_regions(z); {
if (ret == 0) goto lab0; /* call mark_regions, line 203 */ {
if (ret < 0) return ret; int c = z->c; /* do, line 203 */
{
int ret = r_mark_regions(z);
if (ret == 0)
goto lab0; /* call mark_regions, line 203 */
if (ret < 0)
return ret;
} }
lab0: lab0:
z->c = c; z->c = c;
} }
z->lb = z->c; z->c = z->l; /* backwards, line 204 */ z->lb = z->c;
z->c = z->l; /* backwards, line 204 */
{ int m3; /* setlimit, line 204 */ {
int m = z->l - z->c; (void) m; int m3; /* setlimit, line 204 */
if (z->c < z->I[0]) return 0; int m = z->l - z->c;
(void) m;
if (z->c < z->I[0])
return 0;
z->c = z->I[0]; /* tomark, line 204 */ z->c = z->I[0]; /* tomark, line 204 */
m3 = z->lb; z->lb = z->c; m3 = z->lb;
z->lb = z->c;
z->c = z->l - m; z->c = z->l - m;
{ int m = z->l - z->c; (void) m; /* do, line 205 */ {
{ int m = z->l - z->c; (void) m; /* or, line 206 */ int m = z->l - z->c;
{ int ret = r_perfective_gerund(z);
if (ret == 0) goto lab3; /* call perfective_gerund, line 206 */ (void) m; /* do, line 205 */
if (ret < 0) return ret; {
int m = z->l - z->c;
(void) m; /* or, line 206 */
{
int ret = r_perfective_gerund(z);
if (ret == 0)
goto lab3; /* call perfective_gerund, line 206 */
if (ret < 0)
return ret;
} }
goto lab2; goto lab2;
lab3: lab3:
z->c = z->l - m; z->c = z->l - m;
{ int m = z->l - z->c; (void) m; /* try, line 207 */ {
{ int ret = r_reflexive(z); int m = z->l - z->c;
if (ret == 0) { z->c = z->l - m; goto lab4; } /* call reflexive, line 207 */
if (ret < 0) return ret; (void) m; /* try, line 207 */
{
int ret = r_reflexive(z);
if (ret == 0)
{
z->c = z->l - m;
goto lab4;
} /* call reflexive, line 207 */
if (ret < 0)
return ret;
} }
lab4: lab4:
; ;
} }
{ int m = z->l - z->c; (void) m; /* or, line 208 */ {
{ int ret = r_adjectival(z); int m = z->l - z->c;
if (ret == 0) goto lab6; /* call adjectival, line 208 */
if (ret < 0) return ret; (void) m; /* or, line 208 */
{
int ret = r_adjectival(z);
if (ret == 0)
goto lab6; /* call adjectival, line 208 */
if (ret < 0)
return ret;
} }
goto lab5; goto lab5;
lab6: lab6:
z->c = z->l - m; z->c = z->l - m;
{ int ret = r_verb(z); {
if (ret == 0) goto lab7; /* call verb, line 208 */ int ret = r_verb(z);
if (ret < 0) return ret;
if (ret == 0)
goto lab7; /* call verb, line 208 */
if (ret < 0)
return ret;
} }
goto lab5; goto lab5;
lab7: lab7:
z->c = z->l - m; z->c = z->l - m;
{ int ret = r_noun(z); {
if (ret == 0) goto lab1; /* call noun, line 208 */ int ret = r_noun(z);
if (ret < 0) return ret;
if (ret == 0)
goto lab1; /* call noun, line 208 */
if (ret < 0)
return ret;
} }
} }
lab5: lab5:
@ -662,29 +858,53 @@ extern int russian_KOI8_R_stem(struct SN_env * z) {
lab1: lab1:
z->c = z->l - m; z->c = z->l - m;
} }
{ int m = z->l - z->c; (void) m; /* try, line 211 */ {
int m = z->l - z->c;
(void) m; /* try, line 211 */
z->ket = z->c; /* [, line 211 */ z->ket = z->c; /* [, line 211 */
if (!(eq_s_b(z, 1, s_9))) { z->c = z->l - m; goto lab8; } if (!(eq_s_b(z, 1, s_9)))
{
z->c = z->l - m;
goto lab8;
}
z->bra = z->c; /* ], line 211 */ z->bra = z->c; /* ], line 211 */
{ int ret; {
int ret;
ret = slice_del(z); /* delete, line 211 */ ret = slice_del(z); /* delete, line 211 */
if (ret < 0) return ret; if (ret < 0)
return ret;
} }
lab8: lab8:
; ;
} }
{ int m = z->l - z->c; (void) m; /* do, line 214 */ {
{ int ret = r_derivational(z); int m = z->l - z->c;
if (ret == 0) goto lab9; /* call derivational, line 214 */
if (ret < 0) return ret; (void) m; /* do, line 214 */
{
int ret = r_derivational(z);
if (ret == 0)
goto lab9; /* call derivational, line 214 */
if (ret < 0)
return ret;
} }
lab9: lab9:
z->c = z->l - m; z->c = z->l - m;
} }
{ int m = z->l - z->c; (void) m; /* do, line 215 */ {
{ int ret = r_tidy_up(z); int m = z->l - z->c;
if (ret == 0) goto lab10; /* call tidy_up, line 215 */
if (ret < 0) return ret; (void) m; /* do, line 215 */
{
int ret = r_tidy_up(z);
if (ret == 0)
goto lab10; /* call tidy_up, line 215 */
if (ret < 0)
return ret;
} }
lab10: lab10:
z->c = z->l - m; z->c = z->l - m;
@ -695,7 +915,12 @@ extern int russian_KOI8_R_stem(struct SN_env * z) {
return 1; return 1;
} }
extern struct SN_env * russian_KOI8_R_create_env(void) { return SN_create_env(0, 2, 0); } extern struct SN_env *russian_KOI8_R_create_env(void)
{
extern void russian_KOI8_R_close_env(struct SN_env * z) { SN_close_env(z); } return SN_create_env(0, 2, 0);
}
extern void russian_KOI8_R_close_env(struct SN_env * z)
{
SN_close_env(z);
}

View File

@ -2,7 +2,8 @@
/* This file was generated automatically by the Snowball to ANSI C compiler */ /* This file was generated automatically by the Snowball to ANSI C compiler */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
extern struct SN_env *russian_KOI8_R_create_env(void); extern struct SN_env *russian_KOI8_R_create_env(void);
@ -12,5 +13,5 @@ extern int russian_KOI8_R_stem(struct SN_env * z);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif
#endif

View File

@ -9,18 +9,25 @@
#define CREATE_SIZE 1 #define CREATE_SIZE 1
extern symbol * create_s(void) { extern symbol *
create_s(void)
{
symbol *p; symbol *p;
void *mem = malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol)); void *mem = malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol));
if (mem == NULL) return NULL;
if (mem == NULL)
return NULL;
p = (symbol *) (HEAD + (char *) mem); p = (symbol *) (HEAD + (char *) mem);
CAPACITY(p) = CREATE_SIZE; CAPACITY(p) = CREATE_SIZE;
SET_SIZE(p, CREATE_SIZE); SET_SIZE(p, CREATE_SIZE);
return p; return p;
} }
extern void lose_s(symbol * p) { extern void
if (p == NULL) return; lose_s(symbol * p)
{
if (p == NULL)
return;
free((char *) p - HEAD); free((char *) p - HEAD);
} }
@ -32,29 +39,45 @@ extern void lose_s(symbol * p) {
-- used to implement hop and next in the utf8 case. -- used to implement hop and next in the utf8 case.
*/ */
extern int skip_utf8(const symbol * p, int c, int lb, int l, int n) { extern int
skip_utf8(const symbol * p, int c, int lb, int l, int n)
{
int b; int b;
if (n >= 0) {
for (; n > 0; n--) { if (n >= 0)
if (c >= l) return -1; {
for (; n > 0; n--)
{
if (c >= l)
return -1;
b = p[c++]; b = p[c++];
if (b >= 0xC0) { /* 1100 0000 */ if (b >= 0xC0)
while (c < l) { { /* 1100 0000 */
while (c < l)
{
b = p[c]; b = p[c];
if (b >= 0xC0 || b < 0x80) break; if (b >= 0xC0 || b < 0x80)
break;
/* break unless b is 10------ */ /* break unless b is 10------ */
c++; c++;
} }
} }
} }
} else { }
for (; n < 0; n++) { else
if (c <= lb) return -1; {
for (; n < 0; n++)
{
if (c <= lb)
return -1;
b = p[--c]; b = p[--c];
if (b >= 0x80) { /* 1000 0000 */ if (b >= 0x80)
while (c > lb) { { /* 1000 0000 */
while (c > lb)
{
b = p[c]; b = p[c];
if (b >= 0xC0) break; /* 1100 0000 */ if (b >= 0xC0)
break; /* 1100 0000 */
c--; c--;
} }
} }
@ -65,124 +88,199 @@ extern int skip_utf8(const symbol * p, int c, int lb, int l, int n) {
/* Code for character groupings: utf8 cases */ /* Code for character groupings: utf8 cases */
static int get_utf8(const symbol * p, int c, int l, int * slot) { static int
int b0, b1; get_utf8(const symbol * p, int c, int l, int *slot)
if (c >= l) return 0; {
int b0,
b1;
if (c >= l)
return 0;
b0 = p[c++]; b0 = p[c++];
if (b0 < 0xC0 || c == l) { /* 1100 0000 */ if (b0 < 0xC0 || c == l)
* slot = b0; return 1; { /* 1100 0000 */
*slot = b0;
return 1;
} }
b1 = p[c++]; b1 = p[c++];
if (b0 < 0xE0 || c == l) { /* 1110 0000 */ if (b0 < 0xE0 || c == l)
* slot = (b0 & 0x1F) << 6 | (b1 & 0x3F); return 2; { /* 1110 0000 */
*slot = (b0 & 0x1F) << 6 | (b1 & 0x3F);
return 2;
} }
* slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (*p & 0x3F); return 3; *slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (*p & 0x3F);
return 3;
} }
static int get_b_utf8(const symbol * p, int c, int lb, int * slot) { static int
int b0, b1; get_b_utf8(const symbol * p, int c, int lb, int *slot)
if (c <= lb) return 0; {
int b0,
b1;
if (c <= lb)
return 0;
b0 = p[--c]; b0 = p[--c];
if (b0 < 0x80 || c == lb) { /* 1000 0000 */ if (b0 < 0x80 || c == lb)
* slot = b0; return 1; { /* 1000 0000 */
*slot = b0;
return 1;
} }
b1 = p[--c]; b1 = p[--c];
if (b1 >= 0xC0 || c == lb) { /* 1100 0000 */ if (b1 >= 0xC0 || c == lb)
* slot = (b1 & 0x1F) << 6 | (b0 & 0x3F); return 2; { /* 1100 0000 */
*slot = (b1 & 0x1F) << 6 | (b0 & 0x3F);
return 2;
} }
* slot = (*p & 0xF) << 12 | (b1 & 0x3F) << 6 | (b0 & 0x3F); return 3; *slot = (*p & 0xF) << 12 | (b1 & 0x3F) << 6 | (b0 & 0x3F);
return 3;
} }
extern int in_grouping_U(struct SN_env * z, unsigned char * s, int min, int max) { extern int
in_grouping_U(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
int w = get_utf8(z->p, z->c, z->l, &ch); int w = get_utf8(z->p, z->c, z->l, &ch);
unless(w) return 0; unless(w) return 0;
if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
z->c += w; return 1; return 0;
z->c += w;
return 1;
} }
extern int in_grouping_b_U(struct SN_env * z, unsigned char * s, int min, int max) { extern int
in_grouping_b_U(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
int w = get_b_utf8(z->p, z->c, z->lb, &ch); int w = get_b_utf8(z->p, z->c, z->lb, &ch);
unless(w) return 0; unless(w) return 0;
if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
z->c -= w; return 1; return 0;
z->c -= w;
return 1;
} }
extern int out_grouping_U(struct SN_env * z, unsigned char * s, int min, int max) { extern int
out_grouping_U(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
int w = get_utf8(z->p, z->c, z->l, &ch); int w = get_utf8(z->p, z->c, z->l, &ch);
unless(w) return 0; unless(w) return 0;
unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0;
z->c += w; return 1; z->c += w;
return 1;
} }
extern int out_grouping_b_U(struct SN_env * z, unsigned char * s, int min, int max) { extern int
out_grouping_b_U(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
int w = get_b_utf8(z->p, z->c, z->lb, &ch); int w = get_b_utf8(z->p, z->c, z->lb, &ch);
unless(w) return 0; unless(w) return 0;
unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0;
z->c -= w; return 1; z->c -= w;
return 1;
} }
/* Code for character groupings: non-utf8 cases */ /* Code for character groupings: non-utf8 cases */
extern int in_grouping(struct SN_env * z, unsigned char * s, int min, int max) { extern int
in_grouping(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
if (z->c >= z->l) return 0;
if (z->c >= z->l)
return 0;
ch = z->p[z->c]; ch = z->p[z->c];
if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
z->c++; return 1; return 0;
z->c++;
return 1;
} }
extern int in_grouping_b(struct SN_env * z, unsigned char * s, int min, int max) { extern int
in_grouping_b(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
if (z->c <= z->lb) return 0;
if (z->c <= z->lb)
return 0;
ch = z->p[z->c - 1]; ch = z->p[z->c - 1];
if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
z->c--; return 1; return 0;
z->c--;
return 1;
} }
extern int out_grouping(struct SN_env * z, unsigned char * s, int min, int max) { extern int
out_grouping(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
if (z->c >= z->l) return 0;
if (z->c >= z->l)
return 0;
ch = z->p[z->c]; ch = z->p[z->c];
unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0;
z->c++; return 1; z->c++;
return 1;
} }
extern int out_grouping_b(struct SN_env * z, unsigned char * s, int min, int max) { extern int
out_grouping_b(struct SN_env * z, unsigned char *s, int min, int max)
{
int ch; int ch;
if (z->c <= z->lb) return 0;
if (z->c <= z->lb)
return 0;
ch = z->p[z->c - 1]; ch = z->p[z->c - 1];
unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; unless(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0;
z->c--; return 1; z->c--;
return 1;
} }
extern int eq_s(struct SN_env * z, int s_size, symbol * s) { extern int
if (z->l - z->c < s_size || memcmp(z->p + z->c, s, s_size * sizeof(symbol)) != 0) return 0; eq_s(struct SN_env * z, int s_size, symbol * s)
z->c += s_size; return 1; {
if (z->l - z->c < s_size || memcmp(z->p + z->c, s, s_size * sizeof(symbol)) != 0)
return 0;
z->c += s_size;
return 1;
} }
extern int eq_s_b(struct SN_env * z, int s_size, symbol * s) { extern int
if (z->c - z->lb < s_size || memcmp(z->p + z->c - s_size, s, s_size * sizeof(symbol)) != 0) return 0; eq_s_b(struct SN_env * z, int s_size, symbol * s)
z->c -= s_size; return 1; {
if (z->c - z->lb < s_size || memcmp(z->p + z->c - s_size, s, s_size * sizeof(symbol)) != 0)
return 0;
z->c -= s_size;
return 1;
} }
extern int eq_v(struct SN_env * z, symbol * p) { extern int
eq_v(struct SN_env * z, symbol * p)
{
return eq_s(z, SIZE(p), p); return eq_s(z, SIZE(p), p);
} }
extern int eq_v_b(struct SN_env * z, symbol * p) { extern int
eq_v_b(struct SN_env * z, symbol * p)
{
return eq_s_b(z, SIZE(p), p); return eq_s_b(z, SIZE(p), p);
} }
extern int find_among(struct SN_env * z, struct among * v, int v_size) { extern int
find_among(struct SN_env * z, struct among * v, int v_size)
{
int i = 0; int i = 0;
int j = v_size; int j = v_size;
int c = z->c; int l = z->l; int c = z->c;
int l = z->l;
symbol *q = z->p + c; symbol *q = z->p + c;
struct among *w; struct among *w;
@ -192,57 +290,89 @@ extern int find_among(struct SN_env * z, struct among * v, int v_size) {
int first_key_inspected = 0; int first_key_inspected = 0;
while(1) { while (1)
{
int k = i + ((j - i) >> 1); int k = i + ((j - i) >> 1);
int diff = 0; int diff = 0;
int common = common_i < common_j ? common_i : common_j; /* smaller */ int common = common_i < common_j ? common_i : common_j; /* smaller */
w = v + k; w = v + k;
{ {
int i; for (i = common; i < w->s_size; i++) { int i;
if (c + common == l) { diff = -1; break; }
for (i = common; i < w->s_size; i++)
{
if (c + common == l)
{
diff = -1;
break;
}
diff = q[common] - w->s[i]; diff = q[common] - w->s[i];
if (diff != 0) break; if (diff != 0)
break;
common++; common++;
} }
} }
if (diff < 0) { j = k; common_j = common; } if (diff < 0)
else { i = k; common_i = common; } {
if (j - i <= 1) { j = k;
if (i > 0) break; /* v->s has been inspected */ common_j = common;
if (j == i) break; /* only one item in v */ }
else
{
i = k;
common_i = common;
}
if (j - i <= 1)
{
if (i > 0)
break; /* v->s has been inspected */
if (j == i)
break; /* only one item in v */
/* - but now we need to go round once more to get /*
v->s inspected. This looks messy, but is actually * - but now we need to go round once more to get v->s inspected.
the optimal approach. */ * This looks messy, but is actually the optimal approach.
*/
if (first_key_inspected) break; if (first_key_inspected)
break;
first_key_inspected = 1; first_key_inspected = 1;
} }
} }
while(1) { while (1)
{
w = v + i; w = v + i;
if (common_i >= w->s_size) { if (common_i >= w->s_size)
{
z->c = c + w->s_size; z->c = c + w->s_size;
if (w->function == 0) return w->result; if (w->function == 0)
return w->result;
{ {
int res = w->function(z); int res = w->function(z);
z->c = c + w->s_size; z->c = c + w->s_size;
if (res) return w->result; if (res)
return w->result;
} }
} }
i = w->substring_i; i = w->substring_i;
if (i < 0) return 0; if (i < 0)
return 0;
} }
} }
/* find_among_b is for backwards processing. Same comments apply */ /* find_among_b is for backwards processing. Same comments apply */
extern int find_among_b(struct SN_env * z, struct among * v, int v_size) { extern int
find_among_b(struct SN_env * z, struct among * v, int v_size)
{
int i = 0; int i = 0;
int j = v_size; int j = v_size;
int c = z->c; int lb = z->lb; int c = z->c;
int lb = z->lb;
symbol *q = z->p + c - 1; symbol *q = z->p + c - 1;
struct among *w; struct among *w;
@ -252,41 +382,69 @@ extern int find_among_b(struct SN_env * z, struct among * v, int v_size) {
int first_key_inspected = 0; int first_key_inspected = 0;
while(1) { while (1)
{
int k = i + ((j - i) >> 1); int k = i + ((j - i) >> 1);
int diff = 0; int diff = 0;
int common = common_i < common_j ? common_i : common_j; int common = common_i < common_j ? common_i : common_j;
w = v + k; w = v + k;
{ {
int i; for (i = w->s_size - 1 - common; i >= 0; i--) { int i;
if (c - common == lb) { diff = -1; break; }
for (i = w->s_size - 1 - common; i >= 0; i--)
{
if (c - common == lb)
{
diff = -1;
break;
}
diff = q[-common] - w->s[i]; diff = q[-common] - w->s[i];
if (diff != 0) break; if (diff != 0)
break;
common++; common++;
} }
} }
if (diff < 0) { j = k; common_j = common; } if (diff < 0)
else { i = k; common_i = common; } {
if (j - i <= 1) { j = k;
if (i > 0) break; common_j = common;
if (j == i) break; }
if (first_key_inspected) break; else
{
i = k;
common_i = common;
}
if (j - i <= 1)
{
if (i > 0)
break;
if (j == i)
break;
if (first_key_inspected)
break;
first_key_inspected = 1; first_key_inspected = 1;
} }
} }
while(1) { while (1)
{
w = v + i; w = v + i;
if (common_i >= w->s_size) { if (common_i >= w->s_size)
{
z->c = c - w->s_size; z->c = c - w->s_size;
if (w->function == 0) return w->result; if (w->function == 0)
return w->result;
{ {
int res = w->function(z); int res = w->function(z);
z->c = c - w->s_size; z->c = c - w->s_size;
if (res) return w->result; if (res)
return w->result;
} }
} }
i = w->substring_i; i = w->substring_i;
if (i < 0) return 0; if (i < 0)
return 0;
} }
} }
@ -294,12 +452,16 @@ extern int find_among_b(struct SN_env * z, struct among * v, int v_size) {
/* Increase the size of the buffer pointed to by p to at least n symbols. /* Increase the size of the buffer pointed to by p to at least n symbols.
* If insufficient memory, returns NULL and frees the old buffer. * If insufficient memory, returns NULL and frees the old buffer.
*/ */
static symbol * increase_size(symbol * p, int n) { static symbol *
increase_size(symbol * p, int n)
{
symbol *q; symbol *q;
int new_size = n + 20; int new_size = n + 20;
void *mem = realloc((char *) p - HEAD, void *mem = realloc((char *) p - HEAD,
HEAD + (new_size + 1) * sizeof(symbol)); HEAD + (new_size + 1) * sizeof(symbol));
if (mem == NULL) {
if (mem == NULL)
{
lose_s(p); lose_s(p);
return NULL; return NULL;
} }
@ -313,20 +475,27 @@ static symbol * increase_size(symbol * p, int n) {
Returns 0 on success, -1 on error. Returns 0 on success, -1 on error.
Also, frees z->p (and sets it to NULL) on error. Also, frees z->p (and sets it to NULL) on error.
*/ */
extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int * adjptr) extern int
replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int *adjptr)
{ {
int adjustment; int adjustment;
int len; int len;
if (z->p == NULL) {
if (z->p == NULL)
{
z->p = create_s(); z->p = create_s();
if (z->p == NULL) return -1; if (z->p == NULL)
return -1;
} }
adjustment = s_size - (c_ket - c_bra); adjustment = s_size - (c_ket - c_bra);
len = SIZE(z->p); len = SIZE(z->p);
if (adjustment != 0) { if (adjustment != 0)
if (adjustment + len > CAPACITY(z->p)) { {
if (adjustment + len > CAPACITY(z->p))
{
z->p = increase_size(z->p, adjustment + len); z->p = increase_size(z->p, adjustment + len);
if (z->p == NULL) return -1; if (z->p == NULL)
return -1;
} }
memmove(z->p + c_ket + adjustment, memmove(z->p + c_ket + adjustment,
z->p + c_ket, z->p + c_ket,
@ -335,8 +504,7 @@ extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const
z->l += adjustment; z->l += adjustment;
if (z->c >= c_ket) if (z->c >= c_ket)
z->c += adjustment; z->c += adjustment;
else else if (z->c > c_bra)
if (z->c > c_bra)
z->c = c_bra; z->c = c_bra;
} }
unless(s_size == 0) memmove(z->p + c_bra, s, s_size * sizeof(symbol)); unless(s_size == 0) memmove(z->p + c_bra, s, s_size * sizeof(symbol));
@ -345,7 +513,9 @@ extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const
return 0; return 0;
} }
static int slice_check(struct SN_env * z) { static int
slice_check(struct SN_env * z)
{
if (z->bra < 0 || if (z->bra < 0 ||
z->bra > z->ket || z->bra > z->ket ||
@ -362,45 +532,67 @@ static int slice_check(struct SN_env * z) {
return 0; return 0;
} }
extern int slice_from_s(struct SN_env * z, int s_size, symbol * s) { extern int
if (slice_check(z)) return -1; slice_from_s(struct SN_env * z, int s_size, symbol * s)
{
if (slice_check(z))
return -1;
return replace_s(z, z->bra, z->ket, s_size, s, NULL); return replace_s(z, z->bra, z->ket, s_size, s, NULL);
} }
extern int slice_from_v(struct SN_env * z, symbol * p) { extern int
slice_from_v(struct SN_env * z, symbol * p)
{
return slice_from_s(z, SIZE(p), p); return slice_from_s(z, SIZE(p), p);
} }
extern int slice_del(struct SN_env * z) { extern int
slice_del(struct SN_env * z)
{
return slice_from_s(z, 0, 0); return slice_from_s(z, 0, 0);
} }
extern int insert_s(struct SN_env * z, int bra, int ket, int s_size, symbol * s) { extern int
insert_s(struct SN_env * z, int bra, int ket, int s_size, symbol * s)
{
int adjustment; int adjustment;
if (replace_s(z, bra, ket, s_size, s, &adjustment)) if (replace_s(z, bra, ket, s_size, s, &adjustment))
return -1; return -1;
if (bra <= z->bra) z->bra += adjustment; if (bra <= z->bra)
if (bra <= z->ket) z->ket += adjustment; z->bra += adjustment;
if (bra <= z->ket)
z->ket += adjustment;
return 0; return 0;
} }
extern int insert_v(struct SN_env * z, int bra, int ket, symbol * p) { extern int
insert_v(struct SN_env * z, int bra, int ket, symbol * p)
{
int adjustment; int adjustment;
if (replace_s(z, bra, ket, SIZE(p), p, &adjustment)) if (replace_s(z, bra, ket, SIZE(p), p, &adjustment))
return -1; return -1;
if (bra <= z->bra) z->bra += adjustment; if (bra <= z->bra)
if (bra <= z->ket) z->ket += adjustment; z->bra += adjustment;
if (bra <= z->ket)
z->ket += adjustment;
return 0; return 0;
} }
extern symbol * slice_to(struct SN_env * z, symbol * p) { extern symbol *
if (slice_check(z)) { slice_to(struct SN_env * z, symbol * p)
{
if (slice_check(z))
{
lose_s(p); lose_s(p);
return NULL; return NULL;
} }
{ {
int len = z->ket - z->bra; int len = z->ket - z->bra;
if (CAPACITY(p) < len) {
if (CAPACITY(p) < len)
{
p = increase_size(p, len); p = increase_size(p, len);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
@ -411,9 +603,13 @@ extern symbol * slice_to(struct SN_env * z, symbol * p) {
return p; return p;
} }
extern symbol * assign_to(struct SN_env * z, symbol * p) { extern symbol *
assign_to(struct SN_env * z, symbol * p)
{
int len = z->l; int len = z->l;
if (CAPACITY(p) < len) {
if (CAPACITY(p) < len)
{
p = increase_size(p, len); p = increase_size(p, len);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
@ -424,23 +620,37 @@ extern symbol * assign_to(struct SN_env * z, symbol * p) {
} }
#if 0 #if 0
extern void debug(struct SN_env * z, int number, int line_count) { extern void
debug(struct SN_env * z, int number, int line_count)
{
int i; int i;
int limit = SIZE(z->p); int limit = SIZE(z->p);
/* if (number >= 0) printf("%3d (line %4d): '", number, line_count); */ /* if (number >= 0) printf("%3d (line %4d): '", number, line_count); */
if (number >= 0) printf("%3d (line %4d): [%d]'", number, line_count,limit); if (number >= 0)
for (i = 0; i <= limit; i++) { printf("%3d (line %4d): [%d]'", number, line_count, limit);
if (z->lb == i) printf("{"); for (i = 0; i <= limit; i++)
if (z->bra == i) printf("["); {
if (z->c == i) printf("|"); if (z->lb == i)
if (z->ket == i) printf("]"); printf("{");
if (z->l == i) printf("}"); if (z->bra == i)
printf("[");
if (z->c == i)
printf("|");
if (z->ket == i)
printf("]");
if (z->l == i)
printf("}");
if (i < limit) if (i < limit)
{ int ch = z->p[i]; {
if (ch == 0) ch = '#'; int ch = z->p[i];
if (ch == 0)
ch = '#';
printf("%c", ch); printf("%c", ch);
} }
} }
printf("'\n"); printf("'\n");
} }
#endif #endif

View File

@ -355,8 +355,7 @@ parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen)
prs->curwords++; prs->curwords++;
} }
pfree(norms); pfree(norms);
break; /* lexem already normalized or is stop break; /* lexem already normalized or is stop word */
* word */
} }
} }
@ -481,8 +480,7 @@ hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4
ptr++; ptr++;
} }
pfree(norms); pfree(norms);
break; /* lexem already normalized or is stop break; /* lexem already normalized or is stop word */
* word */
} }
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/contrib/vacuumlo/vacuumlo.c,v 1.29 2004/12/31 21:58:50 pgsql Exp $ * $PostgreSQL: pgsql/contrib/vacuumlo/vacuumlo.c,v 1.30 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -130,8 +130,8 @@ vacuumlo(char *database, struct _param * param)
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
* for the DELETEs below. * the DELETEs below.
*/ */
buf[0] = '\0'; buf[0] = '\0';
strcat(buf, "VACUUM ANALYZE vacuum_l"); strcat(buf, "VACUUM ANALYZE vacuum_l");
@ -193,8 +193,8 @@ vacuumlo(char *database, struct _param * param)
/* /*
* The "IN" construct used here was horribly inefficient before * The "IN" construct used here was horribly inefficient before
* Postgres 7.4, but should be now competitive if not better than * Postgres 7.4, but should be now competitive if not better than the
* the bogus join we used before. * bogus join we used before.
*/ */
snprintf(buf, BUFSIZE, snprintf(buf, BUFSIZE,
"DELETE FROM vacuum_l " "DELETE FROM vacuum_l "
@ -216,10 +216,9 @@ vacuumlo(char *database, struct _param * param)
PQclear(res); PQclear(res);
/* /*
* Run the actual deletes in a single transaction. Note that this * Run the actual deletes in a single transaction. Note that this would
* would be a bad idea in pre-7.1 Postgres releases (since rolling * be a bad idea in pre-7.1 Postgres releases (since rolling back a table
* back a table delete used to cause problems), but it should be safe * delete used to cause problems), but it should be safe now.
* now.
*/ */
res = PQexec(conn, "begin"); res = PQexec(conn, "begin");
PQclear(res); PQclear(res);

View File

@ -197,7 +197,8 @@ xml_encode_special_chars(PG_FUNCTION_ARGS)
text *tin = PG_GETARG_TEXT_P(0); text *tin = PG_GETARG_TEXT_P(0);
text *tout; text *tout;
int32 ressize; int32 ressize;
xmlChar *ts, *tt; xmlChar *ts,
*tt;
ts = pgxml_texttoxmlchar(tin); ts = pgxml_texttoxmlchar(tin);
@ -225,15 +226,15 @@ pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
/* Function translates a nodeset into a text representation */ /* Function translates a nodeset into a text representation */
/* /*
* iterates over each node in the set and calls xmlNodeDump to write * iterates over each node in the set and calls xmlNodeDump to write it to
* it to an xmlBuffer -from which an xmlChar * string is returned. * an xmlBuffer -from which an xmlChar * string is returned.
*/ */
/* each representation is surrounded by <tagname> ... </tagname> */ /* each representation is surrounded by <tagname> ... </tagname> */
/* /*
* plainsep is an ordinary (not tag) seperator - if used, then nodes * plainsep is an ordinary (not tag) seperator - if used, then nodes are
* are cast to string as output method * cast to string as output method
*/ */
@ -412,8 +413,8 @@ xpath_string(PG_FUNCTION_ARGS)
pathsize = VARSIZE(xpathsupp) - VARHDRSZ; pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
/* /*
* We encapsulate the supplied path with "string()" = 8 chars + 1 for * We encapsulate the supplied path with "string()" = 8 chars + 1 for NUL
* NUL at end * at end
*/ */
/* We could try casting to string using the libxml function? */ /* We could try casting to string using the libxml function? */
@ -663,8 +664,8 @@ xpath_table(PG_FUNCTION_ARGS)
int proc; int proc;
int i; int i;
int j; int j;
int rownr; /* For issuing multiple rows from one int rownr; /* For issuing multiple rows from one original
* original document */ * document */
int had_values; /* To determine end of nodeset results */ int had_values; /* To determine end of nodeset results */
StringInfo querysql; StringInfo querysql;
@ -689,14 +690,16 @@ xpath_table(PG_FUNCTION_ARGS)
errmsg("xpath_table requires Materialize mode, but it is not " errmsg("xpath_table requires Materialize mode, but it is not "
"allowed in this context"))); "allowed in this context")));
/* The tuplestore must exist in a higher context than /*
* this function call (per_query_ctx is used) * The tuplestore must exist in a higher context than this function call
* (per_query_ctx is used)
*/ */
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx); oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* Create the tuplestore - work_mem is the max in-memory size before a /*
* Create the tuplestore - work_mem is the max in-memory size before a
* file is created on disk to hold it. * file is created on disk to hold it.
*/ */
tupstore = tuplestore_begin_heap(true, false, work_mem); tupstore = tuplestore_begin_heap(true, false, work_mem);
@ -707,11 +710,11 @@ xpath_table(PG_FUNCTION_ARGS)
ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
/* /*
* At the moment we assume that the returned attributes make sense for * At the moment we assume that the returned attributes make sense for the
* the XPath specififed (i.e. we trust the caller). It's not fatal if * XPath specififed (i.e. we trust the caller). It's not fatal if they get
* they get it wrong - the input function for the column type will * it wrong - the input function for the column type will raise an error
* raise an error if the path result can't be converted into the * if the path result can't be converted into the correct binary
* correct binary representation. * representation.
*/ */
attinmeta = TupleDescGetAttInMetadata(ret_tupdesc); attinmeta = TupleDescGetAttInMetadata(ret_tupdesc);
@ -810,8 +813,8 @@ xpath_table(PG_FUNCTION_ARGS)
/* /*
* Clear the values array, so that not-well-formed documents * Clear the values array, so that not-well-formed documents return
* return NULL in all columns. * NULL in all columns.
*/ */
/* Note that this also means that spare columns will be NULL. */ /* Note that this also means that spare columns will be NULL. */
@ -825,8 +828,7 @@ xpath_table(PG_FUNCTION_ARGS)
doctree = xmlParseMemory(xmldoc, strlen(xmldoc)); doctree = xmlParseMemory(xmldoc, strlen(xmldoc));
if (doctree == NULL) if (doctree == NULL)
{ /* not well-formed, so output all-NULL { /* not well-formed, so output all-NULL tuple */
* tuple */
ret_tuple = BuildTupleFromCStrings(attinmeta, values); ret_tuple = BuildTupleFromCStrings(attinmeta, values);
oldcontext = MemoryContextSwitchTo(per_query_ctx); oldcontext = MemoryContextSwitchTo(per_query_ctx);
@ -933,10 +935,10 @@ xpath_table(PG_FUNCTION_ARGS)
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual
* tuples are in our tuplestore and passed back through * tuples are in our tuplestore and passed back through rsinfo->setResult.
* rsinfo->setResult. rsinfo->setDesc is set to the tuple description * rsinfo->setDesc is set to the tuple description that we actually used
* that we actually used to build our tuples with, so the caller can * to build our tuples with, so the caller can verify we did what it was
* verify we did what it was expecting. * expecting.
*/ */
return (Datum) 0; return (Datum) 0;

View File

@ -16,7 +16,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.99 2005/03/21 01:23:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.100 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -452,8 +452,8 @@ nocachegetattr(HeapTuple tuple,
int j; int j;
/* /*
* In for(), we test <= and not < because we want to see if we * In for(), we test <= and not < because we want to see if we can
* can go past it in initializing offsets. * go past it in initializing offsets.
*/ */
for (j = 0; j <= attnum; j++) for (j = 0; j <= attnum; j++)
{ {
@ -467,10 +467,9 @@ nocachegetattr(HeapTuple tuple,
} }
/* /*
* If slow is false, and we got here, we know that we have a tuple * If slow is false, and we got here, we know that we have a tuple with no
* with no nulls or var-widths before the target attribute. If * nulls or var-widths before the target attribute. If possible, we also
* possible, we also want to initialize the remainder of the attribute * want to initialize the remainder of the attribute cached offset values.
* cached offset values.
*/ */
if (!slow) if (!slow)
{ {
@ -513,11 +512,11 @@ nocachegetattr(HeapTuple tuple,
/* /*
* Now we know that we have to walk the tuple CAREFULLY. * Now we know that we have to walk the tuple CAREFULLY.
* *
* Note - This loop is a little tricky. For each non-null attribute, * Note - This loop is a little tricky. For each non-null attribute, we
* we have to first account for alignment padding before the attr, * have to first account for alignment padding before the attr, then
* then advance over the attr based on its length. Nulls have no * advance over the attr based on its length. Nulls have no storage
* storage and no alignment padding either. We can use/set attcacheoff * and no alignment padding either. We can use/set attcacheoff until
* until we pass either a null or a var-width attribute. * we pass either a null or a var-width attribute.
*/ */
for (i = 0; i < attnum; i++) for (i = 0; i < attnum; i++)
@ -597,15 +596,13 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
break; break;
/* /*
* If the attribute number is 0, then we are supposed to * If the attribute number is 0, then we are supposed to return
* return the entire tuple as a row-type Datum. (Using zero * the entire tuple as a row-type Datum. (Using zero for this
* for this purpose is unclean since it risks confusion with * purpose is unclean since it risks confusion with "invalid attr"
* "invalid attr" result codes, but it's not worth changing * result codes, but it's not worth changing now.)
* now.)
* *
* We have to make a copy of the tuple so we can safely insert * We have to make a copy of the tuple so we can safely insert the
* the Datum overhead fields, which are not set in on-disk * Datum overhead fields, which are not set in on-disk tuples.
* tuples.
*/ */
case InvalidAttrNumber: case InvalidAttrNumber:
{ {
@ -708,15 +705,15 @@ heap_form_tuple(TupleDesc tupleDescriptor,
numberOfAttributes, MaxTupleAttributeNumber))); numberOfAttributes, MaxTupleAttributeNumber)));
/* /*
* Check for nulls and embedded tuples; expand any toasted attributes * Check for nulls and embedded tuples; expand any toasted attributes in
* in embedded tuples. This preserves the invariant that toasting can * embedded tuples. This preserves the invariant that toasting can only
* only go one level deep. * go one level deep.
* *
* We can skip calling toast_flatten_tuple_attribute() if the attribute * We can skip calling toast_flatten_tuple_attribute() if the attribute
* couldn't possibly be of composite type. All composite datums are * couldn't possibly be of composite type. All composite datums are
* varlena and have alignment 'd'; furthermore they aren't arrays. * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
* Also, if an attribute is already toasted, it must have been sent to * if an attribute is already toasted, it must have been sent to disk
* disk already and so cannot contain toasted attributes. * already and so cannot contain toasted attributes.
*/ */
for (i = 0; i < numberOfAttributes; i++) for (i = 0; i < numberOfAttributes; i++)
{ {
@ -757,8 +754,8 @@ heap_form_tuple(TupleDesc tupleDescriptor,
tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE); tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
/* /*
* And fill in the information. Note we fill the Datum fields even * And fill in the information. Note we fill the Datum fields even though
* though this tuple may never become a Datum. * this tuple may never become a Datum.
*/ */
tuple->t_len = len; tuple->t_len = len;
ItemPointerSetInvalid(&(tuple->t_self)); ItemPointerSetInvalid(&(tuple->t_self));
@ -816,15 +813,15 @@ heap_formtuple(TupleDesc tupleDescriptor,
numberOfAttributes, MaxTupleAttributeNumber))); numberOfAttributes, MaxTupleAttributeNumber)));
/* /*
* Check for nulls and embedded tuples; expand any toasted attributes * Check for nulls and embedded tuples; expand any toasted attributes in
* in embedded tuples. This preserves the invariant that toasting can * embedded tuples. This preserves the invariant that toasting can only
* only go one level deep. * go one level deep.
* *
* We can skip calling toast_flatten_tuple_attribute() if the attribute * We can skip calling toast_flatten_tuple_attribute() if the attribute
* couldn't possibly be of composite type. All composite datums are * couldn't possibly be of composite type. All composite datums are
* varlena and have alignment 'd'; furthermore they aren't arrays. * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
* Also, if an attribute is already toasted, it must have been sent to * if an attribute is already toasted, it must have been sent to disk
* disk already and so cannot contain toasted attributes. * already and so cannot contain toasted attributes.
*/ */
for (i = 0; i < numberOfAttributes; i++) for (i = 0; i < numberOfAttributes; i++)
{ {
@ -865,8 +862,8 @@ heap_formtuple(TupleDesc tupleDescriptor,
tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE); tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
/* /*
* And fill in the information. Note we fill the Datum fields even * And fill in the information. Note we fill the Datum fields even though
* though this tuple may never become a Datum. * this tuple may never become a Datum.
*/ */
tuple->t_len = len; tuple->t_len = len;
ItemPointerSetInvalid(&(tuple->t_self)); ItemPointerSetInvalid(&(tuple->t_self));
@ -917,15 +914,15 @@ heap_modify_tuple(HeapTuple tuple,
HeapTuple newTuple; HeapTuple newTuple;
/* /*
* allocate and fill values and isnull arrays from either the tuple or * allocate and fill values and isnull arrays from either the tuple or the
* the repl information, as appropriate. * repl information, as appropriate.
* *
* NOTE: it's debatable whether to use heap_deform_tuple() here or just * NOTE: it's debatable whether to use heap_deform_tuple() here or just
* heap_getattr() only the non-replaced colums. The latter could win * heap_getattr() only the non-replaced colums. The latter could win if
* if there are many replaced columns and few non-replaced ones. * there are many replaced columns and few non-replaced ones. However,
* However, heap_deform_tuple costs only O(N) while the heap_getattr * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
* way would cost O(N^2) if there are many non-replaced columns, so it * O(N^2) if there are many non-replaced columns, so it seems better to
* seems better to err on the side of linear cost. * err on the side of linear cost.
*/ */
values = (Datum *) palloc(numberOfAttributes * sizeof(Datum)); values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
isnull = (bool *) palloc(numberOfAttributes * sizeof(bool)); isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
@ -950,8 +947,8 @@ heap_modify_tuple(HeapTuple tuple,
pfree(isnull); pfree(isnull);
/* /*
* copy the identification info of the old tuple: t_ctid, t_self, and * copy the identification info of the old tuple: t_ctid, t_self, and OID
* OID (if any) * (if any)
*/ */
newTuple->t_data->t_ctid = tuple->t_data->t_ctid; newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
newTuple->t_self = tuple->t_self; newTuple->t_self = tuple->t_self;
@ -986,15 +983,15 @@ heap_modifytuple(HeapTuple tuple,
HeapTuple newTuple; HeapTuple newTuple;
/* /*
* allocate and fill values and nulls arrays from either the tuple or * allocate and fill values and nulls arrays from either the tuple or the
* the repl information, as appropriate. * repl information, as appropriate.
* *
* NOTE: it's debatable whether to use heap_deformtuple() here or just * NOTE: it's debatable whether to use heap_deformtuple() here or just
* heap_getattr() only the non-replaced colums. The latter could win * heap_getattr() only the non-replaced colums. The latter could win if
* if there are many replaced columns and few non-replaced ones. * there are many replaced columns and few non-replaced ones. However,
* However, heap_deformtuple costs only O(N) while the heap_getattr * heap_deformtuple costs only O(N) while the heap_getattr way would cost
* way would cost O(N^2) if there are many non-replaced columns, so it * O(N^2) if there are many non-replaced columns, so it seems better to
* seems better to err on the side of linear cost. * err on the side of linear cost.
*/ */
values = (Datum *) palloc(numberOfAttributes * sizeof(Datum)); values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
nulls = (char *) palloc(numberOfAttributes * sizeof(char)); nulls = (char *) palloc(numberOfAttributes * sizeof(char));
@ -1022,8 +1019,8 @@ heap_modifytuple(HeapTuple tuple,
pfree(nulls); pfree(nulls);
/* /*
* copy the identification info of the old tuple: t_ctid, t_self, and * copy the identification info of the old tuple: t_ctid, t_self, and OID
* OID (if any) * (if any)
*/ */
newTuple->t_data->t_ctid = tuple->t_data->t_ctid; newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
newTuple->t_self = tuple->t_self; newTuple->t_self = tuple->t_self;
@ -1068,9 +1065,9 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
natts = tup->t_natts; natts = tup->t_natts;
/* /*
* In inheritance situations, it is possible that the given tuple * In inheritance situations, it is possible that the given tuple actually
* actually has more fields than the caller is expecting. Don't run * has more fields than the caller is expecting. Don't run off the end of
* off the end of the caller's arrays. * the caller's arrays.
*/ */
natts = Min(natts, tdesc_natts); natts = Min(natts, tdesc_natts);
@ -1161,9 +1158,9 @@ heap_deformtuple(HeapTuple tuple,
natts = tup->t_natts; natts = tup->t_natts;
/* /*
* In inheritance situations, it is possible that the given tuple * In inheritance situations, it is possible that the given tuple actually
* actually has more fields than the caller is expecting. Don't run * has more fields than the caller is expecting. Don't run off the end of
* off the end of the caller's arrays. * the caller's arrays.
*/ */
natts = Min(natts, tdesc_natts); natts = Min(natts, tdesc_natts);
@ -1242,8 +1239,8 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
bool slow; /* can we use/set attcacheoff? */ bool slow; /* can we use/set attcacheoff? */
/* /*
* Check whether the first call for this tuple, and initialize or * Check whether the first call for this tuple, and initialize or restore
* restore loop state. * loop state.
*/ */
attnum = slot->tts_nvalid; attnum = slot->tts_nvalid;
if (attnum == 0) if (attnum == 0)
@ -1349,8 +1346,8 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
} }
/* /*
* otherwise we had better have a physical tuple (tts_nvalid should * otherwise we had better have a physical tuple (tts_nvalid should equal
* equal natts in all virtual-tuple cases) * natts in all virtual-tuple cases)
*/ */
if (tuple == NULL) /* internal error */ if (tuple == NULL) /* internal error */
elog(ERROR, "cannot extract attribute from empty tuple slot"); elog(ERROR, "cannot extract attribute from empty tuple slot");
@ -1358,9 +1355,9 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
/* /*
* return NULL if attnum is out of range according to the tuple * return NULL if attnum is out of range according to the tuple
* *
* (We have to check this separately because of various inheritance * (We have to check this separately because of various inheritance and
* and table-alteration scenarios: the tuple could be either longer * table-alteration scenarios: the tuple could be either longer or shorter
* or shorter than the tupdesc.) * than the tupdesc.)
*/ */
tup = tuple->t_data; tup = tuple->t_data;
if (attnum > tup->t_natts) if (attnum > tup->t_natts)
@ -1379,10 +1376,9 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
} }
/* /*
* If the attribute's column has been dropped, we force a NULL * If the attribute's column has been dropped, we force a NULL result.
* result. This case should not happen in normal use, but it could * This case should not happen in normal use, but it could happen if we
* happen if we are executing a plan cached before the column was * are executing a plan cached before the column was dropped.
* dropped.
*/ */
if (tupleDesc->attrs[attnum - 1]->attisdropped) if (tupleDesc->attrs[attnum - 1]->attisdropped)
{ {
@ -1420,8 +1416,8 @@ slot_getallattrs(TupleTableSlot *slot)
return; return;
/* /*
* otherwise we had better have a physical tuple (tts_nvalid should * otherwise we had better have a physical tuple (tts_nvalid should equal
* equal natts in all virtual-tuple cases) * natts in all virtual-tuple cases)
*/ */
tuple = slot->tts_tuple; tuple = slot->tts_tuple;
if (tuple == NULL) /* internal error */ if (tuple == NULL) /* internal error */
@ -1467,8 +1463,8 @@ slot_getsomeattrs(TupleTableSlot *slot, int attnum)
elog(ERROR, "invalid attribute number %d", attnum); elog(ERROR, "invalid attribute number %d", attnum);
/* /*
* otherwise we had better have a physical tuple (tts_nvalid should * otherwise we had better have a physical tuple (tts_nvalid should equal
* equal natts in all virtual-tuple cases) * natts in all virtual-tuple cases)
*/ */
tuple = slot->tts_tuple; tuple = slot->tts_tuple;
if (tuple == NULL) /* internal error */ if (tuple == NULL) /* internal error */
@ -1528,8 +1524,8 @@ slot_attisnull(TupleTableSlot *slot, int attnum)
return true; return true;
/* /*
* otherwise we had better have a physical tuple (tts_nvalid should * otherwise we had better have a physical tuple (tts_nvalid should equal
* equal natts in all virtual-tuple cases) * natts in all virtual-tuple cases)
*/ */
if (tuple == NULL) /* internal error */ if (tuple == NULL) /* internal error */
elog(ERROR, "cannot extract attribute from empty tuple slot"); elog(ERROR, "cannot extract attribute from empty tuple slot");

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.74 2005/03/27 18:38:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.75 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -70,8 +70,8 @@ index_form_tuple(TupleDesc tupleDescriptor,
continue; continue;
/* /*
* If value is stored EXTERNAL, must fetch it so we are not * If value is stored EXTERNAL, must fetch it so we are not depending
* depending on outside storage. This should be improved someday. * on outside storage. This should be improved someday.
*/ */
if (VARATT_IS_EXTERNAL(values[i])) if (VARATT_IS_EXTERNAL(values[i]))
{ {
@ -82,8 +82,8 @@ index_form_tuple(TupleDesc tupleDescriptor,
} }
/* /*
* If value is above size target, and is of a compressible * If value is above size target, and is of a compressible datatype,
* datatype, try to compress it in-line. * try to compress it in-line.
*/ */
if (VARATT_SIZE(untoasted_values[i]) > TOAST_INDEX_TARGET && if (VARATT_SIZE(untoasted_values[i]) > TOAST_INDEX_TARGET &&
!VARATT_IS_EXTENDED(untoasted_values[i]) && !VARATT_IS_EXTENDED(untoasted_values[i]) &&
@ -149,16 +149,16 @@ index_form_tuple(TupleDesc tupleDescriptor,
/* /*
* We do this because heap_fill_tuple wants to initialize a "tupmask" * We do this because heap_fill_tuple wants to initialize a "tupmask"
* which is used for HeapTuples, but we want an indextuple infomask. * which is used for HeapTuples, but we want an indextuple infomask. The
* 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_HASVARWIDTH) if (tupmask & HEAP_HASVARWIDTH)
infomask |= INDEX_VAR_MASK; infomask |= INDEX_VAR_MASK;
/* /*
* Here we make sure that the size will fit in the field reserved for * Here we make sure that the size will fit in the field reserved for it
* it in t_info. * in t_info.
*/ */
if ((size & INDEX_SIZE_MASK) != size) if ((size & INDEX_SIZE_MASK) != size)
ereport(ERROR, ereport(ERROR,
@ -322,10 +322,9 @@ nocache_index_getattr(IndexTuple tup,
} }
/* /*
* If slow is false, and we got here, we know that we have a tuple * If slow is false, and we got here, we know that we have a tuple with no
* with no nulls or var-widths before the target attribute. If * nulls or var-widths before the target attribute. If possible, we also
* possible, we also want to initialize the remainder of the attribute * want to initialize the remainder of the attribute cached offset values.
* cached offset values.
*/ */
if (!slow) if (!slow)
{ {

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.91 2005/06/22 17:45:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.92 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -78,9 +78,9 @@ printtup_create_DR(CommandDest dest, Portal portal)
else else
{ {
/* /*
* In protocol 2.0 the Bind message does not exist, so there is no * In protocol 2.0 the Bind message does not exist, so there is no way
* way for the columns to have different print formats; it's * for the columns to have different print formats; it's sufficient to
* sufficient to look at the first one. * look at the first one.
*/ */
if (portal->formats && portal->formats[0] != 0) if (portal->formats && portal->formats[0] != 0)
self->pub.receiveSlot = printtup_internal_20; self->pub.receiveSlot = printtup_internal_20;
@ -113,8 +113,7 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
{ {
/* /*
* Send portal name to frontend (obsolete cruft, gone in proto * Send portal name to frontend (obsolete cruft, gone in proto 3.0)
* 3.0)
* *
* If portal name not specified, use "blank" portal. * If portal name not specified, use "blank" portal.
*/ */
@ -127,8 +126,8 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
} }
/* /*
* If this is a retrieve, and we are supposed to emit row * If this is a retrieve, and we are supposed to emit row descriptions,
* descriptions, then we send back the tuple descriptor of the tuples. * then we send back the tuple descriptor of the tuples.
*/ */
if (operation == CMD_SELECT && myState->sendDescrip) if (operation == CMD_SELECT && myState->sendDescrip)
SendRowDescriptionMessage(typeinfo, SendRowDescriptionMessage(typeinfo,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.111 2005/04/14 22:34:48 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.112 2005/10/15 02:49:08 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
@ -49,10 +49,10 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
* Allocate enough memory for the tuple descriptor, including the * Allocate enough memory for the tuple descriptor, including the
* attribute rows, and set up the attribute row pointers. * attribute rows, and set up the attribute row pointers.
* *
* Note: we assume that sizeof(struct tupleDesc) is a multiple of * Note: we assume that sizeof(struct tupleDesc) is a multiple of the struct
* the struct pointer alignment requirement, and hence we don't need * pointer alignment requirement, and hence we don't need to insert
* to insert alignment padding between the struct and the array of * alignment padding between the struct and the array of attribute row
* attribute row pointers. * pointers.
*/ */
attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute); attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
attroffset = MAXALIGN(attroffset); attroffset = MAXALIGN(attroffset);
@ -273,16 +273,16 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Form_pg_attribute attr2 = tupdesc2->attrs[i]; Form_pg_attribute attr2 = tupdesc2->attrs[i];
/* /*
* We do not need to check every single field here: we can * We do not need to check every single field here: we can disregard
* disregard attrelid and attnum (which were used to place the row * attrelid and attnum (which were used to place the row in the attrs
* in the attrs array in the first place). It might look like we * array in the first place). It might look like we could dispense
* could dispense with checking attlen/attbyval/attalign, since these * with checking attlen/attbyval/attalign, since these are derived
* are derived from atttypid; but in the case of dropped columns * from atttypid; but in the case of dropped columns we must check
* we must check them (since atttypid will be zero for all dropped * them (since atttypid will be zero for all dropped columns) and in
* columns) and in general it seems safer to check them always. * general it seems safer to check them always.
* *
* attcacheoff must NOT be checked since it's possibly not set * attcacheoff must NOT be checked since it's possibly not set in both
* in both copies. * copies.
*/ */
if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
return false; return false;
@ -332,9 +332,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
AttrDefault *defval2 = constr2->defval; AttrDefault *defval2 = constr2->defval;
/* /*
* 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
* system catalogs in the same order; so use the adnum field * catalogs in the same order; so use the adnum field to identify
* to identify the matching item to compare. * the matching item to compare.
*/ */
for (j = 0; j < n; defval2++, j++) for (j = 0; j < n; defval2++, j++)
{ {
@ -355,9 +355,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
ConstrCheck *check2 = constr2->check; ConstrCheck *check2 = constr2->check;
/* /*
* Similarly, don't assume that the checks are always read in * Similarly, don't assume that the checks are always read in the
* the same order; match them up by name and contents. (The * same order; match them up by name and contents. (The name
* name *should* be unique, but...) * *should* be unique, but...)
*/ */
for (j = 0; j < n; check2++, j++) for (j = 0; j < n; check2++, j++)
{ {
@ -407,8 +407,8 @@ TupleDescInitEntry(TupleDesc desc,
/* /*
* Note: attributeName can be NULL, because the planner doesn't always * Note: attributeName can be NULL, because the planner doesn't always
* fill in valid resname values in targetlists, particularly for * fill in valid resname values in targetlists, particularly for resjunk
* resjunk attributes. * attributes.
*/ */
if (attributeName != NULL) if (attributeName != NULL)
namestrcpy(&(att->attname), attributeName); namestrcpy(&(att->attname), attributeName);
@ -482,8 +482,8 @@ BuildDescForRelation(List *schema)
ColumnDef *entry = lfirst(l); ColumnDef *entry = lfirst(l);
/* /*
* for each entry in the list, get the name and type information * for each entry in the list, get the name and type information from
* from the list and have TupleDescInitEntry fill in the attribute * the list and have TupleDescInitEntry fill in the attribute
* information we need. * information we need.
*/ */
attnum++; attnum++;
@ -508,8 +508,8 @@ BuildDescForRelation(List *schema)
desc->attrs[attnum - 1]->attnotnull = entry->is_not_null; desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
/* /*
* Note we copy only pre-cooked default expressions. Digestion of * Note we copy only pre-cooked default expressions. Digestion of raw
* raw ones is someone else's problem. * ones is someone else's problem.
*/ */
if (entry->cooked_default != NULL) if (entry->cooked_default != NULL)
{ {

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.2 2005/09/22 20:44:36 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.3 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.80 2005/06/06 17:01:21 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.81 2005/10/15 02:49:08 momjian Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -55,8 +55,8 @@ hashbuild(PG_FUNCTION_ARGS)
HashBuildState buildstate; HashBuildState buildstate;
/* /*
* We expect to be called exactly once for any index relation. If * We expect to be called exactly once for any index relation. If that's
* that's not the case, big trouble's what we have. * not the case, big trouble's what we have.
*/ */
if (RelationGetNumberOfBlocks(index) != 0) if (RelationGetNumberOfBlocks(index) != 0)
elog(ERROR, "index \"%s\" already contains data", elog(ERROR, "index \"%s\" already contains data",
@ -141,12 +141,12 @@ hashinsert(PG_FUNCTION_ARGS)
/* /*
* If the single index key is null, we don't insert it into the index. * If the single index key is null, we don't insert it into the index.
* Hash tables support scans on '='. Relational algebra says that A = * Hash tables support scans on '='. Relational algebra says that A = B
* B returns null if either A or B is null. This means that no * returns null if either A or B is null. This means that no
* qualification used in an index scan could ever return true on a * qualification used in an index scan could ever return true on a null
* null attribute. It also means that indices can't be used by ISNULL * attribute. It also means that indices can't be used by ISNULL or
* or NOTNULL scans, but that's an artifact of the strategy map * NOTNULL scans, but that's an artifact of the strategy map architecture
* architecture chosen in 1986, not of the way nulls are handled here. * chosen in 1986, not of the way nulls are handled here.
*/ */
if (IndexTupleHasNulls(itup)) if (IndexTupleHasNulls(itup))
{ {
@ -180,16 +180,16 @@ hashgettuple(PG_FUNCTION_ARGS)
bool res; bool res;
/* /*
* We hold pin but not lock on current buffer while outside the hash * We hold pin but not lock on current buffer while outside the hash AM.
* AM. Reacquire the read lock here. * Reacquire the read lock here.
*/ */
if (BufferIsValid(so->hashso_curbuf)) if (BufferIsValid(so->hashso_curbuf))
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ); _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
/* /*
* If we've already initialized this scan, we can just advance it in * If we've already initialized this scan, we can just advance it in the
* the appropriate direction. If we haven't done so yet, we call a * appropriate direction. If we haven't done so yet, we call a routine to
* routine to get the first item in the scan. * get the first item in the scan.
*/ */
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(scan->currentItemData)))
{ {
@ -199,17 +199,16 @@ hashgettuple(PG_FUNCTION_ARGS)
if (scan->kill_prior_tuple) if (scan->kill_prior_tuple)
{ {
/* /*
* Yes, so mark it by setting the LP_DELETE bit in the item * Yes, so mark it by setting the LP_DELETE bit in the item flags.
* flags.
*/ */
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
page = BufferGetPage(so->hashso_curbuf); page = BufferGetPage(so->hashso_curbuf);
PageGetItemId(page, offnum)->lp_flags |= LP_DELETE; PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
/* /*
* Since this can be redone later if needed, it's treated the * Since this can be redone later if needed, it's treated the same
* same as a commit-hint-bit status update for heap tuples: we * as a commit-hint-bit status update for heap tuples: we mark the
* mark the buffer dirty but don't make a WAL log entry. * buffer dirty but don't make a WAL log entry.
*/ */
SetBufferCommitInfoNeedsSave(so->hashso_curbuf); SetBufferCommitInfoNeedsSave(so->hashso_curbuf);
} }
@ -265,8 +264,8 @@ hashgetmulti(PG_FUNCTION_ARGS)
int32 ntids = 0; int32 ntids = 0;
/* /*
* We hold pin but not lock on current buffer while outside the hash * We hold pin but not lock on current buffer while outside the hash AM.
* AM. Reacquire the read lock here. * Reacquire the read lock here.
*/ */
if (BufferIsValid(so->hashso_curbuf)) if (BufferIsValid(so->hashso_curbuf))
_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ); _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ);
@ -280,6 +279,7 @@ hashgetmulti(PG_FUNCTION_ARGS)
res = _hash_next(scan, ForwardScanDirection); res = _hash_next(scan, ForwardScanDirection);
else else
res = _hash_first(scan, ForwardScanDirection); res = _hash_first(scan, ForwardScanDirection);
/* /*
* Skip killed tuples if asked to. * Skip killed tuples if asked to.
*/ */
@ -505,12 +505,12 @@ hashbulkdelete(PG_FUNCTION_ARGS)
num_index_tuples = 0; num_index_tuples = 0;
/* /*
* Read the metapage to fetch original bucket and tuple counts. Also, * Read the metapage to fetch original bucket and tuple counts. Also, we
* we keep a copy of the last-seen metapage so that we can use its * keep a copy of the last-seen metapage so that we can use its
* hashm_spares[] values to compute bucket page addresses. This is a * hashm_spares[] values to compute bucket page addresses. This is a bit
* bit hokey but perfectly safe, since the interesting entries in the * hokey but perfectly safe, since the interesting entries in the spares
* spares array cannot change under us; and it beats rereading the * array cannot change under us; and it beats rereading the metapage for
* metapage for each bucket. * each bucket.
*/ */
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
metap = (HashMetaPage) BufferGetPage(metabuf); metap = (HashMetaPage) BufferGetPage(metabuf);
@ -641,8 +641,7 @@ loop_top:
{ {
/* /*
* Otherwise, our count is untrustworthy since we may have * Otherwise, our count is untrustworthy since we may have
* double-scanned tuples in split buckets. Proceed by * double-scanned tuples in split buckets. Proceed by dead-reckoning.
* dead-reckoning.
*/ */
if (metap->hashm_ntuples > tuples_removed) if (metap->hashm_ntuples > tuples_removed)
metap->hashm_ntuples -= tuples_removed; metap->hashm_ntuples -= tuples_removed;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.44 2005/05/25 21:40:40 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.45 2005/10/15 02:49:08 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
@ -46,11 +46,11 @@ hashint8(PG_FUNCTION_ARGS)
{ {
/* /*
* The idea here is to produce a hash value compatible with the values * The idea here is to produce a hash value compatible with the values
* produced by hashint4 and hashint2 for logically equivalent inputs; * produced by hashint4 and hashint2 for logically equivalent inputs; this
* this is necessary if we ever hope to support cross-type hash joins * is necessary if we ever hope to support cross-type hash joins across
* across these input types. Since all three types are signed, we can * these input types. Since all three types are signed, we can xor the
* xor the high half of the int8 value if the sign is positive, or the * high half of the int8 value if the sign is positive, or the complement
* complement of the high half when the sign is negative. * of the high half when the sign is negative.
*/ */
#ifndef INT64_IS_BUSTED #ifndef INT64_IS_BUSTED
int64 val = PG_GETARG_INT64(0); int64 val = PG_GETARG_INT64(0);
@ -78,9 +78,9 @@ hashfloat4(PG_FUNCTION_ARGS)
float4 key = PG_GETARG_FLOAT4(0); float4 key = PG_GETARG_FLOAT4(0);
/* /*
* On IEEE-float machines, minus zero and zero have different bit * On IEEE-float machines, minus zero and zero have different bit patterns
* patterns but should compare as equal. We must ensure that they * but should compare as equal. We must ensure that they have the same
* have the same hash value, which is most easily done this way: * hash value, which is most easily done this way:
*/ */
if (key == (float4) 0) if (key == (float4) 0)
PG_RETURN_UINT32(0); PG_RETURN_UINT32(0);
@ -94,9 +94,9 @@ hashfloat8(PG_FUNCTION_ARGS)
float8 key = PG_GETARG_FLOAT8(0); float8 key = PG_GETARG_FLOAT8(0);
/* /*
* On IEEE-float machines, minus zero and zero have different bit * On IEEE-float machines, minus zero and zero have different bit patterns
* patterns but should compare as equal. We must ensure that they * but should compare as equal. We must ensure that they have the same
* have the same hash value, which is most easily done this way: * hash value, which is most easily done this way:
*/ */
if (key == (float8) 0) if (key == (float8) 0)
PG_RETURN_UINT32(0); PG_RETURN_UINT32(0);
@ -126,8 +126,7 @@ hashname(PG_FUNCTION_ARGS)
char *key = NameStr(*PG_GETARG_NAME(0)); char *key = NameStr(*PG_GETARG_NAME(0));
int keylen = strlen(key); int keylen = strlen(key);
Assert(keylen < NAMEDATALEN); /* else it's not truncated Assert(keylen < NAMEDATALEN); /* else it's not truncated correctly */
* correctly */
return hash_any((unsigned char *) key, keylen); return hash_any((unsigned char *) key, keylen);
} }
@ -139,8 +138,8 @@ hashtext(PG_FUNCTION_ARGS)
Datum result; Datum result;
/* /*
* Note: this is currently identical in behavior to hashvarlena, but * Note: this is currently identical in behavior to hashvarlena, but it
* it seems likely that we may need to do something different in non-C * seems likely that we may need to do something different in non-C
* locales. (See also hashbpchar, if so.) * locales. (See also hashbpchar, if so.)
*/ */
result = hash_any((unsigned char *) VARDATA(key), result = hash_any((unsigned char *) VARDATA(key),

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.37 2005/08/10 21:36:45 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.38 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -50,8 +50,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
bool isnull; bool isnull;
/* /*
* Compute the hash key for the item. We do this first so as not to * Compute the hash key for the item. We do this first so as not to need
* need to hold any locks while running the hash function. * to hold any locks while running the hash function.
*/ */
itup = &(hitem->hash_itup); itup = &(hitem->hash_itup);
if (rel->rd_rel->relnatts != 1) if (rel->rd_rel->relnatts != 1)
@ -64,12 +64,12 @@ _hash_doinsert(Relation rel, HashItem hitem)
itemsz = IndexTupleDSize(hitem->hash_itup) itemsz = IndexTupleDSize(hitem->hash_itup)
+ (sizeof(HashItemData) - sizeof(IndexTupleData)); + (sizeof(HashItemData) - sizeof(IndexTupleData));
itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we
* we need to be consistent */ * need to be consistent */
/* /*
* Acquire shared split lock so we can compute the target bucket * Acquire shared split lock so we can compute the target bucket safely
* safely (see README). * (see README).
*/ */
_hash_getlock(rel, 0, HASH_SHARE); _hash_getlock(rel, 0, HASH_SHARE);
@ -79,9 +79,9 @@ _hash_doinsert(Relation rel, HashItem hitem)
_hash_checkpage(rel, (Page) metap, LH_META_PAGE); _hash_checkpage(rel, (Page) metap, LH_META_PAGE);
/* /*
* Check whether the item can fit on a hash page at all. (Eventually, * Check whether the item can fit on a hash page at all. (Eventually, we
* we ought to try to apply TOAST methods if not.) Note that at this * ought to try to apply TOAST methods if not.) Note that at this point,
* point, itemsz doesn't include the ItemId. * itemsz doesn't include the ItemId.
*/ */
if (itemsz > HashMaxItemSize((Page) metap)) if (itemsz > HashMaxItemSize((Page) metap))
ereport(ERROR, ereport(ERROR,
@ -105,8 +105,7 @@ _hash_doinsert(Relation rel, HashItem hitem)
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
/* /*
* Acquire share lock on target bucket; then we can release split * Acquire share lock on target bucket; then we can release split lock.
* lock.
*/ */
_hash_getlock(rel, blkno, HASH_SHARE); _hash_getlock(rel, blkno, HASH_SHARE);
@ -130,8 +129,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
if (BlockNumberIsValid(nextblkno)) if (BlockNumberIsValid(nextblkno))
{ {
/* /*
* ovfl page exists; go get it. if it doesn't have room, * ovfl page exists; go get it. if it doesn't have room, we'll
* we'll find out next pass through the loop test above. * find out next pass through the loop test above.
*/ */
_hash_relbuf(rel, buf); _hash_relbuf(rel, buf);
buf = _hash_getbuf(rel, nextblkno, HASH_WRITE); buf = _hash_getbuf(rel, nextblkno, HASH_WRITE);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.46 2005/05/11 01:26:01 neilc Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.47 2005/10/15 02:49:08 momjian Exp $
* *
* NOTES * NOTES
* Overflow pages look like ordinary relation pages. * Overflow pages look like ordinary relation pages.
@ -44,8 +44,8 @@ bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
/* loop */ ; /* loop */ ;
/* /*
* Convert to absolute page number by adding the number of bucket * Convert to absolute page number by adding the number of bucket pages
* pages that exist before this split point. * that exist before this split point.
*/ */
return (BlockNumber) ((1 << i) + ovflbitnum); return (BlockNumber) ((1 << i) + ovflbitnum);
} }
@ -252,10 +252,10 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
/* /*
* We create the new bitmap page with all pages marked "in use". * We create the new bitmap page with all pages marked "in use".
* Actually two pages in the new bitmap's range will exist * Actually two pages in the new bitmap's range will exist
* immediately: the bitmap page itself, and the following page * immediately: the bitmap page itself, and the following page which
* which is the one we return to the caller. Both of these are * is the one we return to the caller. Both of these are correctly
* correctly marked "in use". Subsequent pages do not exist yet, * marked "in use". Subsequent pages do not exist yet, but it is
* but it is convenient to pre-mark them as "in use" too. * convenient to pre-mark them as "in use" too.
*/ */
_hash_initbitmap(rel, metap, bitno_to_blkno(metap, bit)); _hash_initbitmap(rel, metap, bitno_to_blkno(metap, bit));
@ -265,8 +265,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
else else
{ {
/* /*
* Nothing to do here; since the page was past the last used page, * Nothing to do here; since the page was past the last used page, we
* we know its bitmap bit was preinitialized to "in use". * know its bitmap bit was preinitialized to "in use".
*/ */
} }
@ -275,8 +275,7 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
/* /*
* Adjust hashm_firstfree to avoid redundant searches. But don't risk * Adjust hashm_firstfree to avoid redundant searches. But don't risk
* changing it if someone moved it while we were searching bitmap * changing it if someone moved it while we were searching bitmap pages.
* pages.
*/ */
if (metap->hashm_firstfree == orig_firstfree) if (metap->hashm_firstfree == orig_firstfree)
metap->hashm_firstfree = bit + 1; metap->hashm_firstfree = bit + 1;
@ -305,8 +304,7 @@ found:
/* /*
* Adjust hashm_firstfree to avoid redundant searches. But don't risk * Adjust hashm_firstfree to avoid redundant searches. But don't risk
* changing it if someone moved it while we were searching bitmap * changing it if someone moved it while we were searching bitmap pages.
* pages.
*/ */
if (metap->hashm_firstfree == orig_firstfree) if (metap->hashm_firstfree == orig_firstfree)
{ {
@ -394,10 +392,10 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
_hash_wrtbuf(rel, ovflbuf); _hash_wrtbuf(rel, ovflbuf);
/* /*
* Fix up the bucket chain. this is a doubly-linked list, so we must * Fix up the bucket chain. this is a doubly-linked list, so we must fix
* fix up the bucket chain members behind and ahead of the overflow * up the bucket chain members behind and ahead of the overflow page being
* page being deleted. No concurrency issues since we hold exclusive * deleted. No concurrency issues since we hold exclusive lock on the
* lock on the entire bucket. * entire bucket.
*/ */
if (BlockNumberIsValid(prevblkno)) if (BlockNumberIsValid(prevblkno))
{ {
@ -488,12 +486,11 @@ _hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno)
/* /*
* It is okay to write-lock the new bitmap page while holding metapage * It is okay to write-lock the new bitmap page while holding metapage
* write lock, because no one else could be contending for the new * write lock, because no one else could be contending for the new page.
* page.
* *
* There is some loss of concurrency in possibly doing I/O for the new * There is some loss of concurrency in possibly doing I/O for the new page
* page while holding the metapage lock, but this path is taken so * while holding the metapage lock, but this path is taken so seldom that
* seldom that it's not worth worrying about. * it's not worth worrying about.
*/ */
buf = _hash_getbuf(rel, blkno, HASH_WRITE); buf = _hash_getbuf(rel, blkno, HASH_WRITE);
pg = BufferGetPage(buf); pg = BufferGetPage(buf);
@ -586,8 +583,8 @@ _hash_squeezebucket(Relation rel,
} }
/* /*
* find the last page in the bucket chain by starting at the base * find the last page in the bucket chain by starting at the base bucket
* bucket page and working forward. * page and working forward.
*/ */
ropaque = wopaque; ropaque = wopaque;
do do
@ -655,22 +652,21 @@ _hash_squeezebucket(Relation rel,
/* /*
* delete the tuple from the "read" page. PageIndexTupleDelete * delete the tuple from the "read" page. PageIndexTupleDelete
* repacks the ItemId array, so 'roffnum' will be "advanced" * repacks the ItemId array, so 'roffnum' will be "advanced" to
* to the "next" ItemId. * the "next" ItemId.
*/ */
PageIndexTupleDelete(rpage, roffnum); PageIndexTupleDelete(rpage, roffnum);
} }
/* /*
* if the "read" page is now empty because of the deletion (or * if the "read" page is now empty because of the deletion (or because
* because it was empty when we got to it), free it. * it was empty when we got to it), free it.
* *
* Tricky point here: if our read and write pages are adjacent in the * Tricky point here: if our read and write pages are adjacent in the
* bucket chain, our write lock on wbuf will conflict with * bucket chain, our write lock on wbuf will conflict with
* _hash_freeovflpage's attempt to update the sibling links of the * _hash_freeovflpage's attempt to update the sibling links of the
* removed page. However, in that case we are done anyway, so we * removed page. However, in that case we are done anyway, so we can
* can simply drop the write lock before calling * simply drop the write lock before calling _hash_freeovflpage.
* _hash_freeovflpage.
*/ */
if (PageIsEmpty(rpage)) if (PageIsEmpty(rpage))
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.51 2005/06/09 21:01:25 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.52 2005/10/15 02:49:08 momjian Exp $
* *
* NOTES * NOTES
* Postgres hash pages look like ordinary relation pages. The opaque * Postgres hash pages look like ordinary relation pages. The opaque
@ -240,10 +240,10 @@ _hash_metapinit(Relation rel)
RelationGetRelationName(rel)); RelationGetRelationName(rel));
/* /*
* Determine the target fill factor (tuples per bucket) for this * Determine the target fill factor (tuples per bucket) for this index.
* index. The idea is to make the fill factor correspond to pages * The idea is to make the fill factor correspond to pages about 3/4ths
* about 3/4ths full. We can compute it exactly if the index datatype * full. We can compute it exactly if the index datatype is fixed-width,
* is fixed-width, but for var-width there's some guessing involved. * but for var-width there's some guessing involved.
*/ */
data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid, data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid,
RelationGetDescr(rel)->attrs[0]->atttypmod); RelationGetDescr(rel)->attrs[0]->atttypmod);
@ -289,9 +289,8 @@ _hash_metapinit(Relation rel)
metap->hashm_procid = index_getprocid(rel, 1, HASHPROC); metap->hashm_procid = index_getprocid(rel, 1, HASHPROC);
/* /*
* We initialize the index with two buckets, 0 and 1, occupying * We initialize the index with two buckets, 0 and 1, occupying physical
* physical blocks 1 and 2. The first freespace bitmap page is in * blocks 1 and 2. The first freespace bitmap page is in block 3.
* block 3.
*/ */
metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */ metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */
metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */ metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */
@ -321,8 +320,8 @@ _hash_metapinit(Relation rel)
} }
/* /*
* Initialize first bitmap page. Can't do this until we create the * Initialize first bitmap page. Can't do this until we create the first
* first two buckets, else smgr will complain. * two buckets, else smgr will complain.
*/ */
_hash_initbitmap(rel, metap, 3); _hash_initbitmap(rel, metap, 3);
@ -367,15 +366,14 @@ _hash_expandtable(Relation rel, Buffer metabuf)
* Obtain the page-zero lock to assert the right to begin a split (see * Obtain the page-zero lock to assert the right to begin a split (see
* README). * README).
* *
* Note: deadlock should be impossible here. Our own backend could only * Note: deadlock should be impossible here. Our own backend could only be
* be holding bucket sharelocks due to stopped indexscans; those will * holding bucket sharelocks due to stopped indexscans; those will not
* not block other holders of the page-zero lock, who are only * block other holders of the page-zero lock, who are only interested in
* interested in acquiring bucket sharelocks themselves. Exclusive * acquiring bucket sharelocks themselves. Exclusive bucket locks are
* bucket locks are only taken here and in hashbulkdelete, and neither * only taken here and in hashbulkdelete, and neither of these operations
* of these operations needs any additional locks to complete. (If, * needs any additional locks to complete. (If, due to some flaw in this
* due to some flaw in this reasoning, we manage to deadlock anyway, * reasoning, we manage to deadlock anyway, it's okay to error out; the
* it's okay to error out; the index will be left in a consistent * index will be left in a consistent state.)
* state.)
*/ */
_hash_getlock(rel, 0, HASH_EXCLUSIVE); _hash_getlock(rel, 0, HASH_EXCLUSIVE);
@ -386,8 +384,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
_hash_checkpage(rel, (Page) metap, LH_META_PAGE); _hash_checkpage(rel, (Page) metap, LH_META_PAGE);
/* /*
* Check to see if split is still needed; someone else might have * Check to see if split is still needed; someone else might have already
* already done one while we waited for the lock. * done one while we waited for the lock.
* *
* Make sure this stays in sync with _hash_doinsert() * Make sure this stays in sync with _hash_doinsert()
*/ */
@ -402,11 +400,11 @@ _hash_expandtable(Relation rel, Buffer metabuf)
* The lock protects us against other backends, but not against our own * The lock protects us against other backends, but not against our own
* backend. Must check for active scans separately. * backend. Must check for active scans separately.
* *
* Ideally we would lock the new bucket too before proceeding, but if we * Ideally we would lock the new bucket too before proceeding, but if we are
* are about to cross a splitpoint then the BUCKET_TO_BLKNO mapping * about to cross a splitpoint then the BUCKET_TO_BLKNO mapping isn't
* isn't correct yet. For simplicity we update the metapage first and * correct yet. For simplicity we update the metapage first and then
* then lock. This should be okay because no one else should be * lock. This should be okay because no one else should be trying to lock
* trying to lock the new bucket yet... * the new bucket yet...
*/ */
new_bucket = metap->hashm_maxbucket + 1; new_bucket = metap->hashm_maxbucket + 1;
old_bucket = (new_bucket & metap->hashm_lowmask); old_bucket = (new_bucket & metap->hashm_lowmask);
@ -420,14 +418,13 @@ _hash_expandtable(Relation rel, Buffer metabuf)
goto fail; goto fail;
/* /*
* Okay to proceed with split. Update the metapage bucket mapping * Okay to proceed with split. Update the metapage bucket mapping info.
* info.
* *
* Since we are scribbling on the metapage data right in the shared * Since we are scribbling on the metapage data right in the shared buffer,
* buffer, any failure in this next little bit leaves us with a big * any failure in this next little bit leaves us with a big problem: the
* problem: the metapage is effectively corrupt but could get written * metapage is effectively corrupt but could get written back to disk. We
* back to disk. We don't really expect any failure, but just to be * don't really expect any failure, but just to be sure, establish a
* sure, establish a critical section. * critical section.
*/ */
START_CRIT_SECTION(); START_CRIT_SECTION();
@ -443,8 +440,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
/* /*
* If the split point is increasing (hashm_maxbucket's log base 2 * If the split point is increasing (hashm_maxbucket's log base 2
* increases), we need to adjust the hashm_spares[] array and * increases), we need to adjust the hashm_spares[] array and
* hashm_ovflpoint so that future overflow pages will be created * hashm_ovflpoint so that future overflow pages will be created beyond
* beyond this new batch of bucket pages. * this new batch of bucket pages.
* *
* XXX should initialize new bucket pages to prevent out-of-order page * XXX should initialize new bucket pages to prevent out-of-order page
* creation? Don't wanna do it right here though. * creation? Don't wanna do it right here though.
@ -471,10 +468,9 @@ _hash_expandtable(Relation rel, Buffer metabuf)
/* /*
* Copy bucket mapping info now; this saves re-accessing the meta page * Copy bucket mapping info now; this saves re-accessing the meta page
* inside _hash_splitbucket's inner loop. Note that once we drop the * inside _hash_splitbucket's inner loop. Note that once we drop the
* split lock, other splits could begin, so these values might be out * split lock, other splits could begin, so these values might be out of
* of date before _hash_splitbucket finishes. That's okay, since all * date before _hash_splitbucket finishes. That's okay, since all it
* it needs is to tell which of these two buckets to map hashkeys * needs is to tell which of these two buckets to map hashkeys into.
* into.
*/ */
maxbucket = metap->hashm_maxbucket; maxbucket = metap->hashm_maxbucket;
highmask = metap->hashm_highmask; highmask = metap->hashm_highmask;
@ -554,9 +550,9 @@ _hash_splitbucket(Relation rel,
TupleDesc itupdesc = RelationGetDescr(rel); TupleDesc itupdesc = RelationGetDescr(rel);
/* /*
* It should be okay to simultaneously write-lock pages from each * It should be okay to simultaneously write-lock pages from each bucket,
* bucket, since no one else can be trying to acquire buffer lock on * since no one else can be trying to acquire buffer lock on pages of
* pages of either bucket. * either bucket.
*/ */
oblkno = start_oblkno; oblkno = start_oblkno;
nblkno = start_nblkno; nblkno = start_nblkno;
@ -578,17 +574,17 @@ _hash_splitbucket(Relation rel,
nopaque->hasho_filler = HASHO_FILL; nopaque->hasho_filler = HASHO_FILL;
/* /*
* Partition the tuples in the old bucket between the old bucket and * Partition the tuples in the old bucket between the old bucket and the
* the new bucket, advancing along the old bucket's overflow bucket * new bucket, advancing along the old bucket's overflow bucket chain and
* chain and adding overflow pages to the new bucket as needed. * adding overflow pages to the new bucket as needed.
*/ */
ooffnum = FirstOffsetNumber; ooffnum = FirstOffsetNumber;
omaxoffnum = PageGetMaxOffsetNumber(opage); omaxoffnum = PageGetMaxOffsetNumber(opage);
for (;;) for (;;)
{ {
/* /*
* at each iteration through this loop, each of these variables * at each iteration through this loop, each of these variables should
* should be up-to-date: obuf opage oopaque ooffnum omaxoffnum * be up-to-date: obuf opage oopaque ooffnum omaxoffnum
*/ */
/* check if we're at the end of the page */ /* check if we're at the end of the page */
@ -600,8 +596,8 @@ _hash_splitbucket(Relation rel,
break; break;
/* /*
* we ran out of tuples on this particular page, but we have * we ran out of tuples on this particular page, but we have more
* more overflow pages; advance to next page. * overflow pages; advance to next page.
*/ */
_hash_wrtbuf(rel, obuf); _hash_wrtbuf(rel, obuf);
@ -618,8 +614,7 @@ _hash_splitbucket(Relation rel,
* Re-hash the tuple to determine which bucket it now belongs in. * Re-hash the tuple to determine which bucket it now belongs in.
* *
* It is annoying to call the hash function while holding locks, but * It is annoying to call the hash function while holding locks, but
* releasing and relocking the page for each tuple is unappealing * releasing and relocking the page for each tuple is unappealing too.
* too.
*/ */
hitem = (HashItem) PageGetItem(opage, PageGetItemId(opage, ooffnum)); hitem = (HashItem) PageGetItem(opage, PageGetItemId(opage, ooffnum));
itup = &(hitem->hash_itup); itup = &(hitem->hash_itup);
@ -632,9 +627,9 @@ _hash_splitbucket(Relation rel,
if (bucket == nbucket) if (bucket == nbucket)
{ {
/* /*
* insert the tuple into the new bucket. if it doesn't fit on * insert the tuple into the new bucket. if it doesn't fit on the
* the current page in the new bucket, we must allocate a new * current page in the new bucket, we must allocate a new overflow
* overflow page and place the tuple on that page instead. * page and place the tuple on that page instead.
*/ */
itemsz = IndexTupleDSize(hitem->hash_itup) itemsz = IndexTupleDSize(hitem->hash_itup)
+ (sizeof(HashItemData) - sizeof(IndexTupleData)); + (sizeof(HashItemData) - sizeof(IndexTupleData));
@ -659,13 +654,13 @@ _hash_splitbucket(Relation rel,
RelationGetRelationName(rel)); RelationGetRelationName(rel));
/* /*
* now delete the tuple from the old bucket. after this * now delete the tuple from the old bucket. after this section
* section of code, 'ooffnum' will actually point to the * of code, 'ooffnum' will actually point to the ItemId to which
* ItemId to which we would point if we had advanced it before * we would point if we had advanced it before the deletion
* the deletion (PageIndexTupleDelete repacks the ItemId * (PageIndexTupleDelete repacks the ItemId array). this also
* array). this also means that 'omaxoffnum' is exactly one * means that 'omaxoffnum' is exactly one less than it used to be,
* less than it used to be, so we really can just decrement it * so we really can just decrement it instead of calling
* instead of calling PageGetMaxOffsetNumber. * PageGetMaxOffsetNumber.
*/ */
PageIndexTupleDelete(opage, ooffnum); PageIndexTupleDelete(opage, ooffnum);
omaxoffnum = OffsetNumberPrev(omaxoffnum); omaxoffnum = OffsetNumberPrev(omaxoffnum);
@ -673,9 +668,9 @@ _hash_splitbucket(Relation rel,
else else
{ {
/* /*
* the tuple stays on this page. we didn't move anything, so * the tuple stays on this page. we didn't move anything, so we
* we didn't delete anything and therefore we don't have to * didn't delete anything and therefore we don't have to change
* change 'omaxoffnum'. * 'omaxoffnum'.
*/ */
Assert(bucket == obucket); Assert(bucket == obucket);
ooffnum = OffsetNumberNext(ooffnum); ooffnum = OffsetNumberNext(ooffnum);
@ -683,11 +678,10 @@ _hash_splitbucket(Relation rel,
} }
/* /*
* We're at the end of the old bucket chain, so we're done * We're at the end of the old bucket chain, so we're done partitioning
* partitioning the tuples. Before quitting, call _hash_squeezebucket * the tuples. Before quitting, call _hash_squeezebucket to ensure the
* to ensure the tuples remaining in the old bucket (including the * tuples remaining in the old bucket (including the overflow pages) are
* overflow pages) are packed as tightly as possible. The new bucket * packed as tightly as possible. The new bucket is already tight.
* is already tight.
*/ */
_hash_wrtbuf(rel, obuf); _hash_wrtbuf(rel, obuf);
_hash_wrtbuf(rel, nbuf); _hash_wrtbuf(rel, nbuf);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashscan.c,v 1.38 2004/12/31 21:59:13 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashscan.c,v 1.39 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -44,9 +44,9 @@ ReleaseResources_hash(void)
HashScanList next; HashScanList next;
/* /*
* Note: this should be a no-op during normal query shutdown. However, * Note: this should be a no-op during normal query shutdown. However, in
* in an abort situation ExecutorEnd is not called and so there may be * an abort situation ExecutorEnd is not called and so there may be open
* open index scans to clean up. * index scans to clean up.
*/ */
prev = NULL; prev = NULL;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.39 2005/10/06 02:29:08 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.40 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -137,11 +137,10 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
/* /*
* We do not support hash scans with no index qualification, because * We do not support hash scans with no index qualification, because we
* we would have to read the whole index rather than just one bucket. * would have to read the whole index rather than just one bucket. That
* That creates a whole raft of problems, since we haven't got a * creates a whole raft of problems, since we haven't got a practical way
* practical way to lock all the buckets against splits or * to lock all the buckets against splits or compactions.
* compactions.
*/ */
if (scan->numberOfKeys < 1) if (scan->numberOfKeys < 1)
ereport(ERROR, ereport(ERROR,
@ -149,21 +148,21 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
errmsg("hash indexes do not support whole-index scans"))); errmsg("hash indexes do not support whole-index scans")));
/* /*
* If the constant in the index qual is NULL, assume it cannot match * If the constant in the index qual is NULL, assume it cannot match any
* any items in the index. * items in the index.
*/ */
if (scan->keyData[0].sk_flags & SK_ISNULL) if (scan->keyData[0].sk_flags & SK_ISNULL)
return false; return false;
/* /*
* Okay to compute the hash key. We want to do this before acquiring * Okay to compute the hash key. We want to do this before acquiring any
* any locks, in case a user-defined hash function happens to be slow. * locks, in case a user-defined hash function happens to be slow.
*/ */
hashkey = _hash_datum2hashkey(rel, scan->keyData[0].sk_argument); hashkey = _hash_datum2hashkey(rel, scan->keyData[0].sk_argument);
/* /*
* Acquire shared split lock so we can compute the target bucket * Acquire shared split lock so we can compute the target bucket safely
* safely (see README). * (see README).
*/ */
_hash_getlock(rel, 0, HASH_SHARE); _hash_getlock(rel, 0, HASH_SHARE);
@ -186,8 +185,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
_hash_relbuf(rel, metabuf); _hash_relbuf(rel, metabuf);
/* /*
* Acquire share lock on target bucket; then we can release split * Acquire share lock on target bucket; then we can release split lock.
* lock.
*/ */
_hash_getlock(rel, blkno, HASH_SHARE); _hash_getlock(rel, blkno, HASH_SHARE);
@ -263,9 +261,9 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
bucket = opaque->hasho_bucket; bucket = opaque->hasho_bucket;
/* /*
* If _hash_step is called from _hash_first, current will not be * If _hash_step is called from _hash_first, current will not be valid, so
* valid, so we can't dereference it. However, in that case, we * we can't dereference it. However, in that case, we presumably want to
* presumably want to start at the beginning/end of the page... * start at the beginning/end of the page...
*/ */
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
if (ItemPointerIsValid(current)) if (ItemPointerIsValid(current))
@ -276,8 +274,8 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
/* /*
* 'offnum' now points to the last tuple we have seen (if any). * 'offnum' now points to the last tuple we have seen (if any).
* *
* continue to step through tuples until: 1) we get to the end of the * continue to step through tuples until: 1) we get to the end of the bucket
* bucket chain or 2) we find a valid tuple. * chain or 2) we find a valid tuple.
*/ */
do do
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.199 2005/10/06 02:29:10 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.200 2005/10/15 02:49:08 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -272,8 +272,8 @@ heapgettup(Relation relation,
/* 'dir' is now non-zero */ /* 'dir' is now non-zero */
/* /*
* calculate line pointer and number of remaining items to check on * calculate line pointer and number of remaining items to check on this
* this page. * page.
*/ */
lpp = PageGetItemId(dp, lineoff); lpp = PageGetItemId(dp, lineoff);
if (dir < 0) if (dir < 0)
@ -282,8 +282,8 @@ heapgettup(Relation relation,
linesleft = lines - lineoff; linesleft = lines - lineoff;
/* /*
* advance the scan until we find a qualifying tuple or run out of * advance the scan until we find a qualifying tuple or run out of stuff
* stuff to scan * to scan
*/ */
for (;;) for (;;)
{ {
@ -321,15 +321,14 @@ heapgettup(Relation relation,
} }
else else
{ {
++lpp; /* move forward in this page's ItemId ++lpp; /* move forward in this page's ItemId array */
* array */
++lineoff; ++lineoff;
} }
} }
/* /*
* if we get here, it means we've exhausted the items on this page * if we get here, it means we've exhausted the items on this page and
* and it's time to move to the next. * it's time to move to the next.
*/ */
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
@ -506,15 +505,15 @@ relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
/* /*
* Check for shared-cache-inval messages before trying to open the * Check for shared-cache-inval messages before trying to open the
* relation. This is needed to cover the case where the name * relation. This is needed to cover the case where the name identifies a
* identifies a rel that has been dropped and recreated since the * rel that has been dropped and recreated since the start of our
* start of our transaction: if we don't flush the old syscache entry * transaction: if we don't flush the old syscache entry then we'll latch
* then we'll latch onto that entry and suffer an error when we do * onto that entry and suffer an error when we do LockRelation. Note that
* LockRelation. Note that relation_open does not need to do this, * relation_open does not need to do this, since a relation's OID never
* since a relation's OID never changes. * changes.
* *
* We skip this if asked for NoLock, on the assumption that the caller * We skip this if asked for NoLock, on the assumption that the caller has
* has already ensured some appropriate lock is held. * already ensured some appropriate lock is held.
*/ */
if (lockmode != NoLock) if (lockmode != NoLock)
AcceptInvalidationMessages(); AcceptInvalidationMessages();
@ -633,9 +632,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
/* /*
* increment relation ref count while scanning relation * increment relation ref count while scanning relation
* *
* This is just to make really sure the relcache entry won't go away * This is just to make really sure the relcache entry won't go away while
* while the scan has a pointer to it. Caller should be holding the * the scan has a pointer to it. Caller should be holding the rel open
* rel open anyway, so this is redundant in all normal scenarios... * anyway, so this is redundant in all normal scenarios...
*/ */
RelationIncrementReferenceCount(relation); RelationIncrementReferenceCount(relation);
@ -649,8 +648,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_nkeys = nkeys; scan->rs_nkeys = nkeys;
/* /*
* we do this here instead of in initscan() because heap_rescan also * we do this here instead of in initscan() because heap_rescan also calls
* calls initscan() and we don't want to allocate memory again * initscan() and we don't want to allocate memory again
*/ */
if (nkeys > 0) if (nkeys > 0)
scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
@ -763,8 +762,8 @@ heap_getnext(HeapScanDesc scan, ScanDirection direction)
} }
/* /*
* if we get here it means we have a new current scan tuple, so point * if we get here it means we have a new current scan tuple, so point to
* to the proper return buffer and return the tuple. * the proper return buffer and return the tuple.
*/ */
HEAPDEBUG_3; /* heap_getnext returning tuple */ HEAPDEBUG_3; /* heap_getnext returning tuple */
@ -859,8 +858,8 @@ heap_release_fetch(Relation relation,
dp = (PageHeader) BufferGetPage(buffer); dp = (PageHeader) BufferGetPage(buffer);
/* /*
* We'd better check for out-of-range offnum in case of VACUUM since * We'd better check for out-of-range offnum in case of VACUUM since the
* the TID was obtained. * TID was obtained.
*/ */
offnum = ItemPointerGetOffsetNumber(tid); offnum = ItemPointerGetOffsetNumber(tid);
if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp)) if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
@ -969,10 +968,10 @@ heap_get_latest_tid(Relation relation,
return; return;
/* /*
* Since this can be called with user-supplied TID, don't trust the * Since this can be called with user-supplied TID, don't trust the input
* input too much. (RelationGetNumberOfBlocks is an expensive check, * too much. (RelationGetNumberOfBlocks is an expensive check, so we
* so we don't check t_ctid links again this way. Note that it would * don't check t_ctid links again this way. Note that it would not do to
* not do to call it just once and save the result, either.) * call it just once and save the result, either.)
*/ */
blk = ItemPointerGetBlockNumber(tid); blk = ItemPointerGetBlockNumber(tid);
if (blk >= RelationGetNumberOfBlocks(relation)) if (blk >= RelationGetNumberOfBlocks(relation))
@ -980,9 +979,9 @@ heap_get_latest_tid(Relation relation,
blk, RelationGetRelationName(relation)); blk, RelationGetRelationName(relation));
/* /*
* Loop to chase down t_ctid links. At top of loop, ctid is the * Loop to chase down t_ctid links. At top of loop, ctid is the tuple we
* tuple we need to examine, and *tid is the TID we will return if * need to examine, and *tid is the TID we will return if ctid turns out
* ctid turns out to be bogus. * to be bogus.
* *
* Note that we will loop until we reach the end of the t_ctid chain. * Note that we will loop until we reach the end of the t_ctid chain.
* Depending on the snapshot passed, there might be at most one visible * Depending on the snapshot passed, there might be at most one visible
@ -1008,8 +1007,8 @@ heap_get_latest_tid(Relation relation,
/* /*
* Check for bogus item number. This is not treated as an error * Check for bogus item number. This is not treated as an error
* condition because it can happen while following a t_ctid link. * condition because it can happen while following a t_ctid link. We
* We just assume that the prior tid is OK and return it unchanged. * just assume that the prior tid is OK and return it unchanged.
*/ */
offnum = ItemPointerGetOffsetNumber(&ctid); offnum = ItemPointerGetOffsetNumber(&ctid);
if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp)) if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
@ -1102,13 +1101,12 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
#endif #endif
/* /*
* If the object id of this tuple has already been assigned, trust * If the object id of this tuple has already been assigned, trust the
* the caller. There are a couple of ways this can happen. At * caller. There are a couple of ways this can happen. At initial db
* initial db creation, the backend program sets oids for tuples. * creation, the backend program sets oids for tuples. When we define
* When we define an index, we set the oid. Finally, in the * an index, we set the oid. Finally, in the future, we may allow
* future, we may allow users to set their own object ids in order * users to set their own object ids in order to support a persistent
* to support a persistent object store (objects need to contain * object store (objects need to contain pointers to one another).
* pointers to one another).
*/ */
if (!OidIsValid(HeapTupleGetOid(tup))) if (!OidIsValid(HeapTupleGetOid(tup)))
HeapTupleSetOid(tup, GetNewOid(relation)); HeapTupleSetOid(tup, GetNewOid(relation));
@ -1129,8 +1127,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
/* /*
* If the new tuple is too big for storage or contains already toasted * If the new tuple is too big for storage or contains already toasted
* out-of-line attributes from some other relation, invoke the * out-of-line attributes from some other relation, invoke the toaster.
* toaster.
*/ */
if (HeapTupleHasExternal(tup) || if (HeapTupleHasExternal(tup) ||
(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD)) (MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
@ -1172,9 +1169,9 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
xlhdr.t_hoff = tup->t_data->t_hoff; xlhdr.t_hoff = tup->t_data->t_hoff;
/* /*
* note we mark rdata[1] as belonging to buffer; if XLogInsert * note we mark rdata[1] as belonging to buffer; if XLogInsert decides
* decides to write the whole page to the xlog, we don't need to * to write the whole page to the xlog, we don't need to store
* store xl_heap_header in the xlog. * xl_heap_header in the xlog.
*/ */
rdata[1].data = (char *) &xlhdr; rdata[1].data = (char *) &xlhdr;
rdata[1].len = SizeOfHeapHeader; rdata[1].len = SizeOfHeapHeader;
@ -1190,9 +1187,9 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
rdata[2].next = NULL; rdata[2].next = NULL;
/* /*
* If this is the single and first tuple on page, we can reinit * If this is the single and first tuple on page, we can reinit the
* the page instead of restoring the whole thing. Set flag, and * page instead of restoring the whole thing. Set flag, and hide
* hide buffer references from XLogInsert. * buffer references from XLogInsert.
*/ */
if (ItemPointerGetOffsetNumber(&(tup->t_self)) == FirstOffsetNumber && if (ItemPointerGetOffsetNumber(&(tup->t_self)) == FirstOffsetNumber &&
PageGetMaxOffsetNumber(page) == FirstOffsetNumber) PageGetMaxOffsetNumber(page) == FirstOffsetNumber)
@ -1213,10 +1210,10 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If tuple is cachable, mark it for invalidation from the caches in * If tuple is cachable, mark it for invalidation from the caches in case
* case we abort. Note it is OK to do this after WriteBuffer releases * we abort. Note it is OK to do this after WriteBuffer releases the
* the buffer, because the "tup" data structure is all in local * buffer, because the "tup" data structure is all in local memory, not in
* memory, not in the shared buffer. * the shared buffer.
*/ */
CacheInvalidateHeapTuple(relation, tup); CacheInvalidateHeapTuple(relation, tup);
@ -1310,13 +1307,13 @@ l1:
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
/* /*
* Acquire tuple lock to establish our priority for the tuple * Acquire tuple lock to establish our priority for the tuple (see
* (see heap_lock_tuple). LockTuple will release us when we are * heap_lock_tuple). LockTuple will release us when we are
* next-in-line for the tuple. * next-in-line for the tuple.
* *
* If we are forced to "start over" below, we keep the tuple lock; * If we are forced to "start over" below, we keep the tuple lock; this
* this arranges that we stay at the head of the line while * arranges that we stay at the head of the line while rechecking
* rechecking tuple state. * tuple state.
*/ */
if (!have_tuple_lock) if (!have_tuple_lock)
{ {
@ -1347,12 +1344,12 @@ l1:
goto l1; goto l1;
/* /*
* You might think the multixact is necessarily done here, but * You might think the multixact is necessarily done here, but not
* not so: it could have surviving members, namely our own xact * so: it could have surviving members, namely our own xact or
* or other subxacts of this backend. It is legal for us to * other subxacts of this backend. It is legal for us to delete
* delete the tuple in either case, however (the latter case is * the tuple in either case, however (the latter case is
* essentially a situation of upgrading our former shared lock * essentially a situation of upgrading our former shared lock to
* to exclusive). We don't bother changing the on-disk hint bits * exclusive). We don't bother changing the on-disk hint bits
* since we are about to overwrite the xmax altogether. * since we are about to overwrite the xmax altogether.
*/ */
} }
@ -1385,8 +1382,8 @@ l1:
} }
/* /*
* We may overwrite if previous xmax aborted, or if it committed * We may overwrite if previous xmax aborted, or if it committed but
* but only locked the tuple without updating it. * only locked the tuple without updating it.
*/ */
if (tp.t_data->t_infomask & (HEAP_XMAX_INVALID | if (tp.t_data->t_infomask & (HEAP_XMAX_INVALID |
HEAP_IS_LOCKED)) HEAP_IS_LOCKED))
@ -1467,18 +1464,18 @@ l1:
/* /*
* If the tuple has toasted out-of-line attributes, we need to delete * If the tuple has toasted out-of-line attributes, we need to delete
* those items too. We have to do this before WriteBuffer because we * those items too. We have to do this before WriteBuffer because we need
* need to look at the contents of the tuple, but it's OK to release * to look at the contents of the tuple, but it's OK to release the
* the context lock on the buffer first. * context lock on the buffer first.
*/ */
if (HeapTupleHasExternal(&tp)) if (HeapTupleHasExternal(&tp))
heap_tuple_toast_attrs(relation, NULL, &tp); heap_tuple_toast_attrs(relation, NULL, &tp);
/* /*
* Mark tuple for invalidation from system caches at next command * Mark tuple for invalidation from system caches at next command
* boundary. We have to do this before WriteBuffer because we need to * boundary. We have to do this before WriteBuffer because we need to look
* look at the contents of the tuple, so we need to hold our refcount * at the contents of the tuple, so we need to hold our refcount on the
* on the buffer. * buffer.
*/ */
CacheInvalidateHeapTuple(relation, &tp); CacheInvalidateHeapTuple(relation, &tp);
@ -1598,8 +1595,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
/* /*
* 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
* with the new tuple's location, so there's great risk of confusion * with the new tuple's location, so there's great risk of confusion if we
* if we use otid anymore. * use otid anymore.
*/ */
l2: l2:
@ -1623,13 +1620,13 @@ l2:
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
/* /*
* Acquire tuple lock to establish our priority for the tuple * Acquire tuple lock to establish our priority for the tuple (see
* (see heap_lock_tuple). LockTuple will release us when we are * heap_lock_tuple). LockTuple will release us when we are
* next-in-line for the tuple. * next-in-line for the tuple.
* *
* If we are forced to "start over" below, we keep the tuple lock; * If we are forced to "start over" below, we keep the tuple lock; this
* this arranges that we stay at the head of the line while * arranges that we stay at the head of the line while rechecking
* rechecking tuple state. * tuple state.
*/ */
if (!have_tuple_lock) if (!have_tuple_lock)
{ {
@ -1660,12 +1657,12 @@ l2:
goto l2; goto l2;
/* /*
* You might think the multixact is necessarily done here, but * You might think the multixact is necessarily done here, but not
* not so: it could have surviving members, namely our own xact * so: it could have surviving members, namely our own xact or
* or other subxacts of this backend. It is legal for us to * other subxacts of this backend. It is legal for us to update
* update the tuple in either case, however (the latter case is * the tuple in either case, however (the latter case is
* essentially a situation of upgrading our former shared lock * essentially a situation of upgrading our former shared lock to
* to exclusive). We don't bother changing the on-disk hint bits * exclusive). We don't bother changing the on-disk hint bits
* since we are about to overwrite the xmax altogether. * since we are about to overwrite the xmax altogether.
*/ */
} }
@ -1698,8 +1695,8 @@ l2:
} }
/* /*
* We may overwrite if previous xmax aborted, or if it committed * We may overwrite if previous xmax aborted, or if it committed but
* but only locked the tuple without updating it. * only locked the tuple without updating it.
*/ */
if (oldtup.t_data->t_infomask & (HEAP_XMAX_INVALID | if (oldtup.t_data->t_infomask & (HEAP_XMAX_INVALID |
HEAP_IS_LOCKED)) HEAP_IS_LOCKED))
@ -1753,15 +1750,15 @@ l2:
HeapTupleHeaderSetCmax(newtup->t_data, 0); /* for cleanliness */ HeapTupleHeaderSetCmax(newtup->t_data, 0); /* for cleanliness */
/* /*
* 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
* fit on the same page as the old, then we need to release the * on the same page as the old, then we need to release the context lock
* context lock (but not the pin!) on the old tuple's buffer while we * (but not the pin!) on the old tuple's buffer while we are off doing
* are off doing TOAST and/or table-file-extension work. We must mark * TOAST and/or table-file-extension work. We must mark the old tuple to
* the old tuple to show that it's already being updated, else other * show that it's already being updated, else other processes may try to
* processes may try to update it themselves. * update it themselves.
* *
* We need to invoke the toaster if there are already any out-of-line * We need to invoke the toaster if there are already any out-of-line toasted
* toasted values present, or if the new tuple is over-threshold. * values present, or if the new tuple is over-threshold.
*/ */
need_toast = (HeapTupleHasExternal(&oldtup) || need_toast = (HeapTupleHasExternal(&oldtup) ||
HeapTupleHasExternal(newtup) || HeapTupleHasExternal(newtup) ||
@ -1790,22 +1787,21 @@ l2:
} }
/* /*
* Now, do we need a new page for the tuple, or not? This is a * Now, do we need a new page for the tuple, or not? This is a bit
* bit tricky since someone else could have added tuples to the * tricky since someone else could have added tuples to the page while
* page while we weren't looking. We have to recheck the * we weren't looking. We have to recheck the available space after
* available space after reacquiring the buffer lock. But don't * reacquiring the buffer lock. But don't bother to do that if the
* bother to do that if the former amount of free space is still * former amount of free space is still not enough; it's unlikely
* not enough; it's unlikely there's more free now than before. * there's more free now than before.
* *
* What's more, if we need to get a new page, we will need to acquire * What's more, if we need to get a new page, we will need to acquire
* buffer locks on both old and new pages. To avoid deadlock * buffer locks on both old and new pages. To avoid deadlock against
* against some other backend trying to get the same two locks in * some other backend trying to get the same two locks in the other
* the other order, we must be consistent about the order we get * order, we must be consistent about the order we get the locks in.
* the locks in. We use the rule "lock the lower-numbered page of * We use the rule "lock the lower-numbered page of the relation
* the relation first". To implement this, we must do * first". To implement this, we must do RelationGetBufferForTuple
* RelationGetBufferForTuple while not holding the lock on the old * while not holding the lock on the old page, and we must rely on it
* page, and we must rely on it to get the locks on both pages in * to get the locks on both pages in the correct order.
* the correct order.
*/ */
if (newtupsize > pagefree) if (newtupsize > pagefree)
{ {
@ -1823,8 +1819,8 @@ l2:
{ {
/* /*
* Rats, it doesn't fit anymore. We must now unlock and * Rats, it doesn't fit anymore. We must now unlock and
* relock to avoid deadlock. Fortunately, this path * relock to avoid deadlock. Fortunately, this path should
* should seldom be taken. * seldom be taken.
*/ */
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
newbuf = RelationGetBufferForTuple(relation, newtup->t_len, newbuf = RelationGetBufferForTuple(relation, newtup->t_len,
@ -1845,9 +1841,9 @@ l2:
} }
/* /*
* At this point newbuf and buffer are both pinned and locked, and * At this point newbuf and buffer are both pinned and locked, and newbuf
* newbuf has enough space for the new tuple. If they are the same * has enough space for the new tuple. If they are the same buffer, only
* buffer, only one pin is held. * one pin is held.
*/ */
/* NO EREPORT(ERROR) from here till changes are logged */ /* NO EREPORT(ERROR) from here till changes are logged */
@ -1897,8 +1893,8 @@ l2:
/* /*
* Mark old tuple for invalidation from system caches at next command * Mark old tuple for invalidation from system caches at next command
* boundary. We have to do this before WriteBuffer because we need to * boundary. We have to do this before WriteBuffer because we need to look
* look at the contents of the tuple, so we need to hold our refcount. * at the contents of the tuple, so we need to hold our refcount.
*/ */
CacheInvalidateHeapTuple(relation, &oldtup); CacheInvalidateHeapTuple(relation, &oldtup);
@ -1907,10 +1903,10 @@ l2:
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If new tuple is cachable, mark it for invalidation from the caches * If new tuple is cachable, mark it for invalidation 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 the
* releases the buffer, because the "newtup" data structure is all in * buffer, because the "newtup" data structure is all in local memory, not
* local memory, not in the shared buffer. * in the shared buffer.
*/ */
CacheInvalidateHeapTuple(relation, newtup); CacheInvalidateHeapTuple(relation, newtup);
@ -2077,12 +2073,12 @@ l3:
/* /*
* Acquire tuple lock to establish our priority for the tuple. * Acquire tuple lock to establish our priority for the tuple.
* LockTuple will release us when we are next-in-line for the * LockTuple will release us when we are next-in-line for the tuple.
* tuple. We must do this even if we are share-locking. * We must do this even if we are share-locking.
* *
* If we are forced to "start over" below, we keep the tuple lock; * If we are forced to "start over" below, we keep the tuple lock; this
* this arranges that we stay at the head of the line while * arranges that we stay at the head of the line while rechecking
* rechecking tuple state. * tuple state.
*/ */
if (!have_tuple_lock) if (!have_tuple_lock)
{ {
@ -2108,8 +2104,8 @@ l3:
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* Make sure it's still a shared lock, else start over. (It's * Make sure it's still a shared lock, else start over. (It's OK
* OK if the ownership of the shared lock has changed, though.) * if the ownership of the shared lock has changed, though.)
*/ */
if (!(tuple->t_data->t_infomask & HEAP_XMAX_SHARED_LOCK)) if (!(tuple->t_data->t_infomask & HEAP_XMAX_SHARED_LOCK))
goto l3; goto l3;
@ -2131,9 +2127,9 @@ l3:
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* If xwait had just locked the tuple then some other xact * If xwait had just locked the tuple then some other xact could
* could update this tuple before we get to this point. * update this tuple before we get to this point. Check for xmax
* Check for xmax change, and start over if so. * change, and start over if so.
*/ */
if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetXmax(tuple->t_data), !TransactionIdEquals(HeapTupleHeaderGetXmax(tuple->t_data),
@ -2141,12 +2137,12 @@ l3:
goto l3; goto l3;
/* /*
* You might think the multixact is necessarily done here, but * You might think the multixact is necessarily done here, but not
* not so: it could have surviving members, namely our own xact * so: it could have surviving members, namely our own xact or
* or other subxacts of this backend. It is legal for us to * other subxacts of this backend. It is legal for us to lock the
* lock the tuple in either case, however. We don't bother * tuple in either case, however. We don't bother changing the
* changing the on-disk hint bits since we are about to * on-disk hint bits since we are about to overwrite the xmax
* overwrite the xmax altogether. * altogether.
*/ */
} }
else else
@ -2166,9 +2162,9 @@ l3:
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* xwait is done, but if xwait had just locked the tuple then * xwait is done, but if xwait had just locked the tuple then some
* some other xact could update this tuple before we get to * other xact could update this tuple before we get to this point.
* this point. Check for xmax change, and start over if so. * Check for xmax change, and start over if so.
*/ */
if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetXmax(tuple->t_data), !TransactionIdEquals(HeapTupleHeaderGetXmax(tuple->t_data),
@ -2188,10 +2184,10 @@ l3:
} }
/* /*
* We may lock if previous xmax aborted, or if it committed * We may lock if previous xmax aborted, or if it committed but only
* but only locked the tuple without updating it. The case where * locked the tuple without updating it. The case where we didn't
* we didn't wait because we are joining an existing shared lock * wait because we are joining an existing shared lock is correctly
* is correctly handled, too. * handled, too.
*/ */
if (tuple->t_data->t_infomask & (HEAP_XMAX_INVALID | if (tuple->t_data->t_infomask & (HEAP_XMAX_INVALID |
HEAP_IS_LOCKED)) HEAP_IS_LOCKED))
@ -2213,9 +2209,9 @@ l3:
} }
/* /*
* Compute the new xmax and infomask to store into the tuple. Note we * Compute the new xmax and infomask to store into the tuple. Note we do
* do not modify the tuple just yet, because that would leave it in the * not modify the tuple just yet, because that would leave it in the wrong
* wrong state if multixact.c elogs. * state if multixact.c elogs.
*/ */
xid = GetCurrentTransactionId(); xid = GetCurrentTransactionId();
@ -2234,12 +2230,11 @@ l3:
/* /*
* If this is the first acquisition of a shared lock in the current * If this is the first acquisition of a shared lock in the current
* transaction, set my per-backend OldestMemberMXactId setting. * transaction, set my per-backend OldestMemberMXactId setting. We can
* We can be certain that the transaction will never become a * be certain that the transaction will never become a member of any
* member of any older MultiXactIds than that. (We have to do this * older MultiXactIds than that. (We have to do this even if we end
* even if we end up just using our own TransactionId below, since * up just using our own TransactionId below, since some other backend
* some other backend could incorporate our XID into a MultiXact * could incorporate our XID into a MultiXact immediately afterwards.)
* immediately afterwards.)
*/ */
MultiXactIdSetOldestMember(); MultiXactIdSetOldestMember();
@ -2249,14 +2244,14 @@ l3:
* Check to see if we need a MultiXactId because there are multiple * Check to see if we need a MultiXactId because there are multiple
* lockers. * lockers.
* *
* HeapTupleSatisfiesUpdate will have set the HEAP_XMAX_INVALID * HeapTupleSatisfiesUpdate will have set the HEAP_XMAX_INVALID bit if
* bit if the xmax was a MultiXactId but it was not running anymore. * the xmax was a MultiXactId but it was not running anymore. There is
* There is a race condition, which is that the MultiXactId may have * a race condition, which is that the MultiXactId may have finished
* finished since then, but that uncommon case is handled within * since then, but that uncommon case is handled within
* MultiXactIdExpand. * MultiXactIdExpand.
* *
* There is a similar race condition possible when the old xmax was * There is a similar race condition possible when the old xmax was a
* a regular TransactionId. We test TransactionIdIsInProgress again * regular TransactionId. We test TransactionIdIsInProgress again
* just to narrow the window, but it's still possible to end up * just to narrow the window, but it's still possible to end up
* creating an unnecessary MultiXactId. Fortunately this is harmless. * creating an unnecessary MultiXactId. Fortunately this is harmless.
*/ */
@ -2278,9 +2273,9 @@ l3:
/* /*
* If the old locker is ourselves, we'll just mark the * If the old locker is ourselves, we'll just mark the
* tuple again with our own TransactionId. However we * tuple again with our own TransactionId. However we
* have to consider the possibility that we had * have to consider the possibility that we had exclusive
* exclusive rather than shared lock before --- if so, * rather than shared lock before --- if so, be careful to
* be careful to preserve the exclusivity of the lock. * preserve the exclusivity of the lock.
*/ */
if (!(old_infomask & HEAP_XMAX_SHARED_LOCK)) if (!(old_infomask & HEAP_XMAX_SHARED_LOCK))
{ {
@ -2303,8 +2298,8 @@ l3:
else else
{ {
/* /*
* Can get here iff HeapTupleSatisfiesUpdate saw the old * Can get here iff HeapTupleSatisfiesUpdate saw the old xmax
* xmax as running, but it finished before * as running, but it finished before
* TransactionIdIsInProgress() got to run. Treat it like * TransactionIdIsInProgress() got to run. Treat it like
* there's no locker in the tuple. * there's no locker in the tuple.
*/ */
@ -2329,8 +2324,8 @@ l3:
/* /*
* Store transaction information of xact locking the tuple. * Store transaction information of xact locking the tuple.
* *
* Note: our CID is meaningless if storing a MultiXactId, but no harm * Note: our CID is meaningless if storing a MultiXactId, but no harm in
* in storing it anyway. * storing it anyway.
*/ */
tuple->t_data->t_infomask = new_infomask; tuple->t_data->t_infomask = new_infomask;
HeapTupleHeaderSetXmax(tuple->t_data, xid); HeapTupleHeaderSetXmax(tuple->t_data, xid);
@ -2473,8 +2468,8 @@ log_heap_clean(Relation reln, Buffer buffer, OffsetNumber *unused, int uncnt)
/* /*
* The unused-offsets array is not actually in the buffer, but pretend * The unused-offsets array is not actually in the buffer, but pretend
* that it is. When XLogInsert stores the whole buffer, the offsets * that it is. When XLogInsert stores the whole buffer, the offsets array
* array need not be stored too. * need not be stored too.
*/ */
if (uncnt > 0) if (uncnt > 0)
{ {
@ -2500,11 +2495,10 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup, bool move) Buffer newbuf, HeapTuple newtup, bool move)
{ {
/* /*
* Note: xlhdr is declared to have adequate size and correct alignment * Note: xlhdr is declared to have adequate size and correct alignment for
* for an xl_heap_header. However the two tids, if present at all, * an xl_heap_header. However the two tids, if present at all, will be
* will be packed in with no wasted space after the xl_heap_header; * packed in with no wasted space after the xl_heap_header; they aren't
* they aren't necessarily aligned as implied by this struct * necessarily aligned as implied by this struct declaration.
* declaration.
*/ */
struct struct
{ {
@ -2555,8 +2549,8 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
} }
/* /*
* As with insert records, we need not store the rdata[2] segment if * As with insert records, we need not store the rdata[2] segment if we
* we decide to store the whole buffer instead. * decide to store the whole buffer instead.
*/ */
rdata[2].data = (char *) &xlhdr; rdata[2].data = (char *) &xlhdr;
rdata[2].len = hsize; rdata[2].len = hsize;
@ -2655,8 +2649,8 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
Page page; Page page;
/* /*
* Note: the NEWPAGE log record is used for both heaps and indexes, so * Note: the NEWPAGE log record is used for both heaps and indexes, so do
* do not do anything that assumes we are touching a heap. * not do anything that assumes we are touching a heap.
*/ */
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.57 2005/06/20 18:37:01 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.58 2005/10/15 02:49:08 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -122,22 +122,20 @@ RelationGetBufferForTuple(Relation relation, Size len,
if (otherBuffer != InvalidBuffer) if (otherBuffer != InvalidBuffer)
otherBlock = BufferGetBlockNumber(otherBuffer); otherBlock = BufferGetBlockNumber(otherBuffer);
else else
otherBlock = InvalidBlockNumber; /* just to keep compiler otherBlock = InvalidBlockNumber; /* just to keep compiler quiet */
* quiet */
/* /*
* We first try to put the tuple on the same page we last inserted a * We first try to put the tuple on the same page we last inserted a tuple
* tuple on, as cached in the relcache entry. If that doesn't work, * on, as cached in the relcache entry. If that doesn't work, we ask the
* we ask the shared Free Space Map to locate a suitable page. Since * shared Free Space Map to locate a suitable page. Since the FSM's info
* the FSM's info might be out of date, we have to be prepared to loop * might be out of date, we have to be prepared to loop around and retry
* around and retry multiple times. (To insure this isn't an infinite * multiple times. (To insure this isn't an infinite loop, we must update
* loop, we must update the FSM with the correct amount of free space * the FSM with the correct amount of free space on each page that proves
* on each page that proves not to be suitable.) If the FSM has no * not to be suitable.) If the FSM has no record of a page with enough
* record of a page with enough free space, we give up and extend the * free space, we give up and extend the relation.
* relation.
* *
* When use_fsm is false, we either put the tuple onto the existing * When use_fsm is false, we either put the tuple onto the existing target
* target page or extend the relation. * page or extend the relation.
*/ */
targetBlock = relation->rd_targblock; targetBlock = relation->rd_targblock;
@ -151,9 +149,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
targetBlock = GetPageWithFreeSpace(&relation->rd_node, len); targetBlock = GetPageWithFreeSpace(&relation->rd_node, len);
/* /*
* If the FSM knows nothing of the rel, try the last page before * If the FSM knows nothing of the rel, try the last page before we
* we give up and extend. This avoids one-tuple-per-page syndrome * give up and extend. This avoids one-tuple-per-page syndrome during
* during bootstrapping or in a recently-started system. * bootstrapping or in a recently-started system.
*/ */
if (targetBlock == InvalidBlockNumber) if (targetBlock == InvalidBlockNumber)
{ {
@ -168,8 +166,8 @@ RelationGetBufferForTuple(Relation relation, Size len,
{ {
/* /*
* Read and exclusive-lock the target block, as well as the other * Read and exclusive-lock the target block, as well as the other
* block if one was given, taking suitable care with lock ordering * block if one was given, taking suitable care with lock ordering and
* and the possibility they are the same block. * the possibility they are the same block.
*/ */
if (otherBuffer == InvalidBuffer) if (otherBuffer == InvalidBuffer)
{ {
@ -199,8 +197,8 @@ RelationGetBufferForTuple(Relation relation, Size len,
} }
/* /*
* Now we can check to see if there's enough free space here. If * Now we can check to see if there's enough free space here. If so,
* so, we're done. * we're done.
*/ */
pageHeader = (Page) BufferGetPage(buffer); pageHeader = (Page) BufferGetPage(buffer);
pageFreeSpace = PageGetFreeSpace(pageHeader); pageFreeSpace = PageGetFreeSpace(pageHeader);
@ -213,9 +211,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
/* /*
* Not enough space, so we must give up our page locks and pin (if * Not enough space, so we must give up our page locks and pin (if
* any) and prepare to look elsewhere. We don't care which order * any) and prepare to look elsewhere. We don't care which order we
* we unlock the two buffers in, so this can be slightly simpler * unlock the two buffers in, so this can be slightly simpler than the
* than the code above. * code above.
*/ */
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
if (otherBuffer == InvalidBuffer) if (otherBuffer == InvalidBuffer)
@ -231,8 +229,8 @@ RelationGetBufferForTuple(Relation relation, Size len,
break; break;
/* /*
* Update FSM as to condition of this page, and ask for another * Update FSM as to condition of this page, and ask for another page
* page to try. * to try.
*/ */
targetBlock = RecordAndGetPageWithFreeSpace(&relation->rd_node, targetBlock = RecordAndGetPageWithFreeSpace(&relation->rd_node,
targetBlock, targetBlock,
@ -243,10 +241,10 @@ RelationGetBufferForTuple(Relation relation, Size len,
/* /*
* Have to extend the relation. * Have to extend the relation.
* *
* We have to use a lock to ensure no one else is extending the rel at * We have to use a lock to ensure no one else is extending the rel at the
* the same time, else we will both try to initialize the same new * same time, else we will both try to initialize the same new page. We
* page. We can skip locking for new or temp relations, however, * can skip locking for new or temp relations, however, since no one else
* since no one else could be accessing them. * could be accessing them.
*/ */
needLock = !RELATION_IS_LOCAL(relation); needLock = !RELATION_IS_LOCAL(relation);
@ -254,17 +252,16 @@ RelationGetBufferForTuple(Relation relation, Size len,
LockRelationForExtension(relation, ExclusiveLock); LockRelationForExtension(relation, ExclusiveLock);
/* /*
* XXX This does an lseek - rather expensive - but at the moment it is * XXX This does an lseek - rather expensive - but at the moment it is the
* the only way to accurately determine how many blocks are in a * only way to accurately determine how many blocks are in a relation. Is
* relation. Is it worth keeping an accurate file length in shared * it worth keeping an accurate file length in shared memory someplace,
* memory someplace, rather than relying on the kernel to do it for * rather than relying on the kernel to do it for us?
* us?
*/ */
buffer = ReadBuffer(relation, P_NEW); buffer = ReadBuffer(relation, P_NEW);
/* /*
* We can be certain that locking the otherBuffer first is OK, since * We can be certain that locking the otherBuffer first is OK, since it
* it must have a lower page number. * must have a lower page number.
*/ */
if (otherBuffer != InvalidBuffer) if (otherBuffer != InvalidBuffer)
LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE);
@ -275,10 +272,10 @@ RelationGetBufferForTuple(Relation relation, Size len,
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* Release the file-extension lock; it's now OK for someone else to * Release the file-extension lock; it's now OK for someone else to extend
* extend the relation some more. Note that we cannot release this * the relation some more. Note that we cannot release this lock before
* lock before we have buffer lock on the new page, or we risk a * we have buffer lock on the new page, or we risk a race condition
* race condition against vacuumlazy.c --- see comments therein. * against vacuumlazy.c --- see comments therein.
*/ */
if (needLock) if (needLock)
UnlockRelationForExtension(relation, ExclusiveLock); UnlockRelationForExtension(relation, ExclusiveLock);
@ -299,11 +296,11 @@ RelationGetBufferForTuple(Relation relation, Size len,
/* /*
* Remember the new page as our target for future insertions. * Remember the new page as our target for future insertions.
* *
* XXX should we enter the new page into the free space map immediately, * XXX should we enter the new page into the free space map immediately, or
* or just keep it for this backend's exclusive use in the short run * just keep it for this backend's exclusive use in the short run (until
* (until VACUUM sees it)? Seems to depend on whether you expect the * VACUUM sees it)? Seems to depend on whether you expect the current
* current backend to make more insertions or not, which is probably a * backend to make more insertions or not, which is probably a good bet
* good bet most of the time. So for now, don't add it to FSM yet. * most of the time. So for now, don't add it to FSM yet.
*/ */
relation->rd_targblock = BufferGetBlockNumber(buffer); relation->rd_targblock = BufferGetBlockNumber(buffer);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.52 2005/08/12 01:35:54 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.53 2005/10/15 02:49:09 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -90,8 +90,7 @@ heap_tuple_fetch_attr(varattrib *attr)
else else
{ {
/* /*
* This is a plain value inside of the main tuple - why am I * This is a plain value inside of the main tuple - why am I called?
* called?
*/ */
result = attr; result = attr;
} }
@ -154,8 +153,7 @@ heap_tuple_untoast_attr(varattrib *attr)
else else
/* /*
* This is a plain value inside of the main tuple - why am I * This is a plain value inside of the main tuple - why am I called?
* called?
*/ */
return attr; return attr;
@ -255,8 +253,8 @@ toast_raw_datum_size(Datum value)
else if (VARATT_IS_EXTERNAL(attr)) else if (VARATT_IS_EXTERNAL(attr))
{ {
/* /*
* an uncompressed external attribute has rawsize including the * an uncompressed external attribute has rawsize including the header
* header (not too consistent!) * (not too consistent!)
*/ */
result = attr->va_content.va_external.va_rawsize; result = attr->va_content.va_external.va_rawsize;
} }
@ -284,16 +282,16 @@ toast_datum_size(Datum value)
{ {
/* /*
* Attribute is stored externally - return the extsize whether * Attribute is stored externally - return the extsize whether
* compressed or not. We do not count the size of the toast * compressed or not. We do not count the size of the toast pointer
* pointer ... should we? * ... should we?
*/ */
result = attr->va_content.va_external.va_extsize; result = attr->va_content.va_external.va_extsize;
} }
else else
{ {
/* /*
* Attribute is stored inline either compressed or not, just * Attribute is stored inline either compressed or not, just calculate
* calculate the size of the datum in either case. * the size of the datum in either case.
*/ */
result = VARSIZE(attr); result = VARSIZE(attr);
} }
@ -321,12 +319,12 @@ toast_delete(Relation rel, HeapTuple oldtup)
* Get the tuple descriptor and break down the tuple into fields. * Get the tuple descriptor and break down the tuple into fields.
* *
* NOTE: it's debatable whether to use heap_deformtuple() here or just * NOTE: it's debatable whether to use heap_deformtuple() here or just
* heap_getattr() only the varlena columns. The latter could win if * heap_getattr() only the varlena columns. The latter could win if there
* there are few varlena columns and many non-varlena ones. However, * are few varlena columns and many non-varlena ones. However,
* heap_deformtuple costs only O(N) while the heap_getattr way would * heap_deformtuple costs only O(N) while the heap_getattr way would cost
* cost O(N^2) if there are many varlena columns, so it seems better * O(N^2) if there are many varlena columns, so it seems better to err on
* to err on the side of linear cost. (We won't even be here unless * the side of linear cost. (We won't even be here unless there's at
* there's at least one varlena column, by the way.) * least one varlena column, by the way.)
*/ */
tupleDesc = rel->rd_att; tupleDesc = rel->rd_att;
att = tupleDesc->attrs; att = tupleDesc->attrs;
@ -336,8 +334,8 @@ toast_delete(Relation rel, HeapTuple oldtup)
heap_deform_tuple(oldtup, tupleDesc, toast_values, toast_isnull); heap_deform_tuple(oldtup, tupleDesc, toast_values, toast_isnull);
/* /*
* Check for external stored attributes and delete them from the * Check for external stored attributes and delete them from the secondary
* secondary relation. * relation.
*/ */
for (i = 0; i < numAttrs; i++) for (i = 0; i < numAttrs; i++)
{ {
@ -447,9 +445,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
else else
{ {
/* /*
* This attribute isn't changed by this update so we * This attribute isn't changed by this update so we reuse
* reuse the original reference to the old value in * the original reference to the old value in the new
* the new tuple. * tuple.
*/ */
toast_action[i] = 'p'; toast_action[i] = 'p';
toast_sizes[i] = VARATT_SIZE(toast_values[i]); toast_sizes[i] = VARATT_SIZE(toast_values[i]);
@ -582,16 +580,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
else else
{ {
/* /*
* incompressible data, ignore on subsequent compression * incompressible data, ignore on subsequent compression passes
* passes
*/ */
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
} }
/* /*
* Second we look for attributes of attstorage 'x' or 'e' that are * Second we look for attributes of attstorage 'x' or 'e' that are still
* still inline. * inline.
*/ */
while (MAXALIGN(heap_compute_data_size(tupleDesc, while (MAXALIGN(heap_compute_data_size(tupleDesc,
toast_values, toast_isnull)) > toast_values, toast_isnull)) >
@ -696,8 +693,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
else else
{ {
/* /*
* incompressible data, ignore on subsequent compression * incompressible data, ignore on subsequent compression passes
* passes
*/ */
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
@ -755,8 +751,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
/* /*
* In the case we toasted any values, we need to build a new heap * In the case we toasted any values, we need to build a new heap tuple
* tuple with the changed values. * with the changed values.
*/ */
if (need_change) if (need_change)
{ {
@ -798,8 +794,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
has_nulls ? newtup->t_data->t_bits : NULL); has_nulls ? newtup->t_data->t_bits : NULL);
/* /*
* In the case we modified a previously modified tuple again, free * In the case we modified a previously modified tuple again, free the
* the memory from the previous run * memory from the previous run
*/ */
if ((char *) olddata != ((char *) newtup + HEAPTUPLESIZE)) if ((char *) olddata != ((char *) newtup + HEAPTUPLESIZE))
pfree(olddata); pfree(olddata);
@ -906,8 +902,8 @@ toast_flatten_tuple_attribute(Datum value,
return value; return value;
/* /*
* Calculate the new size of the tuple. Header size should not * Calculate the new size of the tuple. Header size should not change,
* change, but data size might. * but data size might.
*/ */
new_len = offsetof(HeapTupleHeaderData, t_bits); new_len = offsetof(HeapTupleHeaderData, t_bits);
if (has_nulls) if (has_nulls)
@ -1007,9 +1003,9 @@ toast_save_datum(Relation rel, Datum value)
int32 data_todo; int32 data_todo;
/* /*
* Open the toast relation and its index. We can use the index to * Open the toast relation and its index. We can use the index to check
* check uniqueness of the OID we assign to the toasted item, even * uniqueness of the OID we assign to the toasted item, even though it has
* though it has additional columns besides OID. * additional columns besides OID.
*/ */
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att; toasttupDesc = toastrel->rd_att;
@ -1082,11 +1078,11 @@ toast_save_datum(Relation rel, Datum value)
/* /*
* Create the index entry. We cheat a little here by not using * Create the index entry. We cheat a little here by not using
* FormIndexDatum: this relies on the knowledge that the index * FormIndexDatum: this relies on the knowledge that the index columns
* columns are the same as the initial columns of the table. * are the same as the initial columns of the table.
* *
* Note also that there had better not be any user-created index on * Note also that there had better not be any user-created index on the
* the TOAST table, since we don't bother to update anything else. * TOAST table, since we don't bother to update anything else.
*/ */
index_insert(toastidx, t_values, t_isnull, index_insert(toastidx, t_values, t_isnull,
&(toasttup->t_self), &(toasttup->t_self),
@ -1224,9 +1220,9 @@ toast_fetch_datum(varattrib *attr)
/* /*
* Read the chunks by index * Read the chunks by index
* *
* Note that because the index is actually on (valueid, chunkidx) we will * Note that because the index is actually on (valueid, chunkidx) we will see
* see the chunks in chunkidx order, even though we didn't explicitly * the chunks in chunkidx order, even though we didn't explicitly ask for
* ask for it. * it.
*/ */
nextidx = 0; nextidx = 0;
@ -1367,8 +1363,8 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
toastidx = index_open(toastrel->rd_rel->reltoastidxid); toastidx = index_open(toastrel->rd_rel->reltoastidxid);
/* /*
* Setup a scan key to fetch from the index. This is either two keys * Setup a scan key to fetch from the index. This is either two keys or
* or three depending on the number of chunks. * three depending on the number of chunks.
*/ */
ScanKeyInit(&toastkey[0], ScanKeyInit(&toastkey[0],
(AttrNumber) 1, (AttrNumber) 1,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.48 2005/05/27 23:31:20 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.49 2005/10/15 02:49:09 momjian Exp $
* *
* NOTES * NOTES
* many of the old access method routines have been turned into * many of the old access method routines have been turned into
@ -78,8 +78,8 @@ RelationGetIndexScan(Relation indexRelation,
scan->numberOfKeys = nkeys; scan->numberOfKeys = nkeys;
/* /*
* We allocate the key space here, but the AM is responsible for * We allocate the key space here, but the AM is responsible for actually
* actually filling it from the passed key array. * filling it from the passed key array.
*/ */
if (nkeys > 0) if (nkeys > 0)
scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
@ -203,8 +203,8 @@ systable_beginscan(Relation heapRelation,
/* /*
* Change attribute numbers to be index column numbers. * Change attribute numbers to be index column numbers.
* *
* This code could be generalized to search for the index key numbers * This code could be generalized to search for the index key numbers to
* to substitute, but for now there's no need. * substitute, but for now there's no need.
*/ */
for (i = 0; i < nkeys; i++) for (i = 0; i < nkeys; i++)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.85 2005/10/06 02:29:11 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.86 2005/10/15 02:49:09 momjian Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relation OID * index_open - open an index relation by relation OID
@ -241,8 +241,8 @@ index_beginscan(Relation heapRelation,
scan = index_beginscan_internal(indexRelation, nkeys, key); scan = index_beginscan_internal(indexRelation, nkeys, key);
/* /*
* Save additional parameters into the scandesc. Everything else was * Save additional parameters into the scandesc. Everything else was set
* set up by RelationGetIndexScan. * up by RelationGetIndexScan.
*/ */
scan->is_multiscan = false; scan->is_multiscan = false;
scan->heapRelation = heapRelation; scan->heapRelation = heapRelation;
@ -267,8 +267,8 @@ index_beginscan_multi(Relation indexRelation,
scan = index_beginscan_internal(indexRelation, nkeys, key); scan = index_beginscan_internal(indexRelation, nkeys, key);
/* /*
* Save additional parameters into the scandesc. Everything else was * Save additional parameters into the scandesc. Everything else was set
* set up by RelationGetIndexScan. * up by RelationGetIndexScan.
*/ */
scan->is_multiscan = true; scan->is_multiscan = true;
scan->xs_snapshot = snapshot; scan->xs_snapshot = snapshot;
@ -294,14 +294,14 @@ index_beginscan_internal(Relation indexRelation,
* Acquire AccessShareLock for the duration of the scan * Acquire AccessShareLock for the duration of the scan
* *
* Note: we could get an SI inval message here and consequently have to * Note: we could get an SI inval message here and consequently have to
* rebuild the relcache entry. The refcount increment above ensures * rebuild the relcache entry. The refcount increment above ensures that
* that we will rebuild it and not just flush it... * we will rebuild it and not just flush it...
*/ */
LockRelation(indexRelation, AccessShareLock); LockRelation(indexRelation, AccessShareLock);
/* /*
* LockRelation can clean rd_aminfo structure, so fill procedure * LockRelation can clean rd_aminfo structure, so fill procedure after
* after LockRelation * LockRelation
*/ */
GET_REL_PROCEDURE(ambeginscan); GET_REL_PROCEDURE(ambeginscan);
@ -425,8 +425,8 @@ index_restrpos(IndexScanDesc scan)
/* /*
* We do not reset got_tuple; so if the scan is actually being * We do not reset got_tuple; so if the scan is actually being
* short-circuited by index_getnext, the effective position * short-circuited by index_getnext, the effective position restoration is
* restoration is done by restoring unique_tuple_pos. * done by restoring unique_tuple_pos.
*/ */
scan->unique_tuple_pos = scan->unique_tuple_mark; scan->unique_tuple_pos = scan->unique_tuple_mark;
@ -454,19 +454,19 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
/* /*
* If we already got a tuple and it must be unique, there's no need to * If we already got a tuple and it must be unique, there's no need to
* make the index AM look through any additional tuples. (This can * make the index AM look through any additional tuples. (This can save a
* save a useful amount of work in scenarios where there are many dead * useful amount of work in scenarios where there are many dead tuples due
* tuples due to heavy update activity.) * to heavy update activity.)
* *
* To do this we must keep track of the logical scan position * To do this we must keep track of the logical scan position
* (before/on/after tuple). Also, we have to be sure to release scan * (before/on/after tuple). Also, we have to be sure to release scan
* resources before returning NULL; if we fail to do so then a * resources before returning NULL; if we fail to do so then a multi-index
* multi-index scan can easily run the system out of free buffers. We * scan can easily run the system out of free buffers. We can release
* can release index-level resources fairly cheaply by calling * index-level resources fairly cheaply by calling index_rescan. This
* index_rescan. This means there are two persistent states as far as * means there are two persistent states as far as the index AM is
* the index AM is concerned: on-tuple and rescanned. If we are * concerned: on-tuple and rescanned. If we are actually asked to
* actually asked to re-fetch the single tuple, we have to go through * re-fetch the single tuple, we have to go through a fresh indexscan
* a fresh indexscan startup, which penalizes that (infrequent) case. * startup, which penalizes that (infrequent) case.
*/ */
if (scan->keys_are_unique && scan->got_tuple) if (scan->keys_are_unique && scan->got_tuple)
{ {
@ -485,19 +485,18 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
if (new_tuple_pos == 0) if (new_tuple_pos == 0)
{ {
/* /*
* We are moving onto the unique tuple from having been off * We are moving onto the unique tuple from having been off it. We
* it. We just fall through and let the index AM do the work. * just fall through and let the index AM do the work. Note we
* Note we should get the right answer regardless of scan * should get the right answer regardless of scan direction.
* direction.
*/ */
scan->unique_tuple_pos = 0; /* need to update position */ scan->unique_tuple_pos = 0; /* need to update position */
} }
else else
{ {
/* /*
* Moving off the tuple; must do amrescan to release * Moving off the tuple; must do amrescan to release index-level
* index-level pins before we return NULL. Since index_rescan * pins before we return NULL. Since index_rescan will reset my
* will reset my state, must save and restore... * state, must save and restore...
*/ */
int unique_tuple_mark = scan->unique_tuple_mark; int unique_tuple_mark = scan->unique_tuple_mark;
@ -520,8 +519,7 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
bool found; bool found;
/* /*
* The AM's gettuple proc finds the next tuple matching the scan * The AM's gettuple proc finds the next tuple matching the scan keys.
* keys.
*/ */
found = DatumGetBool(FunctionCall2(procedure, found = DatumGetBool(FunctionCall2(procedure,
PointerGetDatum(scan), PointerGetDatum(scan),
@ -556,9 +554,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
continue; continue;
/* /*
* If we can't see it, maybe no one else can either. Check to see * If we can't see it, maybe no one else can either. Check to see if
* if the tuple is dead to all transactions. If so, signal the * the tuple is dead to all transactions. If so, signal the index AM
* index AM to not return it on future indexscans. * to not return it on future indexscans.
* *
* We told heap_release_fetch to keep a pin on the buffer, so we can * We told heap_release_fetch to keep a pin on the buffer, so we can
* re-access the tuple here. But we must re-lock the buffer first. * re-access the tuple here. But we must re-lock the buffer first.
@ -576,8 +574,8 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
scan->got_tuple = true; scan->got_tuple = true;
/* /*
* If we just fetched a known-unique tuple, then subsequent calls will * If we just fetched a known-unique tuple, then subsequent calls will go
* go through the short-circuit code above. unique_tuple_pos has been * through the short-circuit code above. unique_tuple_pos has been
* initialized to 0, which is the correct state ("on row"). * initialized to 0, which is the correct state ("on row").
*/ */
@ -805,11 +803,10 @@ index_getprocinfo(Relation irel,
procId = loc[procindex]; procId = loc[procindex];
/* /*
* Complain if function was not found during * Complain if function was not found during IndexSupportInitialize.
* IndexSupportInitialize. This should not happen unless the * This should not happen unless the system tables contain bogus
* system tables contain bogus entries for the index opclass. (If * entries for the index opclass. (If an AM wants to allow a support
* an AM wants to allow a support function to be optional, it can * function to be optional, it can use index_getprocid.)
* use index_getprocid.)
*/ */
if (!RegProcedureIsValid(procId)) if (!RegProcedureIsValid(procId))
elog(ERROR, "missing support function %d for attribute %d of index \"%s\"", elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.126 2005/10/12 17:18:03 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.127 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -93,30 +93,29 @@ top:
/* /*
* If the page was split between the time that we surrendered our read * If the page was split between the time that we surrendered our read
* lock and acquired our write lock, then this page may no longer be * lock and acquired our write lock, then this page may no longer be the
* the right place for the key we want to insert. In this case, we * right place for the key we want to insert. In this case, we need to
* need to move right in the tree. See Lehman and Yao for an * move right in the tree. See Lehman and Yao for an excruciatingly
* excruciatingly precise description. * precise description.
*/ */
buf = _bt_moveright(rel, buf, natts, itup_scankey, false, BT_WRITE); buf = _bt_moveright(rel, buf, natts, itup_scankey, false, BT_WRITE);
/* /*
* If we're not allowing duplicates, make sure the key isn't already * If we're not allowing duplicates, make sure the key isn't already in
* in the index. * the index.
* *
* NOTE: obviously, _bt_check_unique can only detect keys that are * NOTE: obviously, _bt_check_unique can only detect keys that are already in
* already in the index; so it cannot defend against concurrent * the index; so it cannot defend against concurrent insertions of the
* insertions of the same key. We protect against that by means of * same key. We protect against that by means of holding a write lock on
* holding a write lock on the target page. Any other would-be * the target page. Any other would-be inserter of the same key must
* inserter of the same key must acquire a write lock on the same * acquire a write lock on the same target page, so only one would-be
* target page, so only one would-be inserter can be making the check * inserter can be making the check at one time. Furthermore, once we are
* at one time. Furthermore, once we are past the check we hold write * past the check we hold write locks continuously until we have performed
* locks continuously until we have performed our insertion, so no * our insertion, so no later inserter can fail to see our insertion.
* later inserter can fail to see our insertion. (This requires some * (This requires some care in _bt_insertonpg.)
* care in _bt_insertonpg.)
* *
* If we must wait for another xact, we release the lock while waiting, * If we must wait for another xact, we release the lock while waiting, and
* and then must start over completely. * then must start over completely.
*/ */
if (index_is_unique) if (index_is_unique)
{ {
@ -167,8 +166,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 a * Find first item >= proposed new item. Note we could also get a pointer
* pointer to end-of-page here. * to end-of-page here.
*/ */
offset = _bt_binsrch(rel, buf, natts, itup_scankey, false); offset = _bt_binsrch(rel, buf, natts, itup_scankey, false);
@ -194,24 +193,24 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
/* /*
* We can skip items that are marked killed. * We can skip items that are marked killed.
* *
* Formerly, we applied _bt_isequal() before checking the kill * Formerly, we applied _bt_isequal() before checking the kill flag,
* flag, so as to fall out of the item loop as soon as * so as to fall out of the item loop as soon as possible.
* possible. However, in the presence of heavy update activity * However, in the presence of heavy update activity an index may
* an index may contain many killed items with the same key; * contain many killed items with the same key; running
* running _bt_isequal() on each killed item gets expensive. * _bt_isequal() on each killed item gets expensive. Furthermore
* Furthermore it is likely that the non-killed version of * it is likely that the non-killed version of each key appears
* each key appears first, so that we didn't actually get to * first, so that we didn't actually get to exit any sooner
* exit any sooner anyway. So now we just advance over killed * anyway. So now we just advance over killed items as quickly as
* items as quickly as we can. We only apply _bt_isequal() * we can. We only apply _bt_isequal() when we get to a non-killed
* when we get to a non-killed item or the end of the page. * item or the end of the page.
*/ */
if (!ItemIdDeleted(curitemid)) if (!ItemIdDeleted(curitemid))
{ {
/* /*
* _bt_compare returns 0 for (1,NULL) and (1,NULL) - * _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's
* this's how we handling NULLs - and so we must not use * how we handling NULLs - and so we must not use _bt_compare
* _bt_compare in real comparison, but only for * in real comparison, but only for ordering/finding items on
* ordering/finding items on pages. - vadim 03/24/97 * pages. - vadim 03/24/97
*/ */
if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey)) if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey))
break; /* we're past all the equal tuples */ break; /* we're past all the equal tuples */
@ -252,9 +251,9 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
else if (htup.t_data != NULL) else if (htup.t_data != NULL)
{ {
/* /*
* Hmm, if we can't see the tuple, maybe it can be * Hmm, if we can't see the tuple, maybe it can be marked
* marked killed. This logic should match * killed. This logic should match index_getnext and
* index_getnext and btgettuple. * btgettuple.
*/ */
LockBuffer(hbuffer, BUFFER_LOCK_SHARE); LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
if (HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin, if (HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin,
@ -377,15 +376,15 @@ _bt_insertonpg(Relation rel,
itemsz = IndexTupleDSize(btitem->bti_itup) itemsz = IndexTupleDSize(btitem->bti_itup)
+ (sizeof(BTItemData) - sizeof(IndexTupleData)); + (sizeof(BTItemData) - sizeof(IndexTupleData));
itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we
* we need to be consistent */ * need to be consistent */
/* /*
* Check whether the item can fit on a btree page at all. (Eventually, * Check whether the item can fit on a btree page at all. (Eventually, we
* we ought to try to apply TOAST methods if not.) We actually need to * ought to try to apply TOAST methods if not.) We actually need to be
* be able to fit three items on every page, so restrict any one item * able to fit three items on every page, so restrict any one item to 1/3
* to 1/3 the per-page available space. Note that at this point, * the per-page available space. Note that at this point, itemsz doesn't
* itemsz doesn't include the ItemId. * include the ItemId.
*/ */
if (itemsz > BTMaxItemSize(page)) if (itemsz > BTMaxItemSize(page))
ereport(ERROR, ereport(ERROR,
@ -432,11 +431,11 @@ _bt_insertonpg(Relation rel,
/* /*
* step right to next non-dead page * step right to next non-dead page
* *
* must write-lock that page before releasing write lock on * must write-lock that page before releasing write lock on current
* current page; else someone else's _bt_check_unique scan * page; else someone else's _bt_check_unique scan could fail to
* could fail to see our insertion. write locks on * see our insertion. write locks on intermediate dead pages
* intermediate dead pages won't do because we don't know when * won't do because we don't know when they will get de-linked
* they will get de-linked from the tree. * from the tree.
*/ */
Buffer rbuf = InvalidBuffer; Buffer rbuf = InvalidBuffer;
@ -459,9 +458,9 @@ _bt_insertonpg(Relation rel,
} }
/* /*
* Now we are on the right page, so find the insert position. If * Now we are on the right page, so find the insert position. If we
* we moved right at all, we know we should insert at the start of * moved right at all, we know we should insert at the start of the
* the page, else must find the position by searching. * page, else must find the position by searching.
*/ */
if (movedright) if (movedright)
newitemoff = P_FIRSTDATAKEY(lpageop); newitemoff = P_FIRSTDATAKEY(lpageop);
@ -472,9 +471,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 result, * Note: PageGetFreeSpace() subtracts sizeof(ItemIdData) from its result, so
* so this comparison is correct even though we appear to be * this comparison is correct even though we appear to be accounting only
* accounting only for the item and not for its line pointer. * for the item and not for its line pointer.
*/ */
if (PageGetFreeSpace(page) < itemsz) if (PageGetFreeSpace(page) < itemsz)
{ {
@ -522,12 +521,11 @@ _bt_insertonpg(Relation rel,
itup_blkno = BufferGetBlockNumber(buf); itup_blkno = BufferGetBlockNumber(buf);
/* /*
* If we are doing this insert because we split a page that was * If we are doing this insert because we split a page that was the
* the only one on its tree level, but was not the root, it may * only one on its tree level, but was not the root, it may have been
* have been the "fast root". We need to ensure that the fast * the "fast root". We need to ensure that the fast root link points
* root link points at or above the current page. We can safely * at or above the current page. We can safely acquire a lock on the
* acquire a lock on the metapage here --- see comments for * metapage here --- see comments for _bt_newroot().
* _bt_newroot().
*/ */
if (split_only_page) if (split_only_page)
{ {
@ -692,11 +690,11 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
lopaque->btpo.level = ropaque->btpo.level = oopaque->btpo.level; lopaque->btpo.level = ropaque->btpo.level = oopaque->btpo.level;
/* /*
* 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
* in the tree, then the first entry on the page is the high key for * the tree, then the first entry on the page is the high key for the
* the page. We need to copy that to the right half. Otherwise * page. We need to copy that to the right half. Otherwise (meaning the
* (meaning the rightmost page case), all the items on the right half * rightmost page case), all the items on the right half will be user
* will be user data. * data.
*/ */
rightoff = P_HIKEY; rightoff = P_HIKEY;
@ -712,9 +710,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
} }
/* /*
* The "high key" for the new left page will be the first key that's * The "high key" for the new left page will be the first key that's going
* going to go into the new right page. This might be either the * to go into the new right page. This might be either the existing data
* existing data item at position firstright, or the incoming tuple. * item at position firstright, or the incoming tuple.
*/ */
leftoff = P_HIKEY; leftoff = P_HIKEY;
if (!newitemonleft && newitemoff == firstright) if (!newitemonleft && newitemoff == firstright)
@ -806,8 +804,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
/* /*
* We have to grab the right sibling (if any) and fix the prev pointer * We have to grab the right sibling (if any) and fix the prev pointer
* there. We are guaranteed that this is deadlock-free since no other * there. We are guaranteed that this is deadlock-free since no other
* writer will be holding a lock on that page and trying to move left, * writer will be holding a lock on that page and trying to move left, and
* and all readers release locks on a page before trying to fetch its * all readers release locks on a page before trying to fetch its
* neighbors. * neighbors.
*/ */
@ -821,8 +819,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
} }
/* /*
* Right sibling is locked, new siblings are prepared, but original * Right sibling is locked, new siblings are prepared, but original page
* page is not updated yet. Log changes before continuing. * is not updated yet. Log changes before continuing.
* *
* NO EREPORT(ERROR) till right sibling is updated. * NO EREPORT(ERROR) till right sibling is updated.
*/ */
@ -850,10 +848,10 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
xlrec.level = lopaque->btpo.level; xlrec.level = lopaque->btpo.level;
/* /*
* Direct access to page is not good but faster - we should * Direct access to page is not good but faster - we should implement
* implement some new func in page API. Note we only store the * some new func in page API. Note we only store the tuples
* tuples themselves, knowing that the item pointers are in the * themselves, knowing that the item pointers are in the same order
* same order and can be reconstructed by scanning the tuples. * and can be reconstructed by scanning the tuples.
*/ */
xlrec.leftlen = ((PageHeader) leftpage)->pd_special - xlrec.leftlen = ((PageHeader) leftpage)->pd_special -
((PageHeader) leftpage)->pd_upper; ((PageHeader) leftpage)->pd_upper;
@ -903,13 +901,13 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
} }
/* /*
* By here, the original data page has been split into two new halves, * By here, the original data page has been split into two new halves, and
* and these are correct. The algorithm requires that the left page * these are correct. The algorithm requires that the left page never
* never move during a split, so we copy the new left page back on top * move during a split, so we copy the new left page back on top of the
* of the original. Note that this is not a waste of time, since we * original. Note that this is not a waste of time, since we also require
* also require (in the page management code) that the center of a * (in the page management code) that the center of a page always be
* page always be clean, and the most efficient way to guarantee this * clean, and the most efficient way to guarantee this is just to compact
* is just to compact the data by reinserting it into a new left page. * the data by reinserting it into a new left page.
*/ */
PageRestoreTempPage(leftpage, origpage); PageRestoreTempPage(leftpage, origpage);
@ -984,13 +982,13 @@ _bt_findsplitloc(Relation rel,
MAXALIGN(sizeof(BTPageOpaqueData)); MAXALIGN(sizeof(BTPageOpaqueData));
/* /*
* Finding the best possible split would require checking all the * Finding the best possible split would require checking all the possible
* possible split points, because of the high-key and left-key special * split points, because of the high-key and left-key special cases.
* cases. That's probably more work than it's worth; instead, stop as * That's probably more work than it's worth; instead, stop as soon as we
* soon as we find a "good-enough" split, where good-enough is defined * find a "good-enough" split, where good-enough is defined as an
* as an imbalance in free space of no more than pagesize/16 * imbalance in free space of no more than pagesize/16 (arbitrary...) This
* (arbitrary...) This should let us stop near the middle on most * should let us stop near the middle on most pages, instead of plowing to
* pages, instead of plowing to the end. * the end.
*/ */
goodenough = leftspace / 16; goodenough = leftspace / 16;
@ -1006,8 +1004,8 @@ _bt_findsplitloc(Relation rel,
dataitemtotal = rightspace - (int) PageGetFreeSpace(page); dataitemtotal = rightspace - (int) PageGetFreeSpace(page);
/* /*
* Scan through the data items and calculate space usage for a split * Scan through the data items and calculate space usage for a split at
* at each possible position. * each possible position.
*/ */
dataitemstoleft = 0; dataitemstoleft = 0;
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
@ -1024,9 +1022,9 @@ _bt_findsplitloc(Relation rel,
itemsz = MAXALIGN(ItemIdGetLength(itemid)) + sizeof(ItemIdData); itemsz = MAXALIGN(ItemIdGetLength(itemid)) + sizeof(ItemIdData);
/* /*
* We have to allow for the current item becoming the high key of * We have to allow for the current item becoming the high key of the
* the left page; therefore it counts against left space as well * left page; therefore it counts against left space as well as right
* as right space. * space.
*/ */
leftfree = leftspace - dataitemstoleft - (int) itemsz; leftfree = leftspace - dataitemstoleft - (int) itemsz;
rightfree = rightspace - (dataitemtotal - dataitemstoleft); rightfree = rightspace - (dataitemtotal - dataitemstoleft);
@ -1058,8 +1056,8 @@ _bt_findsplitloc(Relation rel,
} }
/* /*
* I believe it is not possible to fail to find a feasible split, but * I believe it is not possible to fail to find a feasible split, but just
* just in case ... * in case ...
*/ */
if (!state.have_split) if (!state.have_split)
elog(ERROR, "could not find a feasible split point for \"%s\"", elog(ERROR, "could not find a feasible split point for \"%s\"",
@ -1105,8 +1103,7 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
{ {
/* /*
* On a rightmost page, try to equalize right free space with * On a rightmost page, try to equalize right free space with
* twice the left free space. See comments for * twice the left free space. See comments for _bt_findsplitloc.
* _bt_findsplitloc.
*/ */
delta = (2 * leftfree) - rightfree; delta = (2 * leftfree) - rightfree;
} }
@ -1153,19 +1150,18 @@ _bt_insert_parent(Relation rel,
bool is_only) bool is_only)
{ {
/* /*
* Here we have to do something Lehman and Yao don't talk about: deal * Here we have to do something Lehman and Yao don't talk about: deal with
* with a root split and construction of a new root. If our stack is * a root split and construction of a new root. If our stack is empty
* empty then we have just split a node on what had been the root * then we have just split a node on what had been the root level when we
* level when we descended the tree. If it was still the root then we * descended the tree. If it was still the root then we perform a
* perform a new-root construction. If it *wasn't* the root anymore, * new-root construction. If it *wasn't* the root anymore, search to find
* search to find the next higher level that someone constructed * the next higher level that someone constructed meanwhile, and find the
* meanwhile, and find the right place to insert as for the normal * right place to insert as for the normal case.
* case.
* *
* If we have to search for the parent level, we do so by re-descending * If we have to search for the parent level, we do so by re-descending from
* from the root. This is not super-efficient, but it's rare enough * the root. This is not super-efficient, but it's rare enough not to
* not to matter. (This path is also taken when called from WAL * matter. (This path is also taken when called from WAL recovery --- we
* recovery --- we have no stack in that case.) * have no stack in that case.)
*/ */
if (is_root) if (is_root)
{ {
@ -1219,9 +1215,9 @@ _bt_insert_parent(Relation rel,
/* /*
* Find the parent buffer and get the parent page. * Find the parent buffer and get the parent page.
* *
* Oops - if we were moved right then we need to change stack item! * Oops - if we were moved right then we need to change stack item! We
* We want to find parent pointing to where we are, right ? - * want to find parent pointing to where we are, right ? - vadim
* vadim 05/27/97 * 05/27/97
*/ */
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid), ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
bknum, P_HIKEY); bknum, P_HIKEY);
@ -1291,9 +1287,9 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
/* /*
* start = InvalidOffsetNumber means "search the whole page". * start = InvalidOffsetNumber means "search the whole page". We
* We need this test anyway due to possibility that page has a * need this test anyway due to possibility that page has a high
* high key now when it didn't before. * key now when it didn't before.
*/ */
if (start < minoff) if (start < minoff)
start = minoff; start = minoff;
@ -1307,8 +1303,8 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
/* /*
* These loops will check every item on the page --- but in an * These loops will check every item on the page --- but in an
* order that's attuned to the probability of where it * order that's attuned to the probability of where it actually
* actually is. Scan to the right first, then to the left. * is. Scan to the right first, then to the left.
*/ */
for (offnum = start; for (offnum = start;
offnum <= maxoff; offnum <= maxoff;
@ -1424,9 +1420,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
metad->btm_fastlevel = rootopaque->btpo.level; metad->btm_fastlevel = rootopaque->btpo.level;
/* /*
* Create downlink item for left page (old root). Since this will be * Create downlink item for left page (old root). Since this will be the
* the first item in a non-leaf page, it implicitly has minus-infinity * first item in a non-leaf page, it implicitly has minus-infinity key
* key value, so we need not store any actual key in it. * value, so we need not store any actual key in it.
*/ */
itemsz = sizeof(BTItemData); itemsz = sizeof(BTItemData);
new_item = (BTItem) palloc(itemsz); new_item = (BTItem) palloc(itemsz);
@ -1434,17 +1430,17 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
ItemPointerSet(&(new_item->bti_itup.t_tid), lbkno, P_HIKEY); ItemPointerSet(&(new_item->bti_itup.t_tid), lbkno, P_HIKEY);
/* /*
* Insert the left page pointer into the new root page. The root page * Insert the left page pointer into the new root page. The root page is
* is the rightmost page on its level so there is no "high key" in it; * the rightmost page on its level so there is no "high key" in it; the
* the two items will go into positions P_HIKEY and P_FIRSTKEY. * two items will go into positions P_HIKEY and P_FIRSTKEY.
*/ */
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY, LP_USED) == InvalidOffsetNumber) if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY, LP_USED) == InvalidOffsetNumber)
elog(PANIC, "failed to add leftkey to new root page"); elog(PANIC, "failed to add leftkey to new root page");
pfree(new_item); pfree(new_item);
/* /*
* Create downlink item for right page. The key for it is obtained * Create downlink item for right page. The key for it is obtained from
* from the "high key" position in the left page. * the "high key" position in the left page.
*/ */
itemid = PageGetItemId(lpage, P_HIKEY); itemid = PageGetItemId(lpage, P_HIKEY);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
@ -1476,8 +1472,8 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
/* /*
* Direct access to page is not good but faster - we should * Direct access to page is not good but faster - we should implement
* implement some new func in page API. * some new func in page API.
*/ */
rdata[1].data = (char *) rootpage + ((PageHeader) rootpage)->pd_upper; rdata[1].data = (char *) rootpage + ((PageHeader) rootpage)->pd_upper;
rdata[1].len = ((PageHeader) rootpage)->pd_special - rdata[1].len = ((PageHeader) rootpage)->pd_special -

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.87 2005/08/12 14:34:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.88 2005/10/15 02:49:09 momjian Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -115,8 +115,8 @@ _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level)
metaopaque->btpo_flags = BTP_META; metaopaque->btpo_flags = BTP_META;
/* /*
* Set pd_lower just past the end of the metadata. This is not * Set pd_lower just past the end of the metadata. This is not essential
* essential but it makes the page look compressible to xlog.c. * but it makes the page look compressible to xlog.c.
*/ */
((PageHeader) page)->pd_lower = ((PageHeader) page)->pd_lower =
((char *) metad + sizeof(BTMetaPageData)) - (char *) page; ((char *) metad + sizeof(BTMetaPageData)) - (char *) page;
@ -198,26 +198,26 @@ _bt_getroot(Relation rel, int access)
LockBuffer(metabuf, BT_WRITE); LockBuffer(metabuf, BT_WRITE);
/* /*
* Race condition: if someone else initialized the metadata * Race condition: if someone else initialized the metadata between
* between the time we released the read lock and acquired the * the time we released the read lock and acquired the write lock, we
* write lock, we must avoid doing it again. * must avoid doing it again.
*/ */
if (metad->btm_root != P_NONE) if (metad->btm_root != P_NONE)
{ {
/* /*
* Metadata initialized by someone else. In order to * Metadata initialized by someone else. In order to guarantee no
* guarantee no deadlocks, we have to release the metadata * deadlocks, we have to release the metadata page and start all
* page and start all over again. (Is that really true? But * over again. (Is that really true? But it's hardly worth trying
* it's hardly worth trying to optimize this case.) * to optimize this case.)
*/ */
_bt_relbuf(rel, metabuf); _bt_relbuf(rel, metabuf);
return _bt_getroot(rel, access); return _bt_getroot(rel, access);
} }
/* /*
* Get, initialize, write, and leave a lock of the appropriate * Get, initialize, write, and leave a lock of the appropriate type on
* type on the new root page. Since this is the first page in the * the new root page. Since this is the first page in the tree, it's
* tree, it's a leaf as well as the root. * a leaf as well as the root.
*/ */
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE); rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
rootblkno = BufferGetBlockNumber(rootbuf); rootblkno = BufferGetBlockNumber(rootbuf);
@ -266,9 +266,9 @@ _bt_getroot(Relation rel, int access)
_bt_wrtnorelbuf(rel, rootbuf); _bt_wrtnorelbuf(rel, rootbuf);
/* /*
* swap root write lock for read lock. There is no danger of * swap root write lock for read lock. There is no danger of anyone
* anyone else accessing the new root page while it's unlocked, * else accessing the new root page while it's unlocked, since no one
* since no one else knows where it is yet. * else knows where it is yet.
*/ */
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK); LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_READ); LockBuffer(rootbuf, BT_READ);
@ -312,8 +312,8 @@ _bt_getroot(Relation rel, int access)
} }
/* /*
* By here, we have a pin and read lock on the root page, and no lock * By here, we have a pin and read lock on the root page, and no lock set
* set on the metadata page. Return the root page's buffer. * on the metadata page. Return the root page's buffer.
*/ */
return rootbuf; return rootbuf;
} }
@ -435,27 +435,26 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
/* /*
* First see if the FSM knows of any free pages. * First see if the FSM knows of any free pages.
* *
* We can't trust the FSM's report unreservedly; we have to check * We can't trust the FSM's report unreservedly; we have to check that
* that the page is still free. (For example, an already-free * the page is still free. (For example, an already-free page could
* page could have been re-used between the time the last VACUUM * have been re-used between the time the last VACUUM scanned it and
* scanned it and the time the VACUUM made its FSM updates.) * the time the VACUUM made its FSM updates.)
* *
* In fact, it's worse than that: we can't even assume that it's safe * In fact, it's worse than that: we can't even assume that it's safe to
* to take a lock on the reported page. If somebody else has a * take a lock on the reported page. If somebody else has a lock on
* lock on it, or even worse our own caller does, we could * it, or even worse our own caller does, we could deadlock. (The
* deadlock. (The own-caller scenario is actually not improbable. * own-caller scenario is actually not improbable. Consider an index
* Consider an index on a serial or timestamp column. Nearly all * on a serial or timestamp column. Nearly all splits will be at the
* splits will be at the rightmost page, so it's entirely likely * rightmost page, so it's entirely likely that _bt_split will call us
* that _bt_split will call us while holding a lock on the page * while holding a lock on the page most recently acquired from FSM.
* most recently acquired from FSM. A VACUUM running concurrently * A VACUUM running concurrently with the previous split could well
* with the previous split could well have placed that page back * have placed that page back in FSM.)
* in FSM.)
* *
* To get around that, we ask for only a conditional lock on the * To get around that, we ask for only a conditional lock on the reported
* reported page. If we fail, then someone else is using the * page. If we fail, then someone else is using the page, and we may
* page, and we may reasonably assume it's not free. (If we * reasonably assume it's not free. (If we happen to be wrong, the
* happen to be wrong, the worst consequence is the page will be * worst consequence is the page will be lost to use till the next
* lost to use till the next VACUUM, which is no big problem.) * VACUUM, which is no big problem.)
*/ */
for (;;) for (;;)
{ {
@ -486,10 +485,10 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
/* /*
* Extend the relation by one page. * Extend the relation by one page.
* *
* We have to use a lock to ensure no one else is extending the rel * We have to use a lock to ensure no one else is extending the rel at
* at the same time, else we will both try to initialize the same * the same time, else we will both try to initialize the same new
* new page. We can skip locking for new or temp relations, * page. We can skip locking for new or temp relations, however,
* however, since no one else could be accessing them. * since no one else could be accessing them.
*/ */
needLock = !RELATION_IS_LOCAL(rel); needLock = !RELATION_IS_LOCAL(rel);
@ -504,8 +503,8 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
/* /*
* Release the file-extension lock; it's now OK for someone else to * Release the file-extension lock; it's now OK for someone else to
* extend the relation some more. Note that we cannot release this * extend the relation some more. Note that we cannot release this
* lock before we have buffer lock on the new page, or we risk a * lock before we have buffer lock on the new page, or we risk a race
* race condition against btvacuumcleanup --- see comments therein. * condition against btvacuumcleanup --- see comments therein.
*/ */
if (needLock) if (needLock)
UnlockRelationForExtension(rel, ExclusiveLock); UnlockRelationForExtension(rel, ExclusiveLock);
@ -614,10 +613,10 @@ _bt_page_recyclable(Page page)
BTPageOpaque opaque; BTPageOpaque opaque;
/* /*
* It's possible to find an all-zeroes page in an index --- for * It's possible to find an all-zeroes page in an index --- for example, a
* example, a backend might successfully extend the relation one page * backend might successfully extend the relation one page and then crash
* and then crash before it is able to make a WAL entry for adding the * before it is able to make a WAL entry for adding the page. If we find a
* page. If we find a zeroed page then reclaim it. * zeroed page then reclaim it.
*/ */
if (PageIsNew(page)) if (PageIsNew(page))
return true; return true;
@ -672,9 +671,9 @@ _bt_delitems(Relation rel, Buffer buf,
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
/* /*
* The target-offsets array is not in the buffer, but pretend that * The target-offsets array is not in the buffer, but pretend that it
* it is. When XLogInsert stores the whole buffer, the offsets * is. When XLogInsert stores the whole buffer, the offsets array
* array need not be stored too. * need not be stored too.
*/ */
if (nitems > 0) if (nitems > 0)
{ {
@ -747,8 +746,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
BTPageOpaque opaque; BTPageOpaque opaque;
/* /*
* We can never delete rightmost pages nor root pages. While at it, * We can never delete rightmost pages nor root pages. While at it, check
* check that page is not already deleted and is empty. * that page is not already deleted and is empty.
*/ */
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@ -760,8 +759,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
} }
/* /*
* Save info about page, including a copy of its high key (it must * Save info about page, including a copy of its high key (it must have
* have one, being non-rightmost). * one, being non-rightmost).
*/ */
target = BufferGetBlockNumber(buf); target = BufferGetBlockNumber(buf);
targetlevel = opaque->btpo.level; targetlevel = opaque->btpo.level;
@ -770,11 +769,11 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
targetkey = CopyBTItem((BTItem) PageGetItem(page, itemid)); targetkey = CopyBTItem((BTItem) PageGetItem(page, itemid));
/* /*
* We need to get an approximate pointer to the page's parent page. * We need to get an approximate pointer to the page's parent page. Use
* Use the standard search mechanism to search for the page's high * the standard search mechanism to search for the page's high key; this
* key; this will give us a link to either the current parent or * will give us a link to either the current parent or someplace to its
* someplace to its left (if there are multiple equal high keys). To * left (if there are multiple equal high keys). To avoid deadlocks, we'd
* avoid deadlocks, we'd better drop the target page lock first. * better drop the target page lock first.
*/ */
_bt_relbuf(rel, buf); _bt_relbuf(rel, buf);
/* we need a scan key to do our search, so build one */ /* we need a scan key to do our search, so build one */
@ -786,9 +785,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
_bt_relbuf(rel, lbuf); _bt_relbuf(rel, lbuf);
/* /*
* If we are trying to delete an interior page, _bt_search did more * If we are trying to delete an interior page, _bt_search did more than
* than we needed. Locate the stack item pointing to our parent * we needed. Locate the stack item pointing to our parent level.
* level.
*/ */
ilevel = 0; ilevel = 0;
for (;;) for (;;)
@ -803,16 +801,15 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
/* /*
* We have to lock the pages we need to modify in the standard order: * We have to lock the pages we need to modify in the standard order:
* moving right, then up. Else we will deadlock against other * moving right, then up. Else we will deadlock against other writers.
* writers.
* *
* So, we need to find and write-lock the current left sibling of the * So, we need to find and write-lock the current left sibling of the target
* target page. The sibling that was current a moment ago could have * page. The sibling that was current a moment ago could have split, so
* split, so we may have to move right. This search could fail if * we may have to move right. This search could fail if either the
* either the sibling or the target page was deleted by someone else * sibling or the target page was deleted by someone else meanwhile; if
* meanwhile; if so, give up. (Right now, that should never happen, * so, give up. (Right now, that should never happen, since page deletion
* since page deletion is only done in VACUUM and there shouldn't be * is only done in VACUUM and there shouldn't be multiple VACUUMs
* multiple VACUUMs concurrently on the same table.) * concurrently on the same table.)
*/ */
if (leftsib != P_NONE) if (leftsib != P_NONE)
{ {
@ -839,19 +836,18 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
lbuf = InvalidBuffer; lbuf = InvalidBuffer;
/* /*
* Next write-lock the target page itself. It should be okay to take * Next write-lock the target page itself. It should be okay to take just
* just a write lock not a superexclusive lock, since no scans would * a write lock not a superexclusive lock, since no scans would stop on an
* stop on an empty page. * empty page.
*/ */
buf = _bt_getbuf(rel, target, BT_WRITE); buf = _bt_getbuf(rel, target, BT_WRITE);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* Check page is still empty etc, else abandon deletion. The empty * Check page is still empty etc, else abandon deletion. The empty check
* check is necessary since someone else might have inserted into it * is necessary since someone else might have inserted into it while we
* while we didn't have it locked; the others are just for paranoia's * didn't have it locked; the others are just for paranoia's sake.
* sake.
*/ */
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || P_ISDELETED(opaque) || if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || P_ISDELETED(opaque) ||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page)) P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
@ -872,9 +868,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
rbuf = _bt_getbuf(rel, rightsib, BT_WRITE); rbuf = _bt_getbuf(rel, rightsib, BT_WRITE);
/* /*
* Next find and write-lock the current parent of the target page. * Next find and write-lock the current parent of the target page. This is
* This is essentially the same as the corresponding step of * essentially the same as the corresponding step of splitting.
* splitting.
*/ */
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid), ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
target, P_HIKEY); target, P_HIKEY);
@ -887,8 +882,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
/* /*
* If the target is the rightmost child of its parent, then we can't * If the target is the rightmost child of its parent, then we can't
* delete, unless it's also the only child --- in which case the * delete, unless it's also the only child --- in which case the parent
* parent changes to half-dead status. * changes to half-dead status.
*/ */
page = BufferGetPage(pbuf); page = BufferGetPage(pbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@ -917,11 +912,10 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
} }
/* /*
* If we are deleting the next-to-last page on the target's level, * If we are deleting the next-to-last page on the target's level, then
* then the rightsib is a candidate to become the new fast root. (In * the rightsib is a candidate to become the new fast root. (In theory, it
* theory, it might be possible to push the fast root even further * might be possible to push the fast root even further down, but the odds
* down, but the odds of doing so are slim, and the locking * of doing so are slim, and the locking considerations daunting.)
* considerations daunting.)
* *
* We can safely acquire a lock on the metapage here --- see comments for * We can safely acquire a lock on the metapage here --- see comments for
* _bt_newroot(). * _bt_newroot().
@ -939,9 +933,9 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
metad = BTPageGetMeta(metapg); metad = BTPageGetMeta(metapg);
/* /*
* The expected case here is btm_fastlevel == targetlevel+1; * The expected case here is btm_fastlevel == targetlevel+1; if
* if the fastlevel is <= targetlevel, something is wrong, and * the fastlevel is <= targetlevel, something is wrong, and we
* we choose to overwrite it to fix it. * choose to overwrite it to fix it.
*/ */
if (metad->btm_fastlevel > targetlevel + 1) if (metad->btm_fastlevel > targetlevel + 1)
{ {
@ -961,9 +955,9 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
/* /*
* Update parent. The normal case is a tad tricky because we want to * Update parent. The normal case is a tad tricky because we want to
* delete the target's downlink and the *following* key. Easiest way * delete the target's downlink and the *following* key. Easiest way is
* is to copy the right sibling's downlink over the target downlink, * to copy the right sibling's downlink over the target downlink, and then
* and then delete the following item. * delete the following item.
*/ */
page = BufferGetPage(pbuf); page = BufferGetPage(pbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@ -992,8 +986,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
} }
/* /*
* Update siblings' side-links. Note the target page's side-links * Update siblings' side-links. Note the target page's side-links will
* will continue to point to the siblings. * continue to point to the siblings.
*/ */
if (BufferIsValid(lbuf)) if (BufferIsValid(lbuf))
{ {
@ -1123,10 +1117,10 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
_bt_wrtbuf(rel, lbuf); _bt_wrtbuf(rel, lbuf);
/* /*
* If parent became half dead, recurse to try to delete it. Otherwise, * If parent became half dead, recurse to try to delete it. Otherwise, if
* if right sibling is empty and is now the last child of the parent, * right sibling is empty and is now the last child of the parent, recurse
* recurse to try to delete it. (These cases cannot apply at the same * to try to delete it. (These cases cannot apply at the same time,
* time, though the second case might itself recurse to the first.) * though the second case might itself recurse to the first.)
*/ */
if (parent_half_dead) if (parent_half_dead)
{ {

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
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.131 2005/09/02 19:02:19 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.132 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -39,9 +39,9 @@ typedef struct
BTSpool *spool; BTSpool *spool;
/* /*
* spool2 is needed only when the index is an unique index. Dead * spool2 is needed only when the index is an unique index. Dead tuples
* tuples are put into spool2 instead of spool in order to avoid * are put into spool2 instead of spool in order to avoid uniqueness
* uniqueness check. * check.
*/ */
BTSpool *spool2; BTSpool *spool2;
double indtuples; double indtuples;
@ -72,10 +72,10 @@ btbuild(PG_FUNCTION_ARGS)
BTBuildState buildstate; BTBuildState buildstate;
/* /*
* bootstrap processing does something strange, so don't use * bootstrap processing does something strange, so don't use sort/build
* sort/build for initial catalog indices. at some point i need to * for initial catalog indices. at some point i need to look harder at
* look harder at this. (there is some kind of incremental processing * this. (there is some kind of incremental processing going on there.)
* going on there.) -- pma 08/29/95 * -- pma 08/29/95
*/ */
buildstate.usefast = (FastBuild && IsNormalProcessingMode()); buildstate.usefast = (FastBuild && IsNormalProcessingMode());
buildstate.isUnique = indexInfo->ii_Unique; buildstate.isUnique = indexInfo->ii_Unique;
@ -91,8 +91,8 @@ btbuild(PG_FUNCTION_ARGS)
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
/* /*
* We expect to be called exactly once for any index relation. If * We expect to be called exactly once for any index relation. If that's
* that's not the case, big trouble's what we have. * not the case, big trouble's what we have.
*/ */
if (RelationGetNumberOfBlocks(index) != 0) if (RelationGetNumberOfBlocks(index) != 0)
elog(ERROR, "index \"%s\" already contains data", elog(ERROR, "index \"%s\" already contains data",
@ -103,8 +103,8 @@ btbuild(PG_FUNCTION_ARGS)
buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique, false); buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique, false);
/* /*
* If building a unique index, put dead tuples in a second spool * If building a unique index, put dead tuples in a second spool to
* to keep them out of the uniqueness check. * keep them out of the uniqueness check.
*/ */
if (indexInfo->ii_Unique) if (indexInfo->ii_Unique)
buildstate.spool2 = _bt_spoolinit(index, false, true); buildstate.spool2 = _bt_spoolinit(index, false, true);
@ -129,8 +129,8 @@ btbuild(PG_FUNCTION_ARGS)
/* /*
* if we are doing bottom-up btree build, finish the build by (1) * if we are doing bottom-up btree build, finish the build by (1)
* completing the sort of the spool file, (2) inserting the sorted * completing the sort of the spool file, (2) inserting the sorted tuples
* tuples into btree pages and (3) building the upper levels. * into btree pages and (3) building the upper levels.
*/ */
if (buildstate.usefast) if (buildstate.usefast)
{ {
@ -176,9 +176,8 @@ btbuildCallback(Relation index,
btitem = _bt_formitem(itup); btitem = _bt_formitem(itup);
/* /*
* if we are doing bottom-up btree build, we insert the index into a * if we are doing bottom-up btree build, we insert the index into a spool
* spool file for subsequent processing. otherwise, we insert into * file for subsequent processing. otherwise, we insert into the btree.
* the btree.
*/ */
if (buildstate->usefast) if (buildstate->usefast)
{ {
@ -248,16 +247,16 @@ btgettuple(PG_FUNCTION_ARGS)
bool res; bool res;
/* /*
* If we've already initialized this scan, we can just advance it in * If we've already initialized this scan, we can just advance it in the
* the appropriate direction. If we haven't done so yet, we call a * appropriate direction. If we haven't done so yet, we call a routine to
* routine to get the first item in the scan. * get the first item in the scan.
*/ */
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
* to btgettuple(). _bt_restscan() re-grabs the read lock on the * btgettuple(). _bt_restscan() re-grabs the read lock on the buffer,
* buffer, too. * too.
*/ */
_bt_restscan(scan); _bt_restscan(scan);
@ -267,17 +266,16 @@ btgettuple(PG_FUNCTION_ARGS)
if (scan->kill_prior_tuple) if (scan->kill_prior_tuple)
{ {
/* /*
* Yes, so mark it by setting the LP_DELETE bit in the item * Yes, so mark it by setting the LP_DELETE bit in the item flags.
* flags.
*/ */
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
page = BufferGetPage(so->btso_curbuf); page = BufferGetPage(so->btso_curbuf);
PageGetItemId(page, offnum)->lp_flags |= LP_DELETE; PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
/* /*
* Since this can be redone later if needed, it's treated the * Since this can be redone later if needed, it's treated the same
* same as a commit-hint-bit status update for heap tuples: we * as a commit-hint-bit status update for heap tuples: we mark the
* mark the buffer dirty but don't make a WAL log entry. * buffer dirty but don't make a WAL log entry.
*/ */
SetBufferCommitInfoNeedsSave(so->btso_curbuf); SetBufferCommitInfoNeedsSave(so->btso_curbuf);
} }
@ -306,11 +304,11 @@ 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
* lock on the buffer so that we aren't blocking other backends. * the buffer so that we aren't blocking other backends.
* *
* NOTE: we do keep the pin on the buffer! This is essential to ensure * NOTE: we do keep the pin on the buffer! This is essential to ensure that
* that someone else doesn't delete the index entry we are stopped on. * someone else doesn't delete the index entry we are stopped on.
*/ */
if (res) if (res)
{ {
@ -355,6 +353,7 @@ btgetmulti(PG_FUNCTION_ARGS)
res = _bt_next(scan, ForwardScanDirection); res = _bt_next(scan, ForwardScanDirection);
else else
res = _bt_first(scan, ForwardScanDirection); res = _bt_first(scan, ForwardScanDirection);
/* /*
* Skip killed tuples if asked to. * Skip killed tuples if asked to.
*/ */
@ -381,8 +380,8 @@ btgetmulti(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
* lock on the buffer so that we aren't blocking other backends. * the buffer so that we aren't blocking other backends.
*/ */
if (res) if (res)
{ {
@ -456,8 +455,8 @@ btrescan(PG_FUNCTION_ARGS)
} }
/* /*
* Reset the scan keys. Note that keys ordering stuff moved to * Reset the scan keys. Note that keys ordering stuff moved to _bt_first.
* _bt_first. - vadim 05/05/97 * - vadim 05/05/97
*/ */
if (scankey && scan->numberOfKeys > 0) if (scankey && scan->numberOfKeys > 0)
memmove(scan->keyData, memmove(scan->keyData,
@ -593,21 +592,20 @@ btbulkdelete(PG_FUNCTION_ARGS)
num_index_tuples = 0; num_index_tuples = 0;
/* /*
* The outer loop iterates over index leaf pages, the inner over items * The outer loop iterates over index leaf pages, the inner over items on
* on a leaf page. We issue just one _bt_delitems() call per page, so * a leaf page. We issue just one _bt_delitems() call per page, so as to
* as to minimize WAL traffic. * minimize WAL traffic.
* *
* Note that we exclusive-lock every leaf page containing data items, in * Note that we exclusive-lock every leaf page containing data items, in
* sequence left to right. It sounds attractive to only * sequence left to right. It sounds attractive to only exclusive-lock
* exclusive-lock those containing items we need to delete, but * those containing items we need to delete, but unfortunately that is not
* unfortunately that is not safe: we could then pass a stopped * safe: we could then pass a stopped indexscan, which could in rare cases
* indexscan, which could in rare cases lead to deleting the item it * lead to deleting the item it needs to find when it resumes. (See
* needs to find when it resumes. (See _bt_restscan --- this could * _bt_restscan --- this could only happen if an indexscan stops on a
* only happen if an indexscan stops on a deletable item and then a * deletable item and then a page split moves that item into a page
* page split moves that item into a page further to its right, which * further to its right, which the indexscan will have no pin on.) We can
* the indexscan will have no pin on.) We can skip obtaining * skip obtaining exclusive lock on empty pages though, since no indexscan
* exclusive lock on empty pages though, since no indexscan could be * could be stopped on those.
* stopped on those.
*/ */
buf = _bt_get_endpoint(rel, 0, false); buf = _bt_get_endpoint(rel, 0, false);
if (BufferIsValid(buf)) /* check for empty index */ if (BufferIsValid(buf)) /* check for empty index */
@ -632,15 +630,15 @@ btbulkdelete(PG_FUNCTION_ARGS)
if (minoff <= maxoff && !P_ISDELETED(opaque)) if (minoff <= maxoff && !P_ISDELETED(opaque))
{ {
/* /*
* Trade in the initial read lock for a super-exclusive * Trade in the initial read lock for a super-exclusive write
* write lock on this page. * lock on this page.
*/ */
LockBuffer(buf, BUFFER_LOCK_UNLOCK); LockBuffer(buf, BUFFER_LOCK_UNLOCK);
LockBufferForCleanup(buf); LockBufferForCleanup(buf);
/* /*
* Recompute minoff/maxoff, both of which could have * Recompute minoff/maxoff, both of which could have changed
* changed while we weren't holding the lock. * while we weren't holding the lock.
*/ */
minoff = P_FIRSTDATAKEY(opaque); minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
@ -670,8 +668,8 @@ btbulkdelete(PG_FUNCTION_ARGS)
} }
/* /*
* If we need to delete anything, do it and write the buffer; * If we need to delete anything, do it and write the buffer; else
* else just release the buffer. * just release the buffer.
*/ */
nextpage = opaque->btpo_next; nextpage = opaque->btpo_next;
if (ndeletable > 0) if (ndeletable > 0)
@ -725,19 +723,19 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
Assert(stats != NULL); Assert(stats != NULL);
/* /*
* First find out the number of pages in the index. We must acquire * First find out the number of pages in the index. We must acquire the
* the relation-extension lock while doing this to avoid a race * relation-extension lock while doing this to avoid a race condition: if
* condition: if someone else is extending the relation, there is * someone else is extending the relation, there is a window where
* a window where bufmgr/smgr have created a new all-zero page but * bufmgr/smgr have created a new all-zero page but it hasn't yet been
* it hasn't yet been write-locked by _bt_getbuf(). If we manage to * write-locked by _bt_getbuf(). If we manage to scan such a page here,
* scan such a page here, we'll improperly assume it can be recycled. * we'll improperly assume it can be recycled. Taking the lock
* Taking the lock synchronizes things enough to prevent a problem: * synchronizes things enough to prevent a problem: either num_pages won't
* either num_pages won't include the new page, or _bt_getbuf already * include the new page, or _bt_getbuf already has write lock on the
* has write lock on the buffer and it will be fully initialized before * buffer and it will be fully initialized before we can examine it. (See
* we can examine it. (See also vacuumlazy.c, which has the same issue.) * also vacuumlazy.c, which has the same issue.)
* *
* We can skip locking for new or temp relations, * We can skip locking for new or temp relations, however, since no one else
* however, since no one else could be accessing them. * could be accessing them.
*/ */
needLock = !RELATION_IS_LOCAL(rel); needLock = !RELATION_IS_LOCAL(rel);
@ -807,12 +805,12 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
/* /*
* During VACUUM FULL it's okay to recycle deleted pages * During VACUUM FULL it's okay to recycle deleted pages
* immediately, since there can be no other transactions * immediately, since there can be no other transactions scanning
* scanning the index. Note that we will only recycle the * the index. Note that we will only recycle the current page and
* current page and not any parent pages that _bt_pagedel * not any parent pages that _bt_pagedel might have recursed to;
* might have recursed to; this seems reasonable in the name * this seems reasonable in the name of simplicity. (Trying to do
* of simplicity. (Trying to do otherwise would mean we'd * otherwise would mean we'd have to sort the list of recyclable
* have to sort the list of recyclable pages we're building.) * pages we're building.)
*/ */
if (ndel && info->vacuum_full) if (ndel && info->vacuum_full)
{ {
@ -827,10 +825,10 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
} }
/* /*
* During VACUUM FULL, we truncate off any recyclable pages at the end * During VACUUM FULL, we truncate off any recyclable pages at the end of
* of the index. In a normal vacuum it'd be unsafe to do this except * the index. In a normal vacuum it'd be unsafe to do this except by
* by acquiring exclusive lock on the index and then rechecking all * acquiring exclusive lock on the index and then rechecking all the
* the pages; doesn't seem worth it. * pages; doesn't seem worth it.
*/ */
if (info->vacuum_full && nFreePages > 0) if (info->vacuum_full && nFreePages > 0)
{ {
@ -857,9 +855,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
} }
/* /*
* Update the shared Free Space Map with the info we now have about * Update the shared Free Space Map with the info we now have about free
* free pages in the index, discarding any old info the map may have. * pages in the index, discarding any old info the map may have. We do not
* We do not need to sort the page numbers; they're in order already. * need to sort the page numbers; they're in order already.
*/ */
RecordIndexFreeSpace(&rel->rd_node, nFreePages, freePages); RecordIndexFreeSpace(&rel->rd_node, nFreePages, freePages);
@ -915,8 +913,8 @@ _bt_restscan(IndexScanDesc scan)
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* We use this as flag when first index tuple on page is deleted but * We use this as flag when first index tuple on page is deleted but we do
* we do not move left (this would slowdown vacuum) - so we set * not move left (this would slowdown vacuum) - so we set
* current->ip_posid before first index tuple on the current page * current->ip_posid before first index tuple on the current page
* (_bt_step will move it right)... XXX still needed? * (_bt_step will move it right)... XXX still needed?
*/ */
@ -948,12 +946,12 @@ _bt_restscan(IndexScanDesc scan)
} }
/* /*
* The item we're looking for moved right at least one page, so * The item we're looking for moved right at least one page, so move
* move right. We are careful here to pin and read-lock the next * right. We are careful here to pin and read-lock the next non-dead
* non-dead page before releasing the current one. This ensures * page before releasing the current one. This ensures that a
* that a concurrent btbulkdelete scan cannot pass our position * concurrent btbulkdelete scan cannot pass our position --- if it
* --- if it did, it might be able to reach and delete our target * did, it might be able to reach and delete our target item before we
* item before we can find it again. * can find it again.
*/ */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
elog(ERROR, "failed to re-find previous key in \"%s\"", elog(ERROR, "failed to re-find previous key in \"%s\"",

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.94 2005/10/06 02:29:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.95 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -69,9 +69,9 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
BTStack new_stack; BTStack new_stack;
/* /*
* Race -- the page we just grabbed may have split since we read * Race -- the page we just grabbed may have split since we read its
* its pointer in the parent (or metapage). If it has, we may * pointer in the parent (or metapage). If it has, we may need to
* need to move right to its new sibling. Do that. * move right to its new sibling. Do that.
*/ */
*bufP = _bt_moveright(rel, *bufP, keysz, scankey, nextkey, BT_READ); *bufP = _bt_moveright(rel, *bufP, keysz, scankey, nextkey, BT_READ);
@ -82,8 +82,8 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
break; break;
/* /*
* Find the appropriate item on the internal page, and get the * Find the appropriate item on the internal page, and get the child
* child page that it points to. * page that it points to.
*/ */
offnum = _bt_binsrch(rel, *bufP, keysz, scankey, nextkey); offnum = _bt_binsrch(rel, *bufP, keysz, scankey, nextkey);
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
@ -94,13 +94,13 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
/* /*
* We need to save the location of the index entry we chose in the * We need to save the location of the index entry we chose in the
* parent page on a stack. In case we split the tree, we'll use * parent page on a stack. In case we split the tree, we'll use the
* the stack to work back up to the parent page. We also save the * stack to work back up to the parent page. We also save the actual
* actual downlink (TID) to uniquely identify the index entry, in * downlink (TID) to uniquely identify the index entry, in case it
* case it moves right while we're working lower in the tree. See * moves right while we're working lower in the tree. See the paper
* the paper by Lehman and Yao for how this is detected and * by Lehman and Yao for how this is detected and handled. (We use the
* handled. (We use the child link to disambiguate duplicate keys * child link to disambiguate duplicate keys in the index -- Lehman
* in the index -- Lehman and Yao disallow duplicate keys.) * 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;
@ -156,19 +156,18 @@ _bt_moveright(Relation rel,
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* When nextkey = false (normal case): if the scan key that brought us * When nextkey = false (normal case): if the scan key that brought us to
* to this page is > the high key stored on the page, then the page * this page is > the high key stored on the page, then the page has split
* has split and we need to move right. (If the scan key is equal to * and we need to move right. (If the scan key is equal to the high key,
* the high key, we might or might not need to move right; have to * we might or might not need to move right; have to scan the page first
* scan the page first anyway.) * anyway.)
* *
* When nextkey = true: move right if the scan key is >= page's high key. * When nextkey = true: move right if the scan key is >= page's high key.
* *
* The page could even have split more than once, so scan as far as * The page could even have split more than once, so scan as far as needed.
* needed.
* *
* We also have to move right if we followed a link that brought us to a * We also have to move right if we followed a link that brought us to a dead
* dead page. * page.
*/ */
cmpval = nextkey ? 0 : 1; cmpval = nextkey ? 0 : 1;
@ -242,24 +241,24 @@ _bt_binsrch(Relation rel,
high = PageGetMaxOffsetNumber(page); high = PageGetMaxOffsetNumber(page);
/* /*
* If there are no keys on the page, return the first available slot. * If there are no keys on the page, return the first available slot. Note
* Note this covers two cases: the page is really empty (no keys), or * this covers two cases: the page is really empty (no keys), or it
* it contains only a high key. The latter case is possible after * contains only a high key. The latter case is possible after vacuuming.
* vacuuming. This can never happen on an internal page, however, * This can never happen on an internal page, however, since they are
* since they are never empty (an internal page must have children). * never empty (an internal page must have children).
*/ */
if (high < low) if (high < low)
return low; return low;
/* /*
* Binary search to find the first key on the page >= scan key, or * Binary search to find the first key on the page >= scan key, or first
* first key > scankey when nextkey is true. * key > scankey when nextkey is true.
* *
* For nextkey=false (cmpval=1), the loop invariant is: all slots before * For nextkey=false (cmpval=1), the loop invariant is: all slots before
* 'low' are < scan key, all slots at or after 'high' are >= scan key. * 'low' are < scan key, all slots at or after 'high' are >= scan key.
* *
* For nextkey=true (cmpval=0), the loop invariant is: all slots before * For nextkey=true (cmpval=0), the loop invariant is: all slots before 'low'
* 'low' are <= scan key, all slots at or after 'high' are > scan key. * are <= scan key, all slots at or after 'high' are > scan key.
* *
* We can fall out when high == low. * We can fall out when high == low.
*/ */
@ -285,15 +284,15 @@ _bt_binsrch(Relation rel,
* At this point we have high == low, but be careful: they could point * At this point we have high == low, but be careful: they could point
* past the last slot on the page. * past the last slot on the page.
* *
* On a leaf page, we always return the first key >= scan key (resp. > * On a leaf page, we always return the first key >= scan key (resp. > scan
* scan key), which could be the last slot + 1. * key), which could be the last slot + 1.
*/ */
if (P_ISLEAF(opaque)) if (P_ISLEAF(opaque))
return low; return low;
/* /*
* On a non-leaf page, return the last key < scan key (resp. <= scan * On a non-leaf page, return the last key < scan key (resp. <= scan key).
* key). There must be one if _bt_compare() is playing by the rules. * There must be one if _bt_compare() is playing by the rules.
*/ */
Assert(low > P_FIRSTDATAKEY(opaque)); Assert(low > P_FIRSTDATAKEY(opaque));
@ -337,8 +336,8 @@ _bt_compare(Relation rel,
int i; int i;
/* /*
* Force result ">" if target item is first data item on an internal * Force result ">" if target item is first data item on an internal page
* page --- see NOTE above. * --- see NOTE above.
*/ */
if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque)) if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque))
return 1; return 1;
@ -347,15 +346,15 @@ _bt_compare(Relation rel,
itup = &(btitem->bti_itup); itup = &(btitem->bti_itup);
/* /*
* The scan key is set up with the attribute number associated with * The scan key is set up with the attribute number associated with each
* each term in the key. It is important that, if the index is * term in the key. It is important that, if the index is multi-key, the
* multi-key, the scan contain the first k key attributes, and that * scan contain the first k key attributes, and that they be in order. If
* they be in order. If you think about how multi-key ordering works, * you think about how multi-key ordering works, you'll understand why
* you'll understand why this is. * this is.
* *
* We don't test for violation of this condition here, however. The * We don't test for violation of this condition here, however. The initial
* initial setup for the index scan had better have gotten it right * setup for the index scan had better have gotten it right (see
* (see _bt_first). * _bt_first).
*/ */
for (i = 1; i <= keysz; i++) for (i = 1; i <= keysz; i++)
@ -381,15 +380,15 @@ _bt_compare(Relation rel,
else else
{ {
/* /*
* The sk_func needs to be passed the index value as left arg * The sk_func needs to be passed the index value as left arg and
* and the sk_argument as right arg (they might be of * the sk_argument as right arg (they might be of different
* different types). Since it is convenient for callers to * types). Since it is convenient for callers to think of
* think of _bt_compare as comparing the scankey to the index * _bt_compare as comparing the scankey to the index item, we have
* item, we have to flip the sign of the comparison result. * to flip the sign of the comparison result.
* *
* Note: curious-looking coding is to avoid overflow if * Note: curious-looking coding is to avoid overflow if comparison
* comparison function returns INT_MIN. There is no risk of * function returns INT_MIN. There is no risk of overflow for
* overflow for positive results. * positive results.
*/ */
result = DatumGetInt32(FunctionCall2(&scankey->sk_func, result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
datum, datum,
@ -505,8 +504,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
pgstat_count_index_scan(&scan->xs_pgstat_info); pgstat_count_index_scan(&scan->xs_pgstat_info);
/* /*
* Examine the scan keys and eliminate any redundant keys; also * Examine the scan keys and eliminate any redundant keys; also discover
* discover how many keys must be matched to continue the scan. * how many keys must be matched to continue the scan.
*/ */
_bt_preprocess_keys(scan); _bt_preprocess_keys(scan);
@ -556,9 +555,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ScanKey cur; ScanKey cur;
/* /*
* chosen is the so-far-chosen key for the current attribute, if * chosen is the so-far-chosen key for the current attribute, if any.
* any. We don't cast the decision in stone until we reach keys * We don't cast the decision in stone until we reach keys for the
* for the next attribute. * next attribute.
*/ */
curattr = 1; curattr = 1;
chosen = NULL; chosen = NULL;
@ -595,9 +594,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
} }
/* /*
* Done if that was the last attribute, or if next key * Done if that was the last attribute, or if next key is not
* is not in sequence (implying no boundary key is available * in sequence (implying no boundary key is available for the
* for the next attribute). * next attribute).
*/ */
if (i >= so->numberOfKeys || if (i >= so->numberOfKeys ||
cur->sk_attno != curattr + 1) cur->sk_attno != curattr + 1)
@ -632,17 +631,17 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
} }
/* /*
* If we found no usable boundary keys, we have to start from one end * If we found no usable boundary keys, we have to start from one end of
* of the tree. Walk down that edge to the first or last key, and * the tree. Walk down that edge to the first or last key, and scan from
* scan from there. * there.
*/ */
if (keysCount == 0) if (keysCount == 0)
return _bt_endpoint(scan, dir); return _bt_endpoint(scan, dir);
/* /*
* We want to start the scan somewhere within the index. Set up a * We want to start the scan somewhere within the index. Set up a
* 3-way-comparison scankey we can use to search for the boundary * 3-way-comparison scankey we can use to search for the boundary point we
* point we identified above. * identified above.
*/ */
Assert(keysCount <= INDEX_MAX_KEYS); Assert(keysCount <= INDEX_MAX_KEYS);
for (i = 0; i < keysCount; i++) for (i = 0; i < keysCount; i++)
@ -650,16 +649,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ScanKey cur = startKeys[i]; ScanKey cur = startKeys[i];
/* /*
* _bt_preprocess_keys disallows it, but it's place to add some * _bt_preprocess_keys disallows it, but it's place to add some code
* code later * later
*/ */
if (cur->sk_flags & SK_ISNULL) if (cur->sk_flags & SK_ISNULL)
elog(ERROR, "btree doesn't support is(not)null, yet"); elog(ERROR, "btree doesn't support is(not)null, yet");
/* /*
* If scankey operator is of default subtype, we can use the * If scankey operator is of default subtype, we can use the cached
* cached comparison procedure; otherwise gotta look it up in the * comparison procedure; otherwise gotta look it up in the catalogs.
* catalogs.
*/ */
if (cur->sk_subtype == InvalidOid) if (cur->sk_subtype == InvalidOid)
{ {
@ -692,13 +690,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
} }
/* /*
* Examine the selected initial-positioning strategy to determine * Examine the selected initial-positioning strategy to determine exactly
* exactly where we need to start the scan, and set flag variables to * where we need to start the scan, and set flag variables to control the
* control the code below. * code below.
* *
* If nextkey = false, _bt_search and _bt_binsrch will locate the first * If nextkey = false, _bt_search and _bt_binsrch will locate the first item
* item >= scan key. If nextkey = true, they will locate the first * >= scan key. If nextkey = true, they will locate the first item > scan
* item > scan key. * key.
* *
* If goback = true, we will then step back one item, while if goback = * If goback = true, we will then step back one item, while if goback =
* false, we will start the scan on the located item. * false, we will start the scan on the located item.
@ -710,10 +708,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
case BTLessStrategyNumber: case BTLessStrategyNumber:
/* /*
* Find first item >= scankey, then back up one to arrive at * Find first item >= scankey, then back up one to arrive at last
* last item < scankey. (Note: this positioning strategy is * item < scankey. (Note: this positioning strategy is only used
* only used for a backward scan, so that is always the * for a backward scan, so that is always the correct starting
* correct starting position.) * position.)
*/ */
nextkey = false; nextkey = false;
goback = true; goback = true;
@ -722,10 +720,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
case BTLessEqualStrategyNumber: case BTLessEqualStrategyNumber:
/* /*
* Find first item > scankey, then back up one to arrive at * Find first item > scankey, then back up one to arrive at last
* last item <= scankey. (Note: this positioning strategy is * item <= scankey. (Note: this positioning strategy is only used
* only used for a backward scan, so that is always the * for a backward scan, so that is always the correct starting
* correct starting position.) * position.)
*/ */
nextkey = true; nextkey = true;
goback = true; goback = true;
@ -734,14 +732,14 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
case BTEqualStrategyNumber: case BTEqualStrategyNumber:
/* /*
* If a backward scan was specified, need to start with last * If a backward scan was specified, need to start with last equal
* equal item not first one. * item not first one.
*/ */
if (ScanDirectionIsBackward(dir)) if (ScanDirectionIsBackward(dir))
{ {
/* /*
* This is the same as the <= strategy. We will check at * This is the same as the <= strategy. We will check at the
* the end whether the found item is actually =. * end whether the found item is actually =.
*/ */
nextkey = true; nextkey = true;
goback = true; goback = true;
@ -749,8 +747,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
else else
{ {
/* /*
* This is the same as the >= strategy. We will check at * This is the same as the >= strategy. We will check at the
* the end whether the found item is actually =. * end whether the found item is actually =.
*/ */
nextkey = false; nextkey = false;
goback = false; goback = false;
@ -813,24 +811,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ItemPointerSet(current, blkno, offnum); ItemPointerSet(current, blkno, offnum);
/* /*
* If nextkey = false, we are positioned at the first item >= scan * If nextkey = false, we are positioned at the first item >= scan key, or
* key, or possibly at the end of a page on which all the existing * possibly at the end of a page on which all the existing items are less
* items are less than the scan key and we know that everything on * than the scan key and we know that everything on later pages is greater
* later pages is greater than or equal to scan key. * than or equal to scan key.
* *
* If nextkey = true, we are positioned at the first item > scan key, or * If nextkey = true, we are positioned at the first item > scan key, or
* possibly at the end of a page on which all the existing items are * possibly at the end of a page on which all the existing items are less
* less than or equal to the scan key and we know that everything on * than or equal to the scan key and we know that everything on later
* later pages is greater than scan key. * pages is greater than scan key.
* *
* The actually desired starting point is either this item or the prior * The actually desired starting point is either this item or the prior one,
* one, or in the end-of-page case it's the first item on the next * or in the end-of-page case it's the first item on the next page or the
* page or the last item on this page. We apply _bt_step if needed to * last item on this page. We apply _bt_step if needed to get to the
* get to the right place. * right place.
* *
* If _bt_step fails (meaning we fell off the end of the index in one * If _bt_step fails (meaning we fell off the end of the index in one
* direction or the other), then there are no matches so we just * direction or the other), then there are no matches so we just return
* return false. * false.
*/ */
if (goback) if (goback)
{ {
@ -902,8 +900,8 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
BlockNumber blkno; BlockNumber blkno;
/* /*
* Don't use ItemPointerGetOffsetNumber or you risk to get assertion * Don't use ItemPointerGetOffsetNumber or you risk to get assertion due
* due to ability of ip_posid to be equal 0. * to ability of ip_posid to be equal 0.
*/ */
offnum = current->ip_posid; offnum = current->ip_posid;
@ -954,9 +952,9 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
/* /*
* Walk left to the next page with data. This is much more * Walk left to the next page with data. This is much more
* complex than the walk-right case because of the possibility * complex than the walk-right case because of the possibility
* that the page to our left splits while we are in flight to * that the page to our left splits while we are in flight to it,
* it, plus the possibility that the page we were on gets * plus the possibility that the page we were on gets deleted
* deleted after we leave it. See nbtree/README for details. * after we leave it. See nbtree/README for details.
*/ */
for (;;) for (;;)
{ {
@ -973,9 +971,9 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* Okay, we managed to move left to a non-deleted page. * Okay, we managed to move left to a non-deleted page. Done
* Done if it's not half-dead and not empty. Else loop * if it's not half-dead and not empty. Else loop back and do
* back and do it all again. * it all again.
*/ */
if (!P_IGNORE(opaque)) if (!P_IGNORE(opaque))
{ {
@ -1043,15 +1041,14 @@ _bt_walk_left(Relation rel, Buffer buf)
/* /*
* If this isn't the page we want, walk right till we find what we * If this isn't the page we want, walk right till we find what we
* want --- but go no more than four hops (an arbitrary limit). If * want --- but go no more than four hops (an arbitrary limit). If we
* we don't find the correct page by then, the most likely bet is * don't find the correct page by then, the most likely bet is that
* that the original page got deleted and isn't in the sibling * the original page got deleted and isn't in the sibling chain at all
* chain at all anymore, not that its left sibling got split more * anymore, not that its left sibling got split more than four times.
* than four times.
* *
* Note that it is correct to test P_ISDELETED not P_IGNORE here, * Note that it is correct to test P_ISDELETED not P_IGNORE here, because
* because half-dead pages are still in the sibling chain. Caller * half-dead pages are still in the sibling chain. Caller must reject
* must reject half-dead pages if wanted. * half-dead pages if wanted.
*/ */
tries = 0; tries = 0;
for (;;) for (;;)
@ -1077,9 +1074,9 @@ _bt_walk_left(Relation rel, Buffer buf)
{ {
/* /*
* It was deleted. Move right to first nondeleted page (there * It was deleted. Move right to first nondeleted page (there
* must be one); that is the page that has acquired the * must be one); that is the page that has acquired the deleted
* deleted one's keyspace, so stepping left from it will take * one's keyspace, so stepping left from it will take us where we
* us where we want to be. * want to be.
*/ */
for (;;) for (;;)
{ {
@ -1095,16 +1092,16 @@ _bt_walk_left(Relation rel, Buffer buf)
} }
/* /*
* Now return to top of loop, resetting obknum to point to * Now return to top of loop, resetting obknum to point to this
* this nondeleted page, and try again. * nondeleted page, and try again.
*/ */
} }
else else
{ {
/* /*
* It wasn't deleted; the explanation had better be that the * It wasn't deleted; the explanation had better be that the page
* page to the left got split or deleted. Without this check, * to the left got split or deleted. Without this check, we'd go
* we'd go into an infinite loop if there's anything wrong. * into an infinite loop if there's anything wrong.
*/ */
if (opaque->btpo_prev == lblkno) if (opaque->btpo_prev == lblkno)
elog(ERROR, "could not find left sibling in \"%s\"", elog(ERROR, "could not find left sibling in \"%s\"",
@ -1137,8 +1134,8 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
/* /*
* If we are looking for a leaf page, okay to descend from fast root; * If we are looking for a leaf page, okay to descend from fast root;
* otherwise better descend from true root. (There is no point in * otherwise better descend from true root. (There is no point in being
* being smarter about intermediate levels.) * smarter about intermediate levels.)
*/ */
if (level == 0) if (level == 0)
buf = _bt_getroot(rel, BT_READ); buf = _bt_getroot(rel, BT_READ);
@ -1159,8 +1156,8 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
/* /*
* If we landed on a deleted page, step right to find a live page * If we landed on a deleted page, step right to find a live page
* (there must be one). Also, if we want the rightmost page, step * (there must be one). Also, if we want the rightmost page, step
* right if needed to get to it (this could happen if the page * right if needed to get to it (this could happen if the page split
* split since we obtained a pointer to it). * since we obtained a pointer to it).
*/ */
while (P_IGNORE(opaque) || while (P_IGNORE(opaque) ||
(rightmost && !P_RIGHTMOST(opaque))) (rightmost && !P_RIGHTMOST(opaque)))
@ -1228,9 +1225,9 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
so = (BTScanOpaque) scan->opaque; so = (BTScanOpaque) scan->opaque;
/* /*
* Scan down to the leftmost or rightmost leaf page. This is a * Scan down to the leftmost or rightmost leaf page. This is a simplified
* simplified version of _bt_search(). We don't maintain a stack * version of _bt_search(). We don't maintain a stack since we know we
* since we know we won't need it. * won't need it.
*/ */
buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir)); buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir));
@ -1261,8 +1258,7 @@ _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 if (start < P_FIRSTDATAKEY(opaque)) /* watch out for empty page */
* page */
start = P_FIRSTDATAKEY(opaque); start = P_FIRSTDATAKEY(opaque);
} }
else else
@ -1276,8 +1272,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
so->btso_curbuf = buf; so->btso_curbuf = buf;
/* /*
* Left/rightmost page could be empty due to deletions, if so step * Left/rightmost page could be empty due to deletions, if so step till we
* till we find a nonempty page. * find a nonempty page.
*/ */
if (start > maxoff) if (start > maxoff)
{ {
@ -1291,8 +1287,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
itup = &(btitem->bti_itup); itup = &(btitem->bti_itup);
/* /*
* Okay, we are on the first or last tuple. Does it pass all the * Okay, we are on the first or last tuple. Does it pass all the quals?
* quals?
*/ */
if (_bt_checkkeys(scan, itup, dir, &continuescan)) if (_bt_checkkeys(scan, itup, dir, &continuescan))
{ {

View File

@ -56,7 +56,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.94 2005/08/11 13:22:33 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.95 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -99,12 +99,10 @@ typedef struct BTPageState
{ {
Page btps_page; /* workspace for page building */ Page btps_page; /* workspace for page building */
BlockNumber btps_blkno; /* block # to write this page at */ BlockNumber btps_blkno; /* block # to write this page at */
BTItem btps_minkey; /* copy of minimum key (first item) on BTItem btps_minkey; /* copy of minimum key (first item) on page */
* page */
OffsetNumber btps_lastoff; /* last item offset loaded */ OffsetNumber btps_lastoff; /* last item offset loaded */
uint32 btps_level; /* tree level (0 = leaf) */ uint32 btps_level; /* tree level (0 = leaf) */
Size btps_full; /* "full" if less than this much free Size btps_full; /* "full" if less than this much free space */
* space */
struct BTPageState *btps_next; /* link to parent level, if any */ struct BTPageState *btps_next; /* link to parent level, if any */
} BTPageState; } BTPageState;
@ -157,21 +155,21 @@ _bt_spoolinit(Relation index, bool isunique, bool isdead)
btspool->isunique = isunique; btspool->isunique = isunique;
/* /*
* We size the sort area as maintenance_work_mem rather than work_mem * We size the sort area as maintenance_work_mem rather than work_mem to
* to speed index creation. This should be OK since a single backend * speed index creation. This should be OK since a single backend can't
* can't run multiple index creations in parallel. Note that creation * run multiple index creations in parallel. Note that creation of a
* of a unique index actually requires two BTSpool objects. We expect * unique index actually requires two BTSpool objects. We expect that the
* that the second one (for dead tuples) won't get very full, so we * second one (for dead tuples) won't get very full, so we give it only
* give it only work_mem. * work_mem.
*/ */
btKbytes = isdead ? work_mem : maintenance_work_mem; btKbytes = isdead ? work_mem : maintenance_work_mem;
btspool->sortstate = tuplesort_begin_index(index, isunique, btspool->sortstate = tuplesort_begin_index(index, isunique,
btKbytes, false); btKbytes, false);
/* /*
* Currently, tuplesort provides sort functions on IndexTuples. If we * Currently, tuplesort provides sort functions on IndexTuples. If we kept
* kept anything in a BTItem other than a regular IndexTuple, we'd * anything in a BTItem other than a regular IndexTuple, we'd need to
* need to modify tuplesort to understand BTItems as such. * modify tuplesort to understand BTItems as such.
*/ */
Assert(sizeof(BTItemData) == sizeof(IndexTupleData)); Assert(sizeof(BTItemData) == sizeof(IndexTupleData));
@ -222,8 +220,8 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
wstate.index = btspool->index; wstate.index = btspool->index;
/* /*
* We need to log index creation in WAL iff WAL archiving is enabled * We need to log index creation in WAL iff WAL archiving is enabled AND
* AND it's not a temp index. * it's not a temp index.
*/ */
wstate.btws_use_wal = XLogArchivingActive() && !wstate.index->rd_istemp; wstate.btws_use_wal = XLogArchivingActive() && !wstate.index->rd_istemp;
@ -313,9 +311,9 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
/* /*
* If we have to write pages nonsequentially, fill in the space with * If we have to write pages nonsequentially, fill in the space with
* zeroes until we come back and overwrite. This is not logically * zeroes until we come back and overwrite. This is not logically
* necessary on standard Unix filesystems (unwritten space will read * necessary on standard Unix filesystems (unwritten space will read as
* as zeroes anyway), but it should help to avoid fragmentation. The * zeroes anyway), but it should help to avoid fragmentation. The dummy
* dummy pages aren't WAL-logged though. * pages aren't WAL-logged though.
*/ */
while (blkno > wstate->btws_pages_written) while (blkno > wstate->btws_pages_written)
{ {
@ -328,8 +326,8 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
/* /*
* Now write the page. We say isTemp = true even if it's not a temp * Now write the page. We say isTemp = true even if it's not a temp
* index, because there's no need for smgr to schedule an fsync for * index, because there's no need for smgr to schedule an fsync for this
* this write; we'll do it ourselves before ending the build. * write; we'll do it ourselves before ending the build.
*/ */
smgrwrite(wstate->index->rd_smgr, blkno, (char *) page, true); smgrwrite(wstate->index->rd_smgr, blkno, (char *) page, true);
@ -483,15 +481,15 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
btisz = MAXALIGN(btisz); btisz = MAXALIGN(btisz);
/* /*
* Check whether the item can fit on a btree page at all. (Eventually, * Check whether the item can fit on a btree page at all. (Eventually, we
* we ought to try to apply TOAST methods if not.) We actually need to * ought to try to apply TOAST methods if not.) We actually need to be
* be able to fit three items on every page, so restrict any one item * able to fit three items on every page, so restrict any one item to 1/3
* to 1/3 the per-page available space. Note that at this point, btisz * the per-page available space. Note that at this point, btisz doesn't
* doesn't include the ItemId. * include the ItemId.
* *
* NOTE: similar code appears in _bt_insertonpg() to defend against * NOTE: similar code appears in _bt_insertonpg() to defend against oversize
* oversize items being inserted into an already-existing index. But * items being inserted into an already-existing index. But during
* during creation of an index, we don't go through there. * creation of an index, we don't go through there.
*/ */
if (btisz > BTMaxItemSize(npage)) if (btisz > BTMaxItemSize(npage))
ereport(ERROR, ereport(ERROR,
@ -523,11 +521,11 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
/* /*
* We copy the last item on the page into the new page, and then * We copy the last item on the page into the new page, and then
* rearrange the old page so that the 'last item' becomes its high * rearrange the old page so that the 'last item' becomes its high key
* key rather than a true data item. There had better be at least * rather than a true data item. There had better be at least two
* two items on the page already, else the page would be empty of * items on the page already, else the page would be empty of useful
* useful data. (Hence, we must allow pages to be packed at least * data. (Hence, we must allow pages to be packed at least 2/3rds
* 2/3rds full; the 70% figure used above is close to minimum.) * full; the 70% figure used above is close to minimum.)
*/ */
Assert(last_off > P_FIRSTKEY); Assert(last_off > P_FIRSTKEY);
ii = PageGetItemId(opage, last_off); ii = PageGetItemId(opage, last_off);
@ -544,8 +542,8 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
/* /*
* Link the old page into its parent, using its minimum key. If we * Link the old page into its parent, using its minimum key. If we
* don't have a parent, we have to create one; this adds a new * don't have a parent, we have to create one; this adds a new btree
* btree level. * level.
*/ */
if (state->btps_next == NULL) if (state->btps_next == NULL)
state->btps_next = _bt_pagestate(wstate, state->btps_level + 1); state->btps_next = _bt_pagestate(wstate, state->btps_level + 1);
@ -557,9 +555,9 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
pfree(state->btps_minkey); pfree(state->btps_minkey);
/* /*
* 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
* copy it off the old page, not the new one, in case we are not * it off the old page, not the new one, in case we are not at leaf
* at leaf level. * level.
*/ */
state->btps_minkey = _bt_formitem(&(obti->bti_itup)); state->btps_minkey = _bt_formitem(&(obti->bti_itup));
@ -576,8 +574,8 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
} }
/* /*
* Write out the old page. We never need to touch it again, so we * Write out the old page. We never need to touch it again, so we can
* can free the opage workspace too. * free the opage workspace too.
*/ */
_bt_blwritepage(wstate, opage, oblkno); _bt_blwritepage(wstate, opage, oblkno);
@ -588,10 +586,10 @@ _bt_buildadd(BTWriteState *wstate, 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
* Note this will only happen for the first item on a level; on later * this will only happen for the first item on a level; on later pages,
* pages, the first item for a page is copied from the prior page in * the first item for a page is copied from the prior page in the code
* the code above. * above.
*/ */
if (last_off == P_HIKEY) if (last_off == P_HIKEY)
{ {
@ -636,9 +634,9 @@ _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
* We have to link the last page on this level to somewhere. * We have to link the last page on this level to somewhere.
* *
* 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.
* key. This may cause the last page of the parent level to * This may cause the last page of the parent level to split, but
* split, but that's not a problem -- we haven't gotten to it yet. * that's not a problem -- we haven't gotten to it yet.
*/ */
if (s->btps_next == NULL) if (s->btps_next == NULL)
{ {
@ -657,8 +655,8 @@ _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
} }
/* /*
* This is the rightmost page, so the ItemId array needs to be * This is the rightmost page, so the ItemId array needs to be slid
* slid back one slot. Then we can dump out the page. * back one slot. Then we can dump out the page.
*/ */
_bt_slideleft(s->btps_page); _bt_slideleft(s->btps_page);
_bt_blwritepage(wstate, s->btps_page, s->btps_blkno); _bt_blwritepage(wstate, s->btps_page, s->btps_blkno);
@ -667,9 +665,9 @@ _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
/* /*
* As the last step in the process, construct the metapage and make it * As the last step in the process, construct the metapage and make it
* point to the new root (unless we had no data at all, in which case * point to the new root (unless we had no data at all, in which case it's
* it's set to point to "P_NONE"). This changes the index to the * set to point to "P_NONE"). This changes the index to the "valid" state
* "valid" state by filling in a valid magic number in the metapage. * by filling in a valid magic number in the metapage.
*/ */
metapage = (Page) palloc(BLCKSZ); metapage = (Page) palloc(BLCKSZ);
_bt_initmetapage(metapage, rootblkno, rootlevel); _bt_initmetapage(metapage, rootblkno, rootlevel);
@ -805,19 +803,19 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
_bt_uppershutdown(wstate, state); _bt_uppershutdown(wstate, state);
/* /*
* If the index isn't temp, we must fsync it down to disk before it's * If the index isn't temp, we must fsync it down to disk before it's safe
* safe to commit the transaction. (For a temp index we don't care * to commit the transaction. (For a temp index we don't care since the
* since the index will be uninteresting after a crash anyway.) * index will be uninteresting after a crash anyway.)
* *
* It's obvious that we must do this when not WAL-logging the build. It's * It's obvious that we must do this when not WAL-logging the build. It's
* less obvious that we have to do it even if we did WAL-log the index * less obvious that we have to do it even if we did WAL-log the index
* pages. The reason is that since we're building outside shared * pages. The reason is that since we're building outside shared buffers,
* buffers, a CHECKPOINT occurring during the build has no way to * a CHECKPOINT occurring during the build has no way to flush the
* flush the previously written data to disk (indeed it won't know the * previously written data to disk (indeed it won't know the index even
* index even exists). A crash later on would replay WAL from the * exists). A crash later on would replay WAL from the checkpoint,
* checkpoint, therefore it wouldn't replay our earlier WAL entries. * therefore it wouldn't replay our earlier WAL entries. If we do not
* If we do not fsync those pages here, they might still not be on * fsync those pages here, they might still not be on disk when the crash
* disk when the crash occurs. * occurs.
*/ */
if (!wstate->index->rd_istemp) if (!wstate->index->rd_istemp)
smgrimmedsync(wstate->index->rd_smgr); smgrimmedsync(wstate->index->rd_smgr);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.63 2005/06/13 23:14:48 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.64 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -48,8 +48,8 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
bool null; bool null;
/* /*
* We can use the cached (default) support procs since no * We can use the cached (default) support procs since no cross-type
* cross-type comparison can be needed. * comparison can be needed.
*/ */
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
arg = index_getattr(itup, i + 1, itupdesc, &null); arg = index_getattr(itup, i + 1, itupdesc, &null);
@ -93,8 +93,8 @@ _bt_mkscankey_nodata(Relation rel)
FmgrInfo *procinfo; FmgrInfo *procinfo;
/* /*
* We can use the cached (default) support procs since no * We can use the cached (default) support procs since no cross-type
* cross-type comparison can be needed. * comparison can be needed.
*/ */
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
ScanKeyEntryInitializeWithInfo(&skey[i], ScanKeyEntryInitializeWithInfo(&skey[i],
@ -257,9 +257,9 @@ _bt_preprocess_keys(IndexScanDesc scan)
if (numberOfKeys == 1) if (numberOfKeys == 1)
{ {
/* /*
* We don't use indices for 'A is null' and 'A is not null' * We don't use indices for 'A is null' and 'A is not null' currently
* currently and 'A < = > <> NULL' will always fail - so qual is * and 'A < = > <> NULL' will always fail - so qual is not OK if
* not OK if comparison value is NULL. - vadim 03/21/97 * comparison value is NULL. - vadim 03/21/97
*/ */
if (cur->sk_flags & SK_ISNULL) if (cur->sk_flags & SK_ISNULL)
so->qual_ok = false; so->qual_ok = false;
@ -286,20 +286,20 @@ _bt_preprocess_keys(IndexScanDesc scan)
/* /*
* Initialize for processing of keys for attr 1. * Initialize for processing of keys for attr 1.
* *
* xform[i] points to the currently best scan key of strategy type i+1, * xform[i] points to the currently best scan key of strategy type i+1, if
* if any is found with a default operator subtype; it is NULL if we * any is found with a default operator subtype; it is NULL if we haven't
* haven't yet found such a key for this attr. Scan keys of * yet found such a key for this attr. Scan keys of nondefault subtypes
* nondefault subtypes are transferred to the output with no * are transferred to the output with no processing except for noting if
* processing except for noting if they are of "=" type. * they are of "=" type.
*/ */
attno = 1; attno = 1;
memset(xform, 0, sizeof(xform)); memset(xform, 0, sizeof(xform));
hasOtherTypeEqual = false; hasOtherTypeEqual = false;
/* /*
* Loop iterates from 0 to numberOfKeys inclusive; we use the last * Loop iterates from 0 to numberOfKeys inclusive; we use the last pass to
* pass to handle after-last-key processing. Actual exit from the * handle after-last-key processing. Actual exit from the loop is at the
* loop is at the "break" statement below. * "break" statement below.
*/ */
for (i = 0;; cur++, i++) for (i = 0;; cur++, i++)
{ {
@ -319,8 +319,8 @@ _bt_preprocess_keys(IndexScanDesc scan)
} }
/* /*
* If we are at the end of the keys for a particular attr, finish * If we are at the end of the keys for a particular attr, finish up
* up processing and emit the cleaned-up keys. * processing and emit the cleaned-up keys.
*/ */
if (i == numberOfKeys || cur->sk_attno != attno) if (i == numberOfKeys || cur->sk_attno != attno)
{ {
@ -331,9 +331,9 @@ _bt_preprocess_keys(IndexScanDesc scan)
elog(ERROR, "btree index keys must be ordered by attribute"); elog(ERROR, "btree index keys must be ordered by attribute");
/* /*
* If = has been specified, no other key will be used. In case * If = has been specified, no other key will be used. In case of
* of key > 2 && key == 1 and so on we have to set qual_ok to * key > 2 && key == 1 and so on we have to set qual_ok to false
* false before discarding the other keys. * before discarding the other keys.
*/ */
if (xform[BTEqualStrategyNumber - 1]) if (xform[BTEqualStrategyNumber - 1])
{ {
@ -411,8 +411,8 @@ _bt_preprocess_keys(IndexScanDesc scan)
} }
/* /*
* If all attrs before this one had "=", include these keys * If all attrs before this one had "=", include these keys into
* into the required-keys count. * the required-keys count.
*/ */
if (priorNumberOfEqualCols == attno - 1) if (priorNumberOfEqualCols == attno - 1)
so->numberOfRequiredKeys = new_numberOfKeys; so->numberOfRequiredKeys = new_numberOfKeys;
@ -526,11 +526,11 @@ _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
* reached the upper limit of the range of values for this * the upper limit of the range of values for this index attr. On
* index attr. On a forward scan, we can stop if this qual is * a forward scan, we can stop if this qual is one of the "must
* one of the "must match" subset. On a backward scan, * match" subset. On a backward scan, however, we should keep
* however, we should keep going. * going.
*/ */
if (ikey < so->numberOfRequiredKeys && if (ikey < so->numberOfRequiredKeys &&
ScanDirectionIsForward(dir)) ScanDirectionIsForward(dir))
@ -547,24 +547,22 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
if (!DatumGetBool(test)) if (!DatumGetBool(test))
{ {
/* /*
* Tuple fails this qual. If it's a required qual, then we * Tuple fails this qual. If it's a required qual, then we may be
* may be able to conclude no further tuples will pass, * able to conclude no further tuples will pass, either. We have
* either. We have to look at the scan direction and the qual * to look at the scan direction and the qual type.
* type.
* *
* Note: the only case in which we would keep going after failing * Note: the only case in which we would keep going after failing a
* a required qual is if there are partially-redundant quals * required qual is if there are partially-redundant quals that
* that _bt_preprocess_keys() was unable to eliminate. For * _bt_preprocess_keys() was unable to eliminate. For example,
* example, given "x > 4 AND x > 10" where both are cross-type * given "x > 4 AND x > 10" where both are cross-type comparisons
* comparisons and so not removable, we might start the scan * and so not removable, we might start the scan at the x = 4
* at the x = 4 boundary point. The "x > 10" condition will * boundary point. The "x > 10" condition will fail until we pass
* fail until we pass x = 10, but we must not stop the scan on * x = 10, but we must not stop the scan on its account.
* its account.
* *
* Note: because we stop the scan as soon as any required * Note: because we stop the scan as soon as any required equality
* equality qual fails, it is critical that equality quals be * qual fails, it is critical that equality quals be used for the
* used for the initial positioning in _bt_first() when they * initial positioning in _bt_first() when they are available. See
* are available. See comments in _bt_first(). * comments in _bt_first().
*/ */
if (ikey < so->numberOfRequiredKeys) if (ikey < so->numberOfRequiredKeys)
{ {

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.22 2005/06/06 17:01:22 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.23 2005/10/15 02:49:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -136,8 +136,8 @@ _bt_restore_meta(Relation reln, XLogRecPtr lsn,
pageop->btpo_flags = BTP_META; pageop->btpo_flags = BTP_META;
/* /*
* Set pd_lower just past the end of the metadata. This is not * Set pd_lower just past the end of the metadata. This is not essential
* essential but it makes the page look compressible to xlog.c. * but it makes the page look compressible to xlog.c.
*/ */
((PageHeader) metapg)->pd_lower = ((PageHeader) metapg)->pd_lower =
((char *) md + sizeof(BTMetaPageData)) - (char *) metapg; ((char *) md + sizeof(BTMetaPageData)) - (char *) metapg;

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