pgindent run. Make it all clean.

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

View File

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

View File

@ -1,8 +1,8 @@
extern void set_parse_buffer( char* s ); extern void set_parse_buffer(char *s);
extern void reset_parse_buffer( void ); extern void reset_parse_buffer(void);
extern int read_parse_buffer( void ); extern int read_parse_buffer(void);
extern char * parse_buffer( void ); extern char *parse_buffer(void);
extern char * parse_buffer_ptr( void ); extern char *parse_buffer_ptr(void);
extern unsigned int parse_buffer_curr_char( void ); extern unsigned int parse_buffer_curr_char(void);
extern unsigned int parse_buffer_pos( void ); extern unsigned int parse_buffer_pos(void);
extern unsigned int parse_buffer_size( void ); extern unsigned int parse_buffer_size(void);

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -9,7 +9,7 @@
const int EARTH_RADIUS = 3958.747716; const int EARTH_RADIUS = 3958.747716;
const int TWO_PI = 2.0 * M_PI; const int TWO_PI = 2.0 * M_PI;
double *geo_distance(Point *pt1, Point *pt2); double *geo_distance(Point *pt1, Point *pt2);
/****************************************************** /******************************************************

View File

@ -20,7 +20,7 @@ main(int argc, char **argv)
char attname[256]; char attname[256];
char typname[256]; char typname[256];
int count; int count;
char optstr[256]; char optstr[256];
if (argc != 2) if (argc != 2)
halt("Usage: %s database\n", argv[0]); halt("Usage: %s database\n", argv[0]);

View File

@ -62,11 +62,11 @@ select p.* from product p, title_fti f1, title_fti f2 where
that can build the final query automatigally? that can build the final query automatigally?
*/ */
extern Datum fti(PG_FUNCTION_ARGS); extern Datum fti(PG_FUNCTION_ARGS);
static char *breakup(char *, char *); static char *breakup(char *, char *);
static bool is_stopword(char *); static bool is_stopword(char *);
static bool new_tuple = false; static bool new_tuple = false;
/* THIS LIST MUST BE IN SORTED ORDER, A BINARY SEARCH IS USED!!!! */ /* THIS LIST MUST BE IN SORTED ORDER, A BINARY SEARCH IS USED!!!! */

View File

@ -1,7 +1,7 @@
/* /*
* PostgreSQL type definitions for managed LargeObjects. * PostgreSQL type definitions for managed LargeObjects.
* *
* $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.7 2001/02/10 02:31:25 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.8 2001/03/22 03:59:09 momjian Exp $
* *
*/ */
@ -36,7 +36,7 @@ Blob *lo_in(char *str); /* Create from String */
char *lo_out(Blob * addr);/* Output oid as String */ char *lo_out(Blob * addr);/* Output oid as String */
Oid lo_oid(Blob * addr);/* Return oid as an oid */ Oid lo_oid(Blob * addr);/* Return oid as an oid */
Blob *lo(Oid oid); /* Return Blob based on oid */ Blob *lo(Oid oid); /* Return Blob based on oid */
Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */ Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */
/* /*
* This creates a large object, and sets its OID to the value in the * This creates a large object, and sets its OID to the value in the
@ -69,7 +69,7 @@ lo_in(char *str)
* There is no Oid passed, so create a new one * There is no Oid passed, so create a new one
*/ */
oid = DatumGetObjectId(DirectFunctionCall1(lo_creat, oid = DatumGetObjectId(DirectFunctionCall1(lo_creat,
Int32GetDatum(INV_READ | INV_WRITE))); Int32GetDatum(INV_READ | INV_WRITE)));
if (oid == InvalidOid) if (oid == InvalidOid)
elog(ERROR, "lo_in: InvalidOid returned from lo_creat"); elog(ERROR, "lo_in: InvalidOid returned from lo_creat");
} }

View File

@ -1,6 +1,6 @@
/* /*
oid2name; a postgresql 7.1 (+?) app to map OIDs on the filesystem oid2name; a postgresql 7.1 (+?) app to map OIDs on the filesystem
to table and database names. to table and database names.
b. palmer, bpalmer@crimelabs.net 1-17-2001 b. palmer, bpalmer@crimelabs.net 1-17-2001
@ -13,433 +13,439 @@
#include "libpq-fe.h" #include "libpq-fe.h"
/* these are the opts structures for command line params */ /* these are the opts structures for command line params */
struct options { struct options
int getdatabase; {
int gettable; int getdatabase;
int getoid; int gettable;
int getoid;
int systables;
int remotehost; int systables;
int remoteport;
int remoteuser;
int remotepass;
int _oid; int remotehost;
char _dbname[128]; int remoteport;
char _tbname[128]; int remoteuser;
int remotepass;
char _hostname[128]; int _oid;
char _port[6]; char _dbname[128];
char _username[128]; char _tbname[128];
char _password[128];
char _hostname[128];
char _port[6];
char _username[128];
char _password[128];
}; };
/* function prototypes */ /* function prototypes */
void get_opts(int, char **, struct options *); void get_opts(int, char **, struct options *);
PGconn *sql_conn(char *, struct options *); PGconn *sql_conn(char *, struct options *);
void sql_exec_error (int); void sql_exec_error(int);
int sql_exec(PGconn *, char *, int); int sql_exec(PGconn *, char *, int);
void sql_exec_dumpdb(PGconn *); void sql_exec_dumpdb(PGconn *);
void sql_exec_dumptable(PGconn *, int); void sql_exec_dumptable(PGconn *, int);
void sql_exec_searchtable(PGconn *, char *); void sql_exec_searchtable(PGconn *, char *);
void sql_exec_searchoid(PGconn *, int); void sql_exec_searchoid(PGconn *, int);
/* fuction to parse command line options and check for some usage errors. */ /* fuction to parse command line options and check for some usage errors. */
void get_opts(int argc, char **argv, struct options *my_opts) void
get_opts(int argc, char **argv, struct options * my_opts)
{ {
char c; char c;
/* set the defaults */ /* set the defaults */
my_opts->getdatabase = 0; my_opts->getdatabase = 0;
my_opts->gettable = 0; my_opts->gettable = 0;
my_opts->getoid = 0; my_opts->getoid = 0;
my_opts->systables = 0; my_opts->systables = 0;
my_opts->remotehost = 0; my_opts->remotehost = 0;
my_opts->remoteport = 0; my_opts->remoteport = 0;
my_opts->remoteuser = 0; my_opts->remoteuser = 0;
my_opts->remotepass = 0; my_opts->remotepass = 0;
/* get opts */ /* get opts */
while( (c = getopt(argc, argv, "H:p:U:P:d:t:o:xh?")) != EOF) while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:xh?")) != EOF)
{
switch(c)
{ {
/* specify the database */ switch (c)
case 'd': {
my_opts->getdatabase = 1; /* specify the database */
sscanf(optarg, "%s", my_opts->_dbname); case 'd':
break; my_opts->getdatabase = 1;
sscanf(optarg, "%s", my_opts->_dbname);
break;
/* specify the table name */ /* specify the table name */
case 't': case 't':
/* make sure we set the database first */ /* make sure we set the database first */
if(!my_opts->getdatabase) if (!my_opts->getdatabase)
{ {
fprintf(stderr, "Sorry, but you must specify a database to dump from.\n"); fprintf(stderr, "Sorry, but you must specify a database to dump from.\n");
exit(1); exit(1);
} }
/* make sure we don't try to do a -o also */ /* make sure we don't try to do a -o also */
if(my_opts->getoid) if (my_opts->getoid)
{ {
fprintf(stderr, "Sorry, you can only specify either oid or table\n"); fprintf(stderr, "Sorry, you can only specify either oid or table\n");
exit(1); exit(1);
} }
my_opts->gettable = 1; my_opts->gettable = 1;
sscanf(optarg, "%s", my_opts->_tbname); sscanf(optarg, "%s", my_opts->_tbname);
break; break;
/* specify the oid int */ /* specify the oid int */
case 'o': case 'o':
/* make sure we set the database first */ /* make sure we set the database first */
if(!my_opts->getdatabase) if (!my_opts->getdatabase)
{ {
fprintf(stderr, "Sorry, but you must specify a database to dump from.\n"); fprintf(stderr, "Sorry, but you must specify a database to dump from.\n");
exit(1); exit(1);
} }
/* make sure we don't try to do a -t also */ /* make sure we don't try to do a -t also */
if(my_opts->gettable) if (my_opts->gettable)
{ {
fprintf(stderr, "Sorry, you can only specify either oid or table\n"); fprintf(stderr, "Sorry, you can only specify either oid or table\n");
exit(1); exit(1);
} }
my_opts->getoid = 1; my_opts->getoid = 1;
sscanf(optarg, "%i", &my_opts->_oid); sscanf(optarg, "%i", &my_opts->_oid);
break; break;
/* host to connect to */ /* host to connect to */
case 'H': case 'H':
my_opts->remotehost = 1; my_opts->remotehost = 1;
sscanf(optarg, "%s", my_opts->_hostname); sscanf(optarg, "%s", my_opts->_hostname);
break; break;
/* port to connect to on remote host */ /* port to connect to on remote host */
case 'p': case 'p':
my_opts->remoteport = 1; my_opts->remoteport = 1;
sscanf(optarg, "%s", my_opts->_port); sscanf(optarg, "%s", my_opts->_port);
break; break;
/* username */ /* username */
case 'U': case 'U':
my_opts->remoteuser = 1; my_opts->remoteuser = 1;
sscanf(optarg, "%s", my_opts->_username); sscanf(optarg, "%s", my_opts->_username);
break; break;
/* password */ /* password */
case 'P': case 'P':
my_opts->remotepass = 1; my_opts->remotepass = 1;
sscanf(optarg, "%s", my_opts->_password); sscanf(optarg, "%s", my_opts->_password);
break; break;
/* display system tables */ /* display system tables */
case 'x': case 'x':
my_opts->systables = 1; my_opts->systables = 1;
break; break;
/* help! (ugly in code for easier editing) */ /* help! (ugly in code for easier editing) */
case '?': case '?':
case 'h': case 'h':
fprintf(stderr, "\n\ fprintf(stderr, "\n\
Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\ Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\
dafault action display all databases dafault action display all databases\n\
-d database database to oid2name\n\ -d database database to oid2name\n\
-x display system tables\n\ -x display system tables\n\
-t table | -o oid search for table name (-t) or\n\ -t table | -o oid search for table name (-t) or\n\
oid (-o) in -d database oid (-o) in -d database\n\
-H host connect to remote host\n\ -H host connect to remote host\n\
-p port host port to connect to\n\ -p port host port to connect to\n\
-U username username to connect with\n\ -U username username to connect with\n\
-P password password for username\n\n\ -P password password for username\n\n\
"); ");
exit(1); exit(1);
break; break;
}
} }
}
} }
/* establish connection with database. */ /* establish connection with database. */
PGconn *sql_conn(char *dbName, struct options *my_opts) PGconn *
sql_conn(char *dbName, struct options * my_opts)
{ {
char *pghost, *pgport; char *pghost,
char *pgoptions, *pgtty; *pgport;
char *pguser, *pgpass; char *pgoptions,
*pgtty;
char *pguser,
*pgpass;
PGconn *conn; PGconn *conn;
pghost = NULL; pghost = NULL;
pgport = NULL; pgport = NULL;
pgoptions = NULL; /* special options to start up the backend
* server */
pgtty = NULL; /* debugging tty for the backend server */
pguser = NULL; pgoptions = NULL; /* special options to start up the backend
pgpass = NULL; * server */
pgtty = NULL; /* debugging tty for the backend server */
/* override the NULLs with the user params if passed */ pguser = NULL;
if(my_opts->remotehost) pgpass = NULL;
{
pghost = (char *) malloc (128);
sscanf(my_opts->_hostname, "%s", pghost);
}
if(my_opts->remoteport)
{
pgport = (char *) malloc (6);
sscanf(my_opts->_port, "%s", pgport);
}
if(my_opts->remoteuser) /* override the NULLs with the user params if passed */
{ if (my_opts->remotehost)
pguser = (char *) malloc (128); {
sscanf(my_opts->_username, "%s", pguser); pghost = (char *) malloc(128);
} sscanf(my_opts->_hostname, "%s", pghost);
}
if(my_opts->remotepass) if (my_opts->remoteport)
{ {
pgpass = (char *) malloc (128); pgport = (char *) malloc(6);
sscanf(my_opts->_password, "%s", pgpass); sscanf(my_opts->_port, "%s", pgport);
} }
/* login */ if (my_opts->remoteuser)
conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpass); {
pguser = (char *) malloc(128);
sscanf(my_opts->_username, "%s", pguser);
}
/* deal with errors */ if (my_opts->remotepass)
if (PQstatus(conn) == CONNECTION_BAD) {
{ pgpass = (char *) malloc(128);
fprintf(stderr, "Connection to database '%s' failed.\n", dbName); sscanf(my_opts->_password, "%s", pgpass);
fprintf(stderr, "%s", PQerrorMessage(conn)); }
PQfinish(conn);
exit(1);
} /* login */
conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpass);
/* return the conn if good */ /* deal with errors */
return conn; if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
PQfinish(conn);
exit(1);
}
/* return the conn if good */
return conn;
} }
/* If the sql_ command has an error, this function looks up the error number and prints it out. */ /* If the sql_ command has an error, this function looks up the error number and prints it out. */
void sql_exec_error (int error_number) void
sql_exec_error(int error_number)
{ {
fprintf(stderr, "Error number %i.\n", error_number); fprintf(stderr, "Error number %i.\n", error_number);
switch(error_number) switch (error_number)
{ {
case 3: case 3:
fprintf(stderr, "Error: PGRES_COPY_OUT\n"); fprintf(stderr, "Error: PGRES_COPY_OUT\n");
break; break;
case 4: case 4:
fprintf(stderr, "Error: PGRES_COPY_IN\n"); fprintf(stderr, "Error: PGRES_COPY_IN\n");
break; break;
case 5: case 5:
fprintf(stderr, "Error: PGRES_BAD_RESPONCE\n"); fprintf(stderr, "Error: PGRES_BAD_RESPONCE\n");
break; break;
case 6: case 6:
fprintf(stderr, "Error: PGRES_NONFATAL_ERROR\n"); fprintf(stderr, "Error: PGRES_NONFATAL_ERROR\n");
break; break;
case 7: case 7:
fprintf(stderr, "Error: PGRES_FATAL_ERROR\n"); fprintf(stderr, "Error: PGRES_FATAL_ERROR\n");
break; break;
} }
} }
/* actual code to make call to the database and print the output data */ /* actual code to make call to the database and print the output data */
int sql_exec(PGconn *conn, char *todo, int match) int
sql_exec(PGconn *conn, char *todo, int match)
{ {
PGresult *res; PGresult *res;
int numbfields; int numbfields;
int error_number; int error_number;
int i, len; int i,
len;
/* make the call */ /* make the call */
res = PQexec(conn, todo); res = PQexec(conn, todo);
/* check and deal with errors */ /* check and deal with errors */
if (!res || PQresultStatus(res) > 2) if (!res || PQresultStatus(res) > 2)
{ {
error_number = PQresultStatus(res); error_number = PQresultStatus(res);
fprintf(stderr, "There was an error in the SQL command:\n%s\n", todo); fprintf(stderr, "There was an error in the SQL command:\n%s\n", todo);
sql_exec_error(error_number); sql_exec_error(error_number);
fprintf(stderr, "PQerrorMessage = %s\n", PQerrorMessage(conn)); fprintf(stderr, "PQerrorMessage = %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(-1);
}
/* get the number of fields */ PQclear(res);
numbfields = PQntuples(res); PQfinish(conn);
exit(-1);
}
/* if we only expect 1 and there mode than, return -2 */ /* get the number of fields */
if(match == 1 && numbfields > 1) numbfields = PQntuples(res);
return -2;
/* return -1 if there aren't any returns */ /* if we only expect 1 and there mode than, return -2 */
if(match == 1 && numbfields < 1) if (match == 1 && numbfields > 1)
return -1; return -2;
/* for each row, dump the information */ /* return -1 if there aren't any returns */
for(i = 0; i < numbfields; i++) if (match == 1 && numbfields < 1)
{ return -1;
len = strlen(PQgetvalue(res, i, 0));
fprintf(stdout, "%-6s = %s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1)); /* for each row, dump the information */
} for (i = 0; i < numbfields; i++)
{
len = strlen(PQgetvalue(res, i, 0));
/* clean the PGconn once done */ fprintf(stdout, "%-6s = %s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1));
PQclear(res); }
return 0; /* clean the PGconn once done */
PQclear(res);
return 0;
} }
/* dump all databases know by the system table */ /* dump all databases know by the system table */
void sql_exec_dumpdb(PGconn *conn) void
sql_exec_dumpdb(PGconn *conn)
{ {
char *todo; char *todo;
todo = (char *) malloc (1024); todo = (char *) malloc(1024);
/* get the oid and database name from the system pg_database table */ /* get the oid and database name from the system pg_database table */
sprintf(todo, "select oid,datname from pg_database"); sprintf(todo, "select oid,datname from pg_database");
sql_exec(conn, todo, 0); sql_exec(conn, todo, 0);
} }
/* display all tables in whatever db we are connected to. don't display the /* display all tables in whatever db we are connected to. don't display the
system tables by default */ system tables by default */
void sql_exec_dumptable(PGconn *conn, int systables) void
sql_exec_dumptable(PGconn *conn, int systables)
{ {
char *todo; char *todo;
todo = (char *) malloc (1024); todo = (char *) malloc(1024);
/* don't exclude the systables if this is set */ /* don't exclude the systables if this is set */
if(systables == 1) if (systables == 1)
sprintf(todo, "select relfilenode,relname from pg_class order by relname"); sprintf(todo, "select relfilenode,relname from pg_class order by relname");
else else
sprintf(todo, "select relfilenode,relname from pg_class where relname not like 'pg_%%' order by relname"); sprintf(todo, "select relfilenode,relname from pg_class where relname not like 'pg_%%' order by relname");
sql_exec(conn, todo, 0); sql_exec(conn, todo, 0);
} }
/* display the oid for a given tablename for whatever db we are connected /* display the oid for a given tablename for whatever db we are connected
to. do we want to allow %bar% in the search? Not now. */ to. do we want to allow %bar% in the search? Not now. */
void sql_exec_searchtable(PGconn *conn, char *tablename) void
sql_exec_searchtable(PGconn *conn, char *tablename)
{ {
int returnvalue; int returnvalue;
char *todo; char *todo;
todo = (char *) malloc (1024); todo = (char *) malloc(1024);
/* get the oid and tablename where the name matches tablename */ /* get the oid and tablename where the name matches tablename */
sprintf(todo, "select relfilenode,relname from pg_class where relname = '%s'", tablename); sprintf(todo, "select relfilenode,relname from pg_class where relname = '%s'", tablename);
returnvalue = sql_exec(conn, todo, 1); returnvalue = sql_exec(conn, todo, 1);
/* deal with the return errors */ /* deal with the return errors */
if(returnvalue == -1) if (returnvalue == -1)
{ printf("No tables with that name found\n");
printf("No tables with that name found\n");
} if (returnvalue == -2)
printf("VERY scary: more than one table with that name found!!\n");
if(returnvalue == -2)
{
printf("VERY scary: more than one table with that name found!!\n");
}
} }
/* same as above */ /* same as above */
void sql_exec_searchoid(PGconn *conn, int oid) void
sql_exec_searchoid(PGconn *conn, int oid)
{ {
int returnvalue; int returnvalue;
char *todo; char *todo;
todo = (char *) malloc (1024); todo = (char *) malloc(1024);
sprintf(todo, "select relfilenode,relname from pg_class where oid = %i", oid); sprintf(todo, "select relfilenode,relname from pg_class where oid = %i", oid);
returnvalue = sql_exec(conn, todo, 1); returnvalue = sql_exec(conn, todo, 1);
if(returnvalue == -1) if (returnvalue == -1)
{ printf("No tables with that oid found\n");
printf("No tables with that oid found\n");
} if (returnvalue == -2)
printf("VERY scary: more than one table with that oid found!!\n");
if(returnvalue == -2)
{
printf("VERY scary: more than one table with that oid found!!\n");
}
} }
int main(int argc, char **argv) int
main(int argc, char **argv)
{ {
struct options *my_opts; struct options *my_opts;
PGconn *pgconn; PGconn *pgconn;
my_opts = (struct options *) malloc (sizeof(struct options)); my_opts = (struct options *) malloc(sizeof(struct options));
/* parse the opts */ /* parse the opts */
get_opts(argc, argv, my_opts); get_opts(argc, argv, my_opts);
/* display all the tables in the database */ /* display all the tables in the database */
if(my_opts->getdatabase & my_opts->gettable) if (my_opts->getdatabase & my_opts->gettable)
{ {
printf("Oid of table %s from database \"%s\":\n", my_opts->_tbname, my_opts->_dbname); printf("Oid of table %s from database \"%s\":\n", my_opts->_tbname, my_opts->_dbname);
printf("_______________________________\n"); printf("_______________________________\n");
pgconn = sql_conn(my_opts->_dbname, my_opts); pgconn = sql_conn(my_opts->_dbname, my_opts);
sql_exec_searchtable(pgconn, my_opts->_tbname); sql_exec_searchtable(pgconn, my_opts->_tbname);
PQfinish(pgconn); PQfinish(pgconn);
exit(1); exit(1);
} }
/* search for the tablename of the given OID */
if(my_opts->getdatabase & my_opts->getoid)
{
printf("Tablename of oid %i from database \"%s\":\n", my_opts->_oid, my_opts->_dbname);
printf("---------------------------------\n");
pgconn = sql_conn(my_opts->_dbname, my_opts); /* search for the tablename of the given OID */
sql_exec_searchoid(pgconn, my_opts->_oid); if (my_opts->getdatabase & my_opts->getoid)
PQfinish(pgconn); {
printf("Tablename of oid %i from database \"%s\":\n", my_opts->_oid, my_opts->_dbname);
printf("---------------------------------\n");
exit(1); pgconn = sql_conn(my_opts->_dbname, my_opts);
} sql_exec_searchoid(pgconn, my_opts->_oid);
PQfinish(pgconn);
/* search for the oid for the given tablename */ exit(1);
if(my_opts->getdatabase) }
{
printf("All tables from database \"%s\":\n", my_opts->_dbname);
printf("---------------------------------\n");
pgconn = sql_conn(my_opts->_dbname, my_opts); /* search for the oid for the given tablename */
sql_exec_dumptable(pgconn, my_opts->systables); if (my_opts->getdatabase)
PQfinish(pgconn); {
printf("All tables from database \"%s\":\n", my_opts->_dbname);
printf("---------------------------------\n");
exit(1); pgconn = sql_conn(my_opts->_dbname, my_opts);
} sql_exec_dumptable(pgconn, my_opts->systables);
PQfinish(pgconn);
/* display all the databases for the server we are connected to.. */ exit(1);
printf("All databases:\n"); }
printf("---------------------------------\n");
pgconn = sql_conn("template1", my_opts);
sql_exec_dumpdb(pgconn);
PQfinish(pgconn);
exit(0); /* display all the databases for the server we are connected to.. */
printf("All databases:\n");
printf("---------------------------------\n");
pgconn = sql_conn("template1", my_opts);
sql_exec_dumpdb(pgconn);
PQfinish(pgconn);
exit(0);
} }

View File

@ -6,7 +6,7 @@
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001; * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD * licence: BSD
* *
* $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.2 2001/03/13 01:17:40 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.3 2001/03/22 03:59:09 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -24,7 +24,7 @@ dbState(DBState state)
{ {
switch (state) switch (state)
{ {
case DB_STARTUP: case DB_STARTUP:
return "STARTUP"; return "STARTUP";
case DB_SHUTDOWNED: case DB_SHUTDOWNED:
return "SHUTDOWNED"; return "SHUTDOWNED";
@ -43,16 +43,17 @@ int
main() main()
{ {
ControlFileData ControlFile; ControlFileData ControlFile;
int fd; int fd;
char ControlFilePath[MAXPGPATH]; char ControlFilePath[MAXPGPATH];
char *DataDir; char *DataDir;
crc64 crc; crc64 crc;
char pgctime_str[32]; char pgctime_str[32];
char ckpttime_str[32]; char ckpttime_str[32];
DataDir = getenv("PGDATA"); DataDir = getenv("PGDATA");
if ( DataDir == NULL ) { if (DataDir == NULL)
fprintf(stderr,"PGDATA is not defined\n"); {
fprintf(stderr, "PGDATA is not defined\n");
exit(1); exit(1);
} }
@ -73,8 +74,8 @@ main()
/* Check the CRC. */ /* Check the CRC. */
INIT_CRC64(crc); INIT_CRC64(crc);
COMP_CRC64(crc, COMP_CRC64(crc,
(char*) &ControlFile + sizeof(crc64), (char *) &ControlFile + sizeof(crc64),
sizeof(ControlFileData) - sizeof(crc64)); sizeof(ControlFileData) - sizeof(crc64));
FIN_CRC64(crc); FIN_CRC64(crc);
@ -93,7 +94,7 @@ main()
"Database state: %s\n" "Database state: %s\n"
"pg_control last modified: %s\n" "pg_control last modified: %s\n"
"Current log file id: %u\n" "Current log file id: %u\n"
"Next log file segment: %u\n" "Next log file segment: %u\n"
"Latest checkpoint location: %X/%X\n" "Latest checkpoint location: %X/%X\n"
"Prior checkpoint location: %X/%X\n" "Prior checkpoint location: %X/%X\n"
"Latest checkpoint's REDO location: %X/%X\n" "Latest checkpoint's REDO location: %X/%X\n"

View File

@ -1,20 +1,20 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.5 2001/01/24 19:42:44 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.6 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -22,17 +22,17 @@
#include "pg_dumplo.h" #include "pg_dumplo.h"
extern int errno; extern int errno;
void void
load_lolist( LODumpMaster *pgLO ) load_lolist(LODumpMaster * pgLO)
{ {
LOlist *ll; LOlist *ll;
int i; int i;
int n; int n;
/* ---------- /* ----------
* Now find any candidate tables who have columns of type oid. * Now find any candidate tables who have columns of type oid.
* *
* NOTE: System tables including pg_largeobject will be ignored. * NOTE: System tables including pg_largeobject will be ignored.
@ -40,8 +40,8 @@ load_lolist( LODumpMaster *pgLO )
* *
* NOTE: the system oid column is ignored, as it has attnum < 1. * NOTE: the system oid column is ignored, as it has attnum < 1.
* This shouldn't matter for correctness, but it saves time. * This shouldn't matter for correctness, but it saves time.
* ---------- * ----------
*/ */
pgLO->res = PQexec(pgLO->conn, pgLO->res = PQexec(pgLO->conn,
"SELECT c.relname, a.attname " "SELECT c.relname, a.attname "
"FROM pg_class c, pg_attribute a, pg_type t " "FROM pg_class c, pg_attribute a, pg_type t "
@ -52,43 +52,49 @@ load_lolist( LODumpMaster *pgLO )
" AND c.relkind = 'r' " " AND c.relkind = 'r' "
" AND c.relname NOT LIKE 'pg_%'"); " AND c.relname NOT LIKE 'pg_%'");
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) { if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname, fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn)); PQerrorMessage(pgLO->conn));
exit(RE_ERROR); exit(RE_ERROR);
} }
if ((n = PQntuples(pgLO->res)) == 0) { if ((n = PQntuples(pgLO->res)) == 0)
{
fprintf(stderr, "%s: No OID columns in the database.\n", progname); fprintf(stderr, "%s: No OID columns in the database.\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist)); pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist));
if (!pgLO->lolist) { if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname); fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
}
for (i = 0, ll = pgLO->lolist; i < n; i++, ll++) {
ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
} }
ll->lo_table = ll->lo_attr = (char *) NULL;
for (i = 0, ll = pgLO->lolist; i < n; i++, ll++)
{
ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
}
ll->lo_table = ll->lo_attr = (char *) NULL;
PQclear(pgLO->res); PQclear(pgLO->res);
} }
void void
pglo_export(LODumpMaster *pgLO) pglo_export(LODumpMaster * pgLO)
{ {
LOlist *ll; LOlist *ll;
int tuples; int tuples;
char path[BUFSIZ], char path[BUFSIZ],
Qbuff[QUERY_BUFSIZ]; Qbuff[QUERY_BUFSIZ];
if (pgLO->action != ACTION_SHOW) { if (pgLO->action != ACTION_SHOW)
time_t t; {
time_t t;
time(&t); time(&t);
fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n"); fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n");
fprintf(pgLO->index, "#\tDate: %s", ctime(&t)); fprintf(pgLO->index, "#\tDate: %s", ctime(&t));
@ -97,90 +103,102 @@ pglo_export(LODumpMaster *pgLO)
fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user); fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user);
fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\n#\n"); fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\n#\n");
} }
pgLO->counter = 0; pgLO->counter = 0;
for(ll=pgLO->lolist; ll->lo_table != NULL; ll++) { for (ll = pgLO->lolist; ll->lo_table != NULL; ll++)
{
/* ---------- /* ----------
* Query: find the LOs referenced by this column * Query: find the LOs referenced by this column
* ---------- * ----------
*/ */
sprintf(Qbuff, "SELECT DISTINCT l.loid FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid", sprintf(Qbuff, "SELECT DISTINCT l.loid FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid",
ll->lo_table, ll->lo_attr); ll->lo_table, ll->lo_attr);
/* puts(Qbuff); */ /* puts(Qbuff); */
pgLO->res = PQexec(pgLO->conn, Qbuff); pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) { if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname, fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn)); PQerrorMessage(pgLO->conn));
} }
else if ((tuples = PQntuples(pgLO->res)) == 0) { else if ((tuples = PQntuples(pgLO->res)) == 0)
{
if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR) if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
printf("%s: no large objects in \"%s\".\"%s\"\n", printf("%s: no large objects in \"%s\".\"%s\"\n",
progname, ll->lo_table, ll->lo_attr); progname, ll->lo_table, ll->lo_attr);
} else { }
else
int t; {
char *val;
int t;
char *val;
/* ---------- /* ----------
* Create DIR/FILE * Create DIR/FILE
* ---------- * ----------
*/ */
if (pgLO->action != ACTION_SHOW) { if (pgLO->action != ACTION_SHOW)
{
sprintf(path, "%s/%s/%s", pgLO->space, pgLO->db, sprintf(path, "%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_table); ll->lo_table);
if (mkdir(path, DIR_UMASK) == -1) { if (mkdir(path, DIR_UMASK) == -1)
if (errno != EEXIST) { {
if (errno != EEXIST)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
sprintf(path, "%s/%s/%s/%s", pgLO->space, pgLO->db, sprintf(path, "%s/%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_table, ll->lo_attr); ll->lo_table, ll->lo_attr);
if (mkdir(path, DIR_UMASK) == -1) { if (mkdir(path, DIR_UMASK) == -1)
if (errno != EEXIST) { {
if (errno != EEXIST)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
if (!pgLO->quiet) if (!pgLO->quiet)
printf("dump %s.%s (%d large obj)\n", printf("dump %s.%s (%d large obj)\n",
ll->lo_table, ll->lo_attr, tuples); ll->lo_table, ll->lo_attr, tuples);
} }
pgLO->counter += tuples; pgLO->counter += tuples;
for(t=0; t<tuples; t++) { for (t = 0; t < tuples; t++)
Oid lo; {
Oid lo;
val = PQgetvalue(pgLO->res, t, 0); val = PQgetvalue(pgLO->res, t, 0);
lo = atooid(val); lo = atooid(val);
if (pgLO->action == ACTION_SHOW) { if (pgLO->action == ACTION_SHOW)
{
printf("%s.%s: %u\n", ll->lo_table, ll->lo_attr, lo); printf("%s.%s: %u\n", ll->lo_table, ll->lo_attr, lo);
continue; continue;
} }
sprintf(path, "%s/%s/%s/%s/%s", pgLO->space, sprintf(path, "%s/%s/%s/%s/%s", pgLO->space,
pgLO->db, ll->lo_table, ll->lo_attr, val); pgLO->db, ll->lo_table, ll->lo_attr, val);
if (lo_export(pgLO->conn, lo, path) < 0) if (lo_export(pgLO->conn, lo, path) < 0)
fprintf(stderr, "%s: lo_export failed:\n%s", progname, fprintf(stderr, "%s: lo_export failed:\n%s", progname,
PQerrorMessage(pgLO->conn)); PQerrorMessage(pgLO->conn));
else else
fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s\n", val, fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s\n", val,
ll->lo_table, ll->lo_attr, pgLO->db, ll->lo_table, ll->lo_attr, val); ll->lo_table, ll->lo_attr, pgLO->db, ll->lo_table, ll->lo_attr, val);
} }
} }

View File

@ -1,20 +1,20 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -22,76 +22,82 @@
#include "pg_dumplo.h" #include "pg_dumplo.h"
extern int errno; extern int errno;
void void
pglo_import(LODumpMaster *pgLO) pglo_import(LODumpMaster * pgLO)
{ {
LOlist loa; LOlist loa;
Oid new_oid; Oid new_oid;
char tab[MAX_TABLE_NAME], attr[MAX_ATTR_NAME], char tab[MAX_TABLE_NAME],
path[BUFSIZ], lo_path[BUFSIZ], attr[MAX_ATTR_NAME],
Qbuff[QUERY_BUFSIZ]; path[BUFSIZ],
lo_path[BUFSIZ],
while(fgets(Qbuff, QUERY_BUFSIZ, pgLO->index)) { Qbuff[QUERY_BUFSIZ];
while (fgets(Qbuff, QUERY_BUFSIZ, pgLO->index))
{
if (*Qbuff == '#') if (*Qbuff == '#')
continue; continue;
if (! pgLO->remove && ! pgLO->quiet) if (!pgLO->remove && !pgLO->quiet)
printf(Qbuff); printf(Qbuff);
sscanf(Qbuff, "%u\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path);
loa.lo_table = tab;
loa.lo_attr = attr;
sprintf(lo_path, "%s/%s", pgLO->space, path); sscanf(Qbuff, "%u\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path);
loa.lo_table = tab;
loa.lo_attr = attr;
sprintf(lo_path, "%s/%s", pgLO->space, path);
/* ---------- /* ----------
* Import LO * Import LO
* ---------- * ----------
*/ */
if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0) { if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0)
{
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn)); fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
PQexec(pgLO->conn, "ROLLBACK"); PQexec(pgLO->conn, "ROLLBACK");
fprintf(stderr, "\n%s: ROLLBACK\n", progname); fprintf(stderr, "\n%s: ROLLBACK\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
if (pgLO->remove) { if (pgLO->remove)
{
notice(pgLO, FALSE); notice(pgLO, FALSE);
if (lo_unlink(pgLO->conn, loa.lo_oid) < 0) if (lo_unlink(pgLO->conn, loa.lo_oid) < 0)
fprintf(stderr, "%s: can't remove LO %u:\n%s", fprintf(stderr, "%s: can't remove LO %u:\n%s",
progname, loa.lo_oid, PQerrorMessage(pgLO->conn)); progname, loa.lo_oid, PQerrorMessage(pgLO->conn));
else if (!pgLO->quiet) else if (!pgLO->quiet)
printf("remove old %u and create new %u\n", printf("remove old %u and create new %u\n",
loa.lo_oid, new_oid); loa.lo_oid, new_oid);
notice(pgLO, TRUE); notice(pgLO, TRUE);
} }
pgLO->counter++; pgLO->counter++;
/* ---------- /* ----------
* UPDATE oid in tab * UPDATE oid in tab
* ---------- * ----------
*/ */
sprintf(Qbuff, "UPDATE \"%s\" SET \"%s\"=%u WHERE \"%s\"=%u", sprintf(Qbuff, "UPDATE \"%s\" SET \"%s\"=%u WHERE \"%s\"=%u",
loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid); loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid);
/*fprintf(stderr, Qbuff);*/ /* fprintf(stderr, Qbuff); */
pgLO->res = PQexec(pgLO->conn, Qbuff); pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_COMMAND_OK) { if (PQresultStatus(pgLO->res) != PGRES_COMMAND_OK)
fprintf(stderr, "%s: %s\n",progname, PQerrorMessage(pgLO->conn)); {
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
PQclear(pgLO->res); PQclear(pgLO->res);
PQexec(pgLO->conn, "ROLLBACK"); PQexec(pgLO->conn, "ROLLBACK");
fprintf(stderr, "\n%s: ROLLBACK\n", progname); fprintf(stderr, "\n%s: ROLLBACK\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
PQclear(pgLO->res); PQclear(pgLO->res);
} }
} }

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.6 2001/02/10 02:31:25 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.7 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -12,238 +12,254 @@
#include "postgres_fe.h" #include "postgres_fe.h"
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <libpq-fe.h> #include <libpq-fe.h>
#include <libpq/libpq-fs.h> #include <libpq/libpq-fs.h>
#include "pg_dumplo.h" #include "pg_dumplo.h"
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
#include <getopt.h> #include <getopt.h>
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1
#endif #endif
extern int errno;
char *progname = NULL; extern int errno;
int main(int argc, char **argv); char *progname = NULL;
int main(int argc, char **argv);
static void usage(void); static void usage(void);
static void parse_lolist (LODumpMaster *pgLO); static void parse_lolist(LODumpMaster * pgLO);
/*----- /*-----
* The mother of all C functions * The mother of all C functions
*----- *-----
*/ */
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
LODumpMaster _pgLO, *pgLO = &_pgLO; LODumpMaster _pgLO,
char *pwd = NULL; *pgLO = &_pgLO;
char *pwd = NULL;
pgLO->argv = argv; pgLO->argv = argv;
pgLO->argc = argc; pgLO->argc = argc;
pgLO->action = 0; pgLO->action = 0;
pgLO->lolist = NULL; pgLO->lolist = NULL;
pgLO->user = NULL; pgLO->user = NULL;
pgLO->db = NULL; pgLO->db = NULL;
pgLO->host = NULL; pgLO->host = NULL;
pgLO->space = NULL; pgLO->space = NULL;
pgLO->index = NULL; pgLO->index = NULL;
pgLO->remove = FALSE; pgLO->remove = FALSE;
pgLO->quiet = FALSE; pgLO->quiet = FALSE;
pgLO->counter = 0; pgLO->counter = 0;
pgLO->lolist_start = 0; pgLO->lolist_start = 0;
progname = argv[0]; progname = argv[0];
/* ---------- /* ----------
* Parse ARGV * Parse ARGV
* ---------- * ----------
*/ */
if (argc > 1) { if (argc > 1)
int arg; {
extern int optind; int arg;
extern int optind;
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
int l_index=0; int l_index = 0;
static struct option l_opt[] = { static struct option l_opt[] = {
{ "help", no_argument, 0, 'h' }, {"help", no_argument, 0, 'h'},
{ "user", required_argument, 0, 'u' }, {"user", required_argument, 0, 'u'},
{ "pwd", required_argument, 0, 'p' }, {"pwd", required_argument, 0, 'p'},
{ "db", required_argument, 0, 'd' }, {"db", required_argument, 0, 'd'},
{ "host", required_argument, 0, 'h' }, {"host", required_argument, 0, 'h'},
{ "space", required_argument, 0, 's' }, {"space", required_argument, 0, 's'},
{ "import", no_argument, 0, 'i' }, {"import", no_argument, 0, 'i'},
{ "export", no_argument, 0, 'e' }, {"export", no_argument, 0, 'e'},
{ "remove", no_argument, 0, 'r' }, {"remove", no_argument, 0, 'r'},
{ "quiet", no_argument, 0, 'q' }, {"quiet", no_argument, 0, 'q'},
{ "all", no_argument, 0, 'a' }, {"all", no_argument, 0, 'a'},
{ "show", no_argument, 0, 'w' }, {"show", no_argument, 0, 'w'},
{ NULL, 0, 0, 0 } {NULL, 0, 0, 0}
}; };
while((arg = getopt_long(argc, argv, "?aehu:p:qd:l:t:irs:w", l_opt, &l_index)) != -1) { while ((arg = getopt_long(argc, argv, "?aehu:p:qd:l:t:irs:w", l_opt, &l_index)) != -1)
{
#else #else
while((arg = getopt(argc, argv, "?aehu:p:qd:l:t:irs:w")) != -1) { while ((arg = getopt(argc, argv, "?aehu:p:qd:l:t:irs:w")) != -1)
{
#endif #endif
switch(arg) { switch (arg)
case '?': {
case 'h': case '?':
usage(); case 'h':
usage();
exit(RE_OK); exit(RE_OK);
case 'u': case 'u':
pgLO->user = strdup(optarg); pgLO->user = strdup(optarg);
break; break;
case 't': case 't':
pgLO->host = strdup(optarg); pgLO->host = strdup(optarg);
break; break;
case 'p': case 'p':
pwd = strdup(optarg); pwd = strdup(optarg);
break; break;
case 'd': case 'd':
pgLO->db = strdup(optarg); pgLO->db = strdup(optarg);
break; break;
case 's': case 's':
pgLO->space = strdup(optarg); pgLO->space = strdup(optarg);
break; break;
case 'i': case 'i':
pgLO->action = ACTION_IMPORT; pgLO->action = ACTION_IMPORT;
break; break;
case 'l': case 'l':
pgLO->action = ACTION_EXPORT_ATTR; pgLO->action = ACTION_EXPORT_ATTR;
pgLO->lolist_start = optind-1; pgLO->lolist_start = optind - 1;
parse_lolist (pgLO); parse_lolist(pgLO);
break; break;
case 'e': case 'e':
case 'a': case 'a':
pgLO->action = ACTION_EXPORT_ALL; pgLO->action = ACTION_EXPORT_ALL;
break; break;
case 'w': case 'w':
pgLO->action = ACTION_SHOW; pgLO->action = ACTION_SHOW;
break; break;
case 'r': case 'r':
pgLO->remove = TRUE; pgLO->remove = TRUE;
break; break;
case 'q': case 'q':
pgLO->quiet = TRUE; pgLO->quiet = TRUE;
break; break;
default: default:
fprintf(stderr, "%s: bad arg -%c\n", progname, arg); fprintf(stderr, "%s: bad arg -%c\n", progname, arg);
usage(); usage();
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
} else { }
else
{
usage(); usage();
exit(RE_ERROR); exit(RE_ERROR);
} }
/* ---------- /* ----------
* Check space * Check space
* ---------- * ----------
*/ */
if (! pgLO->space && ! pgLO->action == ACTION_SHOW) { if (!pgLO->space && !pgLO->action == ACTION_SHOW)
if (!(pgLO->space = getenv("PWD"))) { {
if (!(pgLO->space = getenv("PWD")))
{
fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname); fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
if (!pgLO->action) { if (!pgLO->action)
{
fprintf(stderr, "%s: What do you want - export or import?\n", progname); fprintf(stderr, "%s: What do you want - export or import?\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
/* ---------- /* ----------
* Make connection * Make connection
* ---------- * ----------
*/ */
pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db, pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db,
pgLO->user, pwd); pgLO->user, pwd);
if (PQstatus(pgLO->conn) == CONNECTION_BAD) { if (PQstatus(pgLO->conn) == CONNECTION_BAD)
{
fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn)); fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn));
exit(RE_ERROR); exit(RE_ERROR);
} }
pgLO->host = PQhost(pgLO->conn) ? PQhost(pgLO->conn) : "localhost"; pgLO->host = PQhost(pgLO->conn) ? PQhost(pgLO->conn) : "localhost";
pgLO->db = PQdb(pgLO->conn); pgLO->db = PQdb(pgLO->conn);
pgLO->user = PQuser(pgLO->conn); pgLO->user = PQuser(pgLO->conn);
/* ---------- /* ----------
* Init index file * Init index file
* ---------- * ----------
*/ */
if (pgLO->action != ACTION_SHOW) if (pgLO->action != ACTION_SHOW)
index_file(pgLO); index_file(pgLO);
PQexec(pgLO->conn, "BEGIN"); PQexec(pgLO->conn, "BEGIN");
switch(pgLO->action) { switch (pgLO->action)
{
case ACTION_SHOW: case ACTION_SHOW:
case ACTION_EXPORT_ALL: case ACTION_EXPORT_ALL:
load_lolist(pgLO); load_lolist(pgLO);
/* FALL THROUGH */ /* FALL THROUGH */
case ACTION_EXPORT_ATTR: case ACTION_EXPORT_ATTR:
pglo_export(pgLO); pglo_export(pgLO);
if (!pgLO->quiet) { if (!pgLO->quiet)
{
if (pgLO->action == ACTION_SHOW) if (pgLO->action == ACTION_SHOW)
printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter); printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter);
else else
printf("\nExported %d large objects.\n\n", pgLO->counter); printf("\nExported %d large objects.\n\n", pgLO->counter);
} }
break; break;
case ACTION_IMPORT: case ACTION_IMPORT:
pglo_import(pgLO); pglo_import(pgLO);
if (!pgLO->quiet) if (!pgLO->quiet)
printf("\nImported %d large objects.\n\n", pgLO->counter); printf("\nImported %d large objects.\n\n", pgLO->counter);
break; break;
} }
PQexec(pgLO->conn, "COMMIT"); PQexec(pgLO->conn, "COMMIT");
PQfinish(pgLO->conn); PQfinish(pgLO->conn);
if (pgLO->action != ACTION_SHOW) if (pgLO->action != ACTION_SHOW)
fclose(pgLO->index); fclose(pgLO->index);
exit(RE_OK); exit(RE_OK);
} }
static void static void
parse_lolist (LODumpMaster *pgLO) parse_lolist(LODumpMaster * pgLO)
{ {
LOlist *ll; LOlist *ll;
char **d, char **d,
*loc, *loc,
buff[MAX_TABLE_NAME + MAX_ATTR_NAME +1]; buff[MAX_TABLE_NAME + MAX_ATTR_NAME + 1];
pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist)); pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist));
if (! pgLO->lolist) { if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname); fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR); exit(RE_ERROR);
} }
for( d=pgLO->argv + pgLO->lolist_start, ll=pgLO->lolist; for (d = pgLO->argv + pgLO->lolist_start, ll = pgLO->lolist;
*d != NULL; *d != NULL;
d++, ll++) { d++, ll++)
{
strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME); strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME);
if ((loc = strchr(buff, '.')) == NULL) { if ((loc = strchr(buff, '.')) == NULL)
{
fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff); fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff);
exit(RE_ERROR); exit(RE_ERROR);
} }
*loc = '\0'; *loc = '\0';
ll->lo_table = strdup(buff); ll->lo_table = strdup(buff);
@ -254,55 +270,55 @@ parse_lolist (LODumpMaster *pgLO)
} }
static void static void
usage() usage()
{ {
printf("\npg_dumplo %s - PostgreSQL large objects dump\n", VERSION); printf("\npg_dumplo %s - PostgreSQL large objects dump\n", VERSION);
puts("pg_dumplo [option]\n\n" puts("pg_dumplo [option]\n\n"
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
"-h --help this help\n" "-h --help this help\n"
"-u --user=<username> username for connection to server\n" "-u --user=<username> username for connection to server\n"
"-p --password=<password> password for connection to server\n" "-p --password=<password> password for connection to server\n"
"-d --db=<database> database name\n" "-d --db=<database> database name\n"
"-t --host=<hostname> server hostname\n" "-t --host=<hostname> server hostname\n"
"-s --space=<dir> directory with dump tree (for export/import)\n" "-s --space=<dir> directory with dump tree (for export/import)\n"
"-i --import import large obj dump tree to DB\n" "-i --import import large obj dump tree to DB\n"
"-e --export export (dump) large obj to dump tree\n" "-e --export export (dump) large obj to dump tree\n"
"-l <table.attr ...> dump attribute (columns) with LO to dump tree\n" "-l <table.attr ...> dump attribute (columns) with LO to dump tree\n"
"-a --all dump all LO in DB (default)\n" "-a --all dump all LO in DB (default)\n"
"-r --remove if is set '-i' try remove old LO\n" "-r --remove if is set '-i' try remove old LO\n"
"-q --quiet run quietly\n" "-q --quiet run quietly\n"
"-w --show not dump, but show all LO in DB\n" "-w --show not dump, but show all LO in DB\n"
); /* puts() */ ); /* puts() */
#else #else
"-h this help\n" "-h this help\n"
"-u <username> username for connection to server\n" "-u <username> username for connection to server\n"
"-p <password> password for connection to server\n" "-p <password> password for connection to server\n"
"-d <database> database name\n" "-d <database> database name\n"
"-t <hostname> server hostname\n" "-t <hostname> server hostname\n"
"-s <dir> directory with dump tree (for export/import)\n" "-s <dir> directory with dump tree (for export/import)\n"
"-i import large obj dump tree to DB\n" "-i import large obj dump tree to DB\n"
"-e export (dump) large obj to dump tree\n" "-e export (dump) large obj to dump tree\n"
"-l <table.attr ...> dump attribute (columns) with LO to dump tree\n" "-l <table.attr ...> dump attribute (columns) with LO to dump tree\n"
"-a dump all LO in DB (default)\n" "-a dump all LO in DB (default)\n"
"-r if is set '-i' try remove old LO\n" "-r if is set '-i' try remove old LO\n"
"-q run quietly\n" "-q run quietly\n"
"-w not dump, but show all LO in DB\n" "-w not dump, but show all LO in DB\n"
); /* puts() */ ); /* puts() */
#endif #endif
puts( puts(
"Example (dump): pg_dumplo -d my_db -s /my_dump/dir -l t1.a t1.b t2.a\n" "Example (dump): pg_dumplo -d my_db -s /my_dump/dir -l t1.a t1.b t2.a\n"
" pg_dumplo -a -d my_db -s /my_dump/dir\n" " pg_dumplo -a -d my_db -s /my_dump/dir\n"
"Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n" "Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n"
"Example (show): pg_dumplo -w -d my_db\n\n" "Example (show): pg_dumplo -w -d my_db\n\n"
"Note: * option '-l' must be last option!\n" "Note: * option '-l' must be last option!\n"
" * option '-i' without option '-r' make new large obj in DB\n" " * option '-i' without option '-r' make new large obj in DB\n"
" not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n" " not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n"
" * if is not set option -s, the pg_dumplo use $PWD\n" " * if is not set option -s, the pg_dumplo use $PWD\n"
); /* puts()*/ ); /* puts() */
} }

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -17,12 +17,12 @@
/* ---------- /* ----------
* Define * Define
* ---------- * ----------
*/ */
#define QUERY_BUFSIZ (8*1024) #define QUERY_BUFSIZ (8*1024)
#define DIR_UMASK 0755 #define DIR_UMASK 0755
#define FILE_UMASK 0644 #define FILE_UMASK 0644
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
#define RE_OK 0 #define RE_OK 0
#define RE_ERROR 1 #define RE_ERROR 1
@ -36,44 +36,47 @@
* LO struct * LO struct
* ---------- * ----------
*/ */
typedef struct { typedef struct
char *lo_table, {
*lo_attr; char *lo_table,
Oid lo_oid; *lo_attr;
} LOlist; Oid lo_oid;
} LOlist;
typedef struct { typedef struct
int action; {
LOlist *lolist; int action;
char **argv, LOlist *lolist;
*user, char **argv,
*db, *user,
*host, *db,
*space; *host,
FILE *index; *space;
int counter, FILE *index;
argc, int counter,
lolist_start, argc,
remove, lolist_start,
quiet; remove,
PGresult *res; quiet;
PGconn *conn; PGresult *res;
} LODumpMaster; PGconn *conn;
} LODumpMaster;
typedef enum { typedef enum
{
ACTION_NONE, ACTION_NONE,
ACTION_SHOW, ACTION_SHOW,
ACTION_EXPORT_ATTR, ACTION_EXPORT_ATTR,
ACTION_EXPORT_ALL, ACTION_EXPORT_ALL,
ACTION_IMPORT ACTION_IMPORT
} PGLODUMP_ACTIONS; } PGLODUMP_ACTIONS;
extern char *progname; extern char *progname;
extern void notice (LODumpMaster *pgLO, int set); extern void notice(LODumpMaster * pgLO, int set);
extern void index_file (LODumpMaster *pgLO); extern void index_file(LODumpMaster * pgLO);
extern void load_lolist (LODumpMaster *pgLO); extern void load_lolist(LODumpMaster * pgLO);
extern void pglo_export (LODumpMaster *pgLO); extern void pglo_export(LODumpMaster * pgLO);
extern void pglo_import (LODumpMaster *pgLO); extern void pglo_import(LODumpMaster * pgLO);
#endif /* PG_DUMPLO_H */ #endif /* PG_DUMPLO_H */

View File

@ -1,20 +1,20 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/utils.c,v 1.3 2001/01/24 19:42:45 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/utils.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -22,65 +22,76 @@
#include "pg_dumplo.h" #include "pg_dumplo.h"
extern int errno; extern int errno;
static void Dummy_NoticeProcessor(void *arg, const char *message);
static void Default_NoticeProcessor(void *arg, const char *message);
static void Dummy_NoticeProcessor(void * arg, const char * message);
static void Default_NoticeProcessor(void * arg, const char * message);
void void
index_file(LODumpMaster *pgLO) index_file(LODumpMaster * pgLO)
{ {
char path[BUFSIZ]; char path[BUFSIZ];
if (pgLO->action == ACTION_SHOW) if (pgLO->action == ACTION_SHOW)
return; return;
sprintf(path, "%s/%s", pgLO->space, pgLO->db);
if (pgLO->action == ACTION_EXPORT_ATTR ||
pgLO->action == ACTION_EXPORT_ALL) {
if (mkdir(path, DIR_UMASK) == -1) {
if (errno != EEXIST) {
perror(path);
exit(RE_ERROR);
}
}
sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "w")) == NULL) { sprintf(path, "%s/%s", pgLO->space, pgLO->db);
if (pgLO->action == ACTION_EXPORT_ATTR ||
pgLO->action == ACTION_EXPORT_ALL)
{
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "w")) == NULL)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
} else if (pgLO->action != ACTION_NONE ) {
sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "r")) == NULL) { }
else if (pgLO->action != ACTION_NONE)
{
sprintf(path, "%s/lo_dump.index", path);
if ((pgLO->index = fopen(path, "r")) == NULL)
{
perror(path); perror(path);
exit(RE_ERROR); exit(RE_ERROR);
} }
} }
} }
static static
void Dummy_NoticeProcessor(void * arg, const char * message) void
Dummy_NoticeProcessor(void *arg, const char *message)
{ {
; ;
} }
static static
void Default_NoticeProcessor(void * arg, const char * message) void
Default_NoticeProcessor(void *arg, const char *message)
{ {
fprintf(stderr, "%s", message); fprintf(stderr, "%s", message);
} }
void void
notice(LODumpMaster *pgLO, int set) notice(LODumpMaster * pgLO, int set)
{ {
if (set)PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL); if (set)
else PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL); PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL);
else
PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL);
} }

View File

@ -2,10 +2,10 @@
* *
* Copyright 2001 by Nathan Myers <ncm@nospam.cantrip.org> * Copyright 2001 by Nathan Myers <ncm@nospam.cantrip.org>
* This software is distributed free of charge with no warranty of any kind. * This software is distributed free of charge with no warranty of any kind.
* You have permission to make copies for any purpose, provided that (1) * You have permission to make copies for any purpose, provided that (1)
* this copyright notice is retained unchanged, and (2) you agree to * this copyright notice is retained unchanged, and (2) you agree to
* absolve the author of all responsibility for all consequences arising * absolve the author of all responsibility for all consequences arising
* from any use. * from any use.
*/ */
#include <stdio.h> #include <stdio.h>
@ -13,73 +13,94 @@
#include <syslog.h> #include <syslog.h>
#include <string.h> #include <string.h>
struct { struct
const char *tag; {
int size; const char *tag;
int priority; int size;
} tags[] = { int priority;
{ "", 0, LOG_NOTICE }, } tags[] =
{ "emerg:", sizeof("emerg"), LOG_EMERG },
{ "alert:", sizeof("alert"), LOG_ALERT }, {
{ "crit:", sizeof("crit"), LOG_CRIT }, {
{ "err:", sizeof("err"), LOG_ERR }, "", 0, LOG_NOTICE
{ "error:", sizeof("error"), LOG_ERR }, },
{ "warning:", sizeof("warning"), LOG_WARNING }, {
{ "notice:", sizeof("notice"), LOG_NOTICE }, "emerg:", sizeof("emerg"), LOG_EMERG
{ "info:", sizeof("info"), LOG_INFO }, },
{ "debug:", sizeof("debug"), LOG_DEBUG } {
"alert:", sizeof("alert"), LOG_ALERT
},
{
"crit:", sizeof("crit"), LOG_CRIT
},
{
"err:", sizeof("err"), LOG_ERR
},
{
"error:", sizeof("error"), LOG_ERR
},
{
"warning:", sizeof("warning"), LOG_WARNING
},
{
"notice:", sizeof("notice"), LOG_NOTICE
},
{
"info:", sizeof("info"), LOG_INFO
},
{
"debug:", sizeof("debug"), LOG_DEBUG
}
}; };
int main() int
main()
{ {
char buf[301]; char buf[301];
int c; int c;
char *pos = buf; char *pos = buf;
const char *colon = 0; const char *colon = 0;
#ifndef DEBUG #ifndef DEBUG
openlog("postgresql", LOG_CONS, LOG_LOCAL1); openlog("postgresql", LOG_CONS, LOG_LOCAL1);
#endif #endif
while ( (c = getchar()) != EOF) { while ((c = getchar()) != EOF)
if (c == '\r') { {
continue; if (c == '\r')
} continue;
if (c == '\n') { if (c == '\n')
int level = sizeof(tags)/sizeof(*tags); {
char *bol; int level = sizeof(tags) / sizeof(*tags);
char *bol;
if (colon == 0 || (size_t)(colon - buf) > sizeof("warning")) { if (colon == 0 || (size_t) (colon - buf) > sizeof("warning"))
level = 1; level = 1;
} *pos = 0;
*pos = 0; while (--level)
while (--level) { {
if (pos - buf >= tags[level].size if (pos - buf >= tags[level].size
&& strncmp(buf, tags[level].tag, tags[level].size) == 0) { && strncmp(buf, tags[level].tag, tags[level].size) == 0)
break; break;
} }
} bol = buf + tags[level].size;
bol = buf + tags[level].size; if (bol > buf && *bol == ' ')
if (bol > buf && *bol == ' ') { ++bol;
++bol; if (pos - bol > 0)
} {
if (pos - bol > 0) {
#ifndef DEBUG #ifndef DEBUG
syslog(tags[level].priority, "%s", bol); syslog(tags[level].priority, "%s", bol);
#else #else
printf("%d/%s\n", tags[level].priority, bol); printf("%d/%s\n", tags[level].priority, bol);
#endif #endif
} }
pos = buf; pos = buf;
colon = (char const *)0; colon = (char const *) 0;
continue; continue;
} }
if (c == ':' && !colon) { if (c == ':' && !colon)
colon = pos; colon = pos;
} if ((size_t) (pos - buf) < sizeof(buf) - 1)
if ((size_t)(pos - buf) < sizeof(buf)-1) { *pos++ = c;
*pos++ = c; }
} return 0;
}
return 0;
} }

View File

@ -5,15 +5,15 @@
* Can also rebuild pg_control if needed. * Can also rebuild pg_control if needed.
* *
* The theory of operation is fairly simple: * The theory of operation is fairly simple:
* 1. Read the existing pg_control (which will include the last * 1. Read the existing pg_control (which will include the last
* checkpoint record). If it is an old format then update to * checkpoint record). If it is an old format then update to
* current format. * current format.
* 2. If pg_control is corrupt, attempt to intuit reasonable values, * 2. If pg_control is corrupt, attempt to intuit reasonable values,
* by scanning the old xlog if necessary. * by scanning the old xlog if necessary.
* 3. Modify pg_control to reflect a "shutdown" state with a checkpoint * 3. Modify pg_control to reflect a "shutdown" state with a checkpoint
* record at the start of xlog. * record at the start of xlog.
* 4. Flush the existing xlog files and write a new segment with * 4. Flush the existing xlog files and write a new segment with
* just a checkpoint record in it. The new segment is positioned * just a checkpoint record in it. The new segment is positioned
* just past the end of the old xlog, so that existing LSNs in * just past the end of the old xlog, so that existing LSNs in
* data pages will appear to be "in the past". * data pages will appear to be "in the past".
* This is all pretty straightforward except for the intuition part of * This is all pretty straightforward except for the intuition part of
@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.2 2001/03/16 05:08:39 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -63,7 +63,7 @@
* Compute ID and segment from an XLogRecPtr. * Compute ID and segment from an XLogRecPtr.
* *
* For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg, * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
* a boundary byte is taken to be in the previous segment. This is suitable * a boundary byte is taken to be in the previous segment. This is suitable
* for deciding which segment to write given a pointer to a record end, * for deciding which segment to write given a pointer to a record end,
* for example. * for example.
*/ */
@ -109,8 +109,9 @@ static char *DataDir; /* locations of important stuff */
static char XLogDir[MAXPGPATH]; static char XLogDir[MAXPGPATH];
static char ControlFilePath[MAXPGPATH]; static char ControlFilePath[MAXPGPATH];
static ControlFileData ControlFile; /* pg_control values */ static ControlFileData ControlFile; /* pg_control values */
static uint32 newXlogId, newXlogSeg; /* ID/Segment of new XLOG segment */ static uint32 newXlogId,
newXlogSeg; /* ID/Segment of new XLOG segment */
static bool guessed = false; /* T if we had to guess at any values */ static bool guessed = false; /* T if we had to guess at any values */
@ -139,17 +140,18 @@ XLogFileOpen(uint32 log, uint32 seg)
static bool static bool
ReadControlFile(void) ReadControlFile(void)
{ {
int fd; int fd;
int len; int len;
char *buffer; char *buffer;
crc64 crc; crc64 crc;
if ((fd = open(ControlFilePath, O_RDONLY)) < 0) if ((fd = open(ControlFilePath, O_RDONLY)) < 0)
{ {
/* /*
* If pg_control is not there at all, or we can't read it, * If pg_control is not there at all, or we can't read it, the
* the odds are we've been handed a bad DataDir path, so give up. * odds are we've been handed a bad DataDir path, so give up. User
* User can do "touch pg_control" to force us to proceed. * can do "touch pg_control" to force us to proceed.
*/ */
perror("Failed to open $PGDATA/global/pg_control for reading"); perror("Failed to open $PGDATA/global/pg_control for reading");
if (errno == ENOENT) if (errno == ENOENT)
@ -175,7 +177,7 @@ ReadControlFile(void)
{ {
/* Seems to be current version --- check the CRC. */ /* Seems to be current version --- check the CRC. */
INIT_CRC64(crc); INIT_CRC64(crc);
COMP_CRC64(crc, COMP_CRC64(crc,
buffer + sizeof(crc64), buffer + sizeof(crc64),
sizeof(ControlFileData) - sizeof(crc64)); sizeof(ControlFileData) - sizeof(crc64));
FIN_CRC64(crc); FIN_CRC64(crc);
@ -193,6 +195,7 @@ ReadControlFile(void)
guessed = true; guessed = true;
return true; return true;
} }
/* /*
* Maybe it's a 7.1beta pg_control. * Maybe it's a 7.1beta pg_control.
*/ */
@ -217,75 +220,75 @@ ReadControlFile(void)
typedef struct crc64V0 typedef struct crc64V0
{ {
uint32 crc1; uint32 crc1;
uint32 crc2; uint32 crc2;
} crc64V0; } crc64V0;
static uint32 crc_tableV0[] = { static uint32 crc_tableV0[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
}; };
#define INIT_CRC64V0(crc) ((crc).crc1 = 0xffffffff, (crc).crc2 = 0xffffffff) #define INIT_CRC64V0(crc) ((crc).crc1 = 0xffffffff, (crc).crc2 = 0xffffffff)
#define FIN_CRC64V0(crc) ((crc).crc1 ^= 0xffffffff, (crc).crc2 ^= 0xffffffff) #define FIN_CRC64V0(crc) ((crc).crc1 ^= 0xffffffff, (crc).crc2 ^= 0xffffffff)
#define COMP_CRC64V0(crc, data, len) \ #define COMP_CRC64V0(crc, data, len) \
{\ {\
uint32 __c1 = (crc).crc1;\ uint32 __c1 = (crc).crc1;\
uint32 __c2 = (crc).crc2;\ uint32 __c2 = (crc).crc2;\
char *__data = (char *) (data);\ char *__data = (char *) (data);\
uint32 __len = (len);\ uint32 __len = (len);\
\ \
while (__len >= 2)\ while (__len >= 2)\
{\ {\
__c1 = crc_tableV0[(__c1 ^ *__data++) & 0xff] ^ (__c1 >> 8);\ __c1 = crc_tableV0[(__c1 ^ *__data++) & 0xff] ^ (__c1 >> 8);\
__c2 = crc_tableV0[(__c2 ^ *__data++) & 0xff] ^ (__c2 >> 8);\ __c2 = crc_tableV0[(__c2 ^ *__data++) & 0xff] ^ (__c2 >> 8);\
__len -= 2;\ __len -= 2;\
}\ }\
if (__len > 0)\ if (__len > 0)\
__c1 = crc_tableV0[(__c1 ^ *__data++) & 0xff] ^ (__c1 >> 8);\ __c1 = crc_tableV0[(__c1 ^ *__data++) & 0xff] ^ (__c1 >> 8);\
(crc).crc1 = __c1;\ (crc).crc1 = __c1;\
(crc).crc2 = __c2;\ (crc).crc2 = __c2;\
} }
#define EQ_CRC64V0(c1,c2) ((c1).crc1 == (c2).crc1 && (c1).crc2 == (c2).crc2) #define EQ_CRC64V0(c1,c2) ((c1).crc1 == (c2).crc1 && (c1).crc2 == (c2).crc2)
@ -295,51 +298,51 @@ static uint32 crc_tableV0[] = {
typedef struct ControlFileDataV0 typedef struct ControlFileDataV0
{ {
crc64V0 crc; crc64V0 crc;
uint32 logId; /* current log file id */ uint32 logId; /* current log file id */
uint32 logSeg; /* current log file segment (1-based) */ uint32 logSeg; /* current log file segment (1-based) */
XLogRecPtr checkPoint; /* last check point record ptr */ XLogRecPtr checkPoint; /* last check point record ptr */
time_t time; /* time stamp of last modification */ time_t time; /* time stamp of last modification */
DBState state; /* see enum above */ DBState state; /* see enum above */
uint32 blcksz; /* block size for this DB */ uint32 blcksz; /* block size for this DB */
uint32 relseg_size; /* blocks per segment of large relation */ uint32 relseg_size; /* blocks per segment of large relation */
uint32 catalog_version_no; /* internal version number */ uint32 catalog_version_no; /* internal version number */
char lc_collate[LOCALE_NAME_BUFLEN_V0]; char lc_collate[LOCALE_NAME_BUFLEN_V0];
char lc_ctype[LOCALE_NAME_BUFLEN_V0]; char lc_ctype[LOCALE_NAME_BUFLEN_V0];
char archdir[MAXPGPATH]; /* where to move offline log files */ char archdir[MAXPGPATH]; /* where to move offline log files */
} ControlFileDataV0; } ControlFileDataV0;
typedef struct CheckPointV0 typedef struct CheckPointV0
{ {
XLogRecPtr redo; /* next RecPtr available when we */ XLogRecPtr redo; /* next RecPtr available when we */
/* began to create CheckPoint */ /* began to create CheckPoint */
/* (i.e. REDO start point) */ /* (i.e. REDO start point) */
XLogRecPtr undo; /* first record of oldest in-progress */ XLogRecPtr undo; /* first record of oldest in-progress */
/* transaction when we started */ /* transaction when we started */
/* (i.e. UNDO end point) */ /* (i.e. UNDO end point) */
StartUpID ThisStartUpID; StartUpID ThisStartUpID;
TransactionId nextXid; TransactionId nextXid;
Oid nextOid; Oid nextOid;
bool Shutdown; bool Shutdown;
} CheckPointV0; } CheckPointV0;
typedef struct XLogRecordV0 typedef struct XLogRecordV0
{ {
crc64V0 xl_crc; crc64V0 xl_crc;
XLogRecPtr xl_prev; /* ptr to previous record in log */ XLogRecPtr xl_prev; /* ptr to previous record in log */
XLogRecPtr xl_xact_prev; /* ptr to previous record of this xact */ XLogRecPtr xl_xact_prev; /* ptr to previous record of this xact */
TransactionId xl_xid; /* xact id */ TransactionId xl_xid; /* xact id */
uint16 xl_len; /* total len of record *data* */ uint16 xl_len; /* total len of record *data* */
uint8 xl_info; uint8 xl_info;
RmgrId xl_rmid; /* resource manager inserted this record */ RmgrId xl_rmid; /* resource manager inserted this record */
} XLogRecordV0; } XLogRecordV0;
#define SizeOfXLogRecordV0 DOUBLEALIGN(sizeof(XLogRecordV0)) #define SizeOfXLogRecordV0 DOUBLEALIGN(sizeof(XLogRecordV0))
typedef struct XLogContRecordV0 typedef struct XLogContRecordV0
{ {
uint16 xl_len; /* len of data left */ uint16 xl_len; /* len of data left */
} XLogContRecordV0; } XLogContRecordV0;
#define SizeOfXLogContRecordV0 DOUBLEALIGN(sizeof(XLogContRecordV0)) #define SizeOfXLogContRecordV0 DOUBLEALIGN(sizeof(XLogContRecordV0))
@ -347,16 +350,16 @@ typedef struct XLogContRecordV0
typedef struct XLogPageHeaderDataV0 typedef struct XLogPageHeaderDataV0
{ {
uint32 xlp_magic; uint32 xlp_magic;
uint16 xlp_info; uint16 xlp_info;
} XLogPageHeaderDataV0; } XLogPageHeaderDataV0;
#define SizeOfXLogPHDV0 DOUBLEALIGN(sizeof(XLogPageHeaderDataV0)) #define SizeOfXLogPHDV0 DOUBLEALIGN(sizeof(XLogPageHeaderDataV0))
typedef XLogPageHeaderDataV0 *XLogPageHeaderV0; typedef XLogPageHeaderDataV0 *XLogPageHeaderV0;
static bool RecordIsValidV0(XLogRecordV0 *record); static bool RecordIsValidV0(XLogRecordV0 * record);
static XLogRecordV0 *ReadRecordV0(XLogRecPtr *RecPtr, char *buffer); static XLogRecordV0 *ReadRecordV0(XLogRecPtr *RecPtr, char *buffer);
static bool ValidXLOGHeaderV0(XLogPageHeaderV0 hdr); static bool ValidXLOGHeaderV0(XLogPageHeaderV0 hdr);
@ -376,7 +379,7 @@ CheckControlVersion0(char *buffer, int len)
return false; return false;
/* Check CRC the version-0 way. */ /* Check CRC the version-0 way. */
INIT_CRC64V0(crc); INIT_CRC64V0(crc);
COMP_CRC64V0(crc, COMP_CRC64V0(crc,
buffer + sizeof(crc64V0), buffer + sizeof(crc64V0),
sizeof(ControlFileDataV0) - sizeof(crc64V0)); sizeof(ControlFileDataV0) - sizeof(crc64V0));
FIN_CRC64V0(crc); FIN_CRC64V0(crc);
@ -409,12 +412,13 @@ CheckControlVersion0(char *buffer, int len)
(char *) malloc(_INTL_MAXLOGRECSZ)); (char *) malloc(_INTL_MAXLOGRECSZ));
if (record == NULL) if (record == NULL)
{ {
/* /*
* We have to guess at the checkpoint contents. * We have to guess at the checkpoint contents.
*/ */
guessed = true; guessed = true;
ControlFile.checkPointCopy.ThisStartUpID = 0; ControlFile.checkPointCopy.ThisStartUpID = 0;
ControlFile.checkPointCopy.nextXid = (TransactionId) 514; /* XXX */ ControlFile.checkPointCopy.nextXid = (TransactionId) 514; /* XXX */
ControlFile.checkPointCopy.nextOid = BootstrapObjectIdData; ControlFile.checkPointCopy.nextOid = BootstrapObjectIdData;
return true; return true;
} }
@ -435,26 +439,26 @@ CheckControlVersion0(char *buffer, int len)
* We assume all of the record has been read into memory at *record. * We assume all of the record has been read into memory at *record.
*/ */
static bool static bool
RecordIsValidV0(XLogRecordV0 *record) RecordIsValidV0(XLogRecordV0 * record)
{ {
crc64V0 crc; crc64V0 crc;
uint32 len = record->xl_len; uint32 len = record->xl_len;
/* /*
* NB: this code is not right for V0 records containing backup blocks, * NB: this code is not right for V0 records containing backup blocks,
* but for now it's only going to be applied to checkpoint records, * but for now it's only going to be applied to checkpoint records, so
* so I'm not going to worry about it... * I'm not going to worry about it...
*/ */
INIT_CRC64V0(crc); INIT_CRC64V0(crc);
COMP_CRC64V0(crc, XLogRecGetData(record), len); COMP_CRC64V0(crc, XLogRecGetData(record), len);
COMP_CRC64V0(crc, (char*) record + sizeof(crc64V0), COMP_CRC64V0(crc, (char *) record + sizeof(crc64V0),
SizeOfXLogRecordV0 - sizeof(crc64V0)); SizeOfXLogRecordV0 - sizeof(crc64V0));
FIN_CRC64V0(crc); FIN_CRC64V0(crc);
if (!EQ_CRC64V0(record->xl_crc, crc)) if (!EQ_CRC64V0(record->xl_crc, crc))
return false; return false;
return(true); return (true);
} }
/* /*
@ -489,7 +493,7 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
readFile = XLogFileOpen(readId, readSeg); readFile = XLogFileOpen(readId, readSeg);
if (readFile < 0) if (readFile < 0)
goto next_record_is_invalid; goto next_record_is_invalid;
readOff = (uint32) (-1); /* force read to occur below */ readOff = (uint32) (-1);/* force read to occur below */
} }
targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / BLCKSZ) * BLCKSZ; targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / BLCKSZ) * BLCKSZ;
@ -510,10 +514,13 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
if (record->xl_len == 0) if (record->xl_len == 0)
goto next_record_is_invalid; goto next_record_is_invalid;
/* /*
* Compute total length of record including any appended backup blocks. * Compute total length of record including any appended backup
* blocks.
*/ */
total_len = SizeOfXLogRecordV0 + record->xl_len; total_len = SizeOfXLogRecordV0 + record->xl_len;
/* /*
* Make sure it will fit in buffer (currently, it is mechanically * Make sure it will fit in buffer (currently, it is mechanically
* impossible for this test to fail, but it seems like a good idea * impossible for this test to fail, but it seems like a good idea
@ -526,7 +533,7 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
{ {
/* Need to reassemble record */ /* Need to reassemble record */
XLogContRecordV0 *contrecord; XLogContRecordV0 *contrecord;
uint32 gotlen = len; uint32 gotlen = len;
memcpy(buffer, record, len); memcpy(buffer, record, len);
record = (XLogRecordV0 *) buffer; record = (XLogRecordV0 *) buffer;
@ -551,13 +558,13 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
if (!(((XLogPageHeaderV0) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD)) if (!(((XLogPageHeaderV0) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD))
goto next_record_is_invalid; goto next_record_is_invalid;
contrecord = (XLogContRecordV0 *) ((char *) readBuf + SizeOfXLogPHDV0); contrecord = (XLogContRecordV0 *) ((char *) readBuf + SizeOfXLogPHDV0);
if (contrecord->xl_len == 0 || if (contrecord->xl_len == 0 ||
total_len != (contrecord->xl_len + gotlen)) total_len != (contrecord->xl_len + gotlen))
goto next_record_is_invalid; goto next_record_is_invalid;
len = BLCKSZ - SizeOfXLogPHDV0 - SizeOfXLogContRecordV0; len = BLCKSZ - SizeOfXLogPHDV0 - SizeOfXLogContRecordV0;
if (contrecord->xl_len > len) if (contrecord->xl_len > len)
{ {
memcpy(buffer, (char *)contrecord + SizeOfXLogContRecordV0, len); memcpy(buffer, (char *) contrecord + SizeOfXLogContRecordV0, len);
gotlen += len; gotlen += len;
buffer += len; buffer += len;
continue; continue;
@ -587,7 +594,7 @@ next_record_is_invalid:;
* Check whether the xlog header of a page just read in looks valid. * Check whether the xlog header of a page just read in looks valid.
* *
* This is just a convenience subroutine to avoid duplicated code in * This is just a convenience subroutine to avoid duplicated code in
* ReadRecord. It's not intended for use from anywhere else. * ReadRecord. It's not intended for use from anywhere else.
*/ */
static bool static bool
ValidXLOGHeaderV0(XLogPageHeaderV0 hdr) ValidXLOGHeaderV0(XLogPageHeaderV0 hdr)
@ -610,6 +617,7 @@ GuessControlValues(void)
{ {
#ifdef USE_LOCALE #ifdef USE_LOCALE
char *localeptr; char *localeptr;
#endif #endif
/* /*
@ -625,7 +633,7 @@ GuessControlValues(void)
ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogPHD; ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogPHD;
ControlFile.checkPointCopy.undo = ControlFile.checkPointCopy.redo; ControlFile.checkPointCopy.undo = ControlFile.checkPointCopy.redo;
ControlFile.checkPointCopy.ThisStartUpID = 0; ControlFile.checkPointCopy.ThisStartUpID = 0;
ControlFile.checkPointCopy.nextXid = (TransactionId) 514; /* XXX */ ControlFile.checkPointCopy.nextXid = (TransactionId) 514; /* XXX */
ControlFile.checkPointCopy.nextOid = BootstrapObjectIdData; ControlFile.checkPointCopy.nextOid = BootstrapObjectIdData;
ControlFile.checkPointCopy.time = time(NULL); ControlFile.checkPointCopy.time = time(NULL);
@ -677,7 +685,7 @@ PrintControlValues(void)
"pg_control version number: %u\n" "pg_control version number: %u\n"
"Catalog version number: %u\n" "Catalog version number: %u\n"
"Current log file id: %u\n" "Current log file id: %u\n"
"Next log file segment: %u\n" "Next log file segment: %u\n"
"Latest checkpoint's StartUpID: %u\n" "Latest checkpoint's StartUpID: %u\n"
"Latest checkpoint's NextXID: %u\n" "Latest checkpoint's NextXID: %u\n"
"Latest checkpoint's NextOID: %u\n" "Latest checkpoint's NextOID: %u\n"
@ -707,11 +715,11 @@ static void
RewriteControlFile(void) RewriteControlFile(void)
{ {
int fd; int fd;
char buffer[BLCKSZ]; /* need not be aligned */ char buffer[BLCKSZ]; /* need not be aligned */
/* /*
* Adjust fields as needed to force an empty XLOG starting at the * Adjust fields as needed to force an empty XLOG starting at the next
* next available segment. * available segment.
*/ */
newXlogId = ControlFile.logId; newXlogId = ControlFile.logId;
newXlogSeg = ControlFile.logSeg; newXlogSeg = ControlFile.logSeg;
@ -734,17 +742,17 @@ RewriteControlFile(void)
/* Contents are protected with a CRC */ /* Contents are protected with a CRC */
INIT_CRC64(ControlFile.crc); INIT_CRC64(ControlFile.crc);
COMP_CRC64(ControlFile.crc, COMP_CRC64(ControlFile.crc,
(char*) &ControlFile + sizeof(crc64), (char *) &ControlFile + sizeof(crc64),
sizeof(ControlFileData) - sizeof(crc64)); sizeof(ControlFileData) - sizeof(crc64));
FIN_CRC64(ControlFile.crc); FIN_CRC64(ControlFile.crc);
/* /*
* We write out BLCKSZ bytes into pg_control, zero-padding the * We write out BLCKSZ bytes into pg_control, zero-padding the excess
* excess over sizeof(ControlFileData). This reduces the odds * over sizeof(ControlFileData). This reduces the odds of
* of premature-EOF errors when reading pg_control. We'll still * premature-EOF errors when reading pg_control. We'll still fail
* fail when we check the contents of the file, but hopefully with * when we check the contents of the file, but hopefully with a more
* a more specific error than "couldn't read pg_control". * specific error than "couldn't read pg_control".
*/ */
if (sizeof(ControlFileData) > BLCKSZ) if (sizeof(ControlFileData) > BLCKSZ)
{ {
@ -786,9 +794,9 @@ RewriteControlFile(void)
static void static void
KillExistingXLOG(void) KillExistingXLOG(void)
{ {
DIR *xldir; DIR *xldir;
struct dirent *xlde; struct dirent *xlde;
char path[MAXPGPATH]; char path[MAXPGPATH];
xldir = opendir(XLogDir); xldir = opendir(XLogDir);
if (xldir == NULL) if (xldir == NULL)
@ -803,7 +811,7 @@ KillExistingXLOG(void)
if (strlen(xlde->d_name) == 16 && if (strlen(xlde->d_name) == 16 &&
strspn(xlde->d_name, "0123456789ABCDEF") == 16) strspn(xlde->d_name, "0123456789ABCDEF") == 16)
{ {
sprintf(path, "%s%c%s", XLogDir, SEP_CHAR, xlde->d_name); sprintf(path, "%s%c%s", XLogDir, SEP_CHAR, xlde->d_name);
if (unlink(path) < 0) if (unlink(path) < 0)
{ {
perror(path); perror(path);
@ -858,7 +866,7 @@ WriteEmptyXLOG(void)
INIT_CRC64(crc); INIT_CRC64(crc);
COMP_CRC64(crc, &ControlFile.checkPointCopy, sizeof(CheckPoint)); COMP_CRC64(crc, &ControlFile.checkPointCopy, sizeof(CheckPoint));
COMP_CRC64(crc, (char*) record + sizeof(crc64), COMP_CRC64(crc, (char *) record + sizeof(crc64),
SizeOfXLogRecord - sizeof(crc64)); SizeOfXLogRecord - sizeof(crc64));
FIN_CRC64(crc); FIN_CRC64(crc);
record->xl_crc = crc; record->xl_crc = crc;
@ -914,13 +922,13 @@ usage(void)
int int
main(int argc, char ** argv) main(int argc, char **argv)
{ {
int argn; int argn;
bool force = false; bool force = false;
bool noupdate = false; bool noupdate = false;
int fd; int fd;
char path[MAXPGPATH]; char path[MAXPGPATH];
for (argn = 1; argn < argc; argn++) for (argn = 1; argn < argc; argn++)
{ {
@ -934,7 +942,7 @@ main(int argc, char ** argv)
usage(); usage();
} }
if (argn != argc-1) /* one required non-switch argument */ if (argn != argc - 1) /* one required non-switch argument */
usage(); usage();
DataDir = argv[argn++]; DataDir = argv[argn++];
@ -946,7 +954,8 @@ main(int argc, char ** argv)
/* /*
* Check for a postmaster lock file --- if there is one, refuse to * Check for a postmaster lock file --- if there is one, refuse to
* proceed, on grounds we might be interfering with a live installation. * proceed, on grounds we might be interfering with a live
* installation.
*/ */
snprintf(path, MAXPGPATH, "%s%cpostmaster.pid", DataDir, SEP_CHAR); snprintf(path, MAXPGPATH, "%s%cpostmaster.pid", DataDir, SEP_CHAR);
@ -973,8 +982,8 @@ main(int argc, char ** argv)
GuessControlValues(); GuessControlValues();
/* /*
* If we had to guess anything, and -f was not given, just print * If we had to guess anything, and -f was not given, just print the
* the guessed values and exit. Also print if -n is given. * guessed values and exit. Also print if -n is given.
*/ */
if ((guessed && !force) || noupdate) if ((guessed && !force) || noupdate)
{ {

View File

@ -1,7 +1,7 @@
/* /*
* encode.c * encode.c
* Various data encoding/decoding things. * Various data encoding/decoding things.
* *
* Copyright (c) 2001 Marko Kreen * Copyright (c) 2001 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: encode.c,v 1.3 2001/02/10 02:31:25 tgl Exp $ * $Id: encode.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -43,9 +43,9 @@
#endif #endif
static pg_coding * static pg_coding *
find_coding(pg_coding *hbuf, text *name, int silent); find_coding(pg_coding * hbuf, text *name, int silent);
static pg_coding * static pg_coding *
pg_find_coding(pg_coding *res, char *name); pg_find_coding(pg_coding * res, char *name);
/* SQL function: encode(bytea, text) returns text */ /* SQL function: encode(bytea, text) returns text */
@ -54,34 +54,37 @@ PG_FUNCTION_INFO_V1(encode);
Datum Datum
encode(PG_FUNCTION_ARGS) encode(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, rlen, rlen0; uint len,
pg_coding *c, cbuf; rlen,
text *res; rlen0;
pg_coding *c,
cbuf;
text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
PG_RETURN_NULL(); PG_RETURN_NULL();
name = PG_GETARG_TEXT_P(1); name = PG_GETARG_TEXT_P(1);
c = find_coding(&cbuf, name, 0); /* will give error if fails */ c = find_coding(&cbuf, name, 0); /* will give error if fails */
arg = PG_GETARG_TEXT_P(0); arg = PG_GETARG_TEXT_P(0);
len = VARSIZE(arg) - VARHDRSZ; len = VARSIZE(arg) - VARHDRSZ;
rlen0 = c->encode_len(len); rlen0 = c->encode_len(len);
res = (text *)palloc(rlen0 + VARHDRSZ); res = (text *) palloc(rlen0 + VARHDRSZ);
rlen = c->encode(VARDATA(arg), len, VARDATA(res)); rlen = c->encode(VARDATA(arg), len, VARDATA(res));
VARATT_SIZEP(res) = rlen + VARHDRSZ; VARATT_SIZEP(res) = rlen + VARHDRSZ;
if (rlen > rlen0) if (rlen > rlen0)
elog(FATAL, "pg_encode: overflow, encode estimate too small"); elog(FATAL, "pg_encode: overflow, encode estimate too small");
PG_FREE_IF_COPY(arg, 0); PG_FREE_IF_COPY(arg, 0);
PG_FREE_IF_COPY(name, 1); PG_FREE_IF_COPY(name, 1);
PG_RETURN_TEXT_P(res); PG_RETURN_TEXT_P(res);
} }
@ -91,54 +94,58 @@ PG_FUNCTION_INFO_V1(decode);
Datum Datum
decode(PG_FUNCTION_ARGS) decode(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, rlen, rlen0; uint len,
pg_coding *c, cbuf; rlen,
text *res; rlen0;
pg_coding *c,
cbuf;
text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
PG_RETURN_NULL(); PG_RETURN_NULL();
name = PG_GETARG_TEXT_P(1); name = PG_GETARG_TEXT_P(1);
c = find_coding(&cbuf, name, 0); /* will give error if fails */ c = find_coding(&cbuf, name, 0); /* will give error if fails */
arg = PG_GETARG_TEXT_P(0); arg = PG_GETARG_TEXT_P(0);
len = VARSIZE(arg) - VARHDRSZ; len = VARSIZE(arg) - VARHDRSZ;
rlen0 = c->decode_len(len); rlen0 = c->decode_len(len);
res = (text *)palloc(rlen0 + VARHDRSZ); res = (text *) palloc(rlen0 + VARHDRSZ);
rlen = c->decode(VARDATA(arg), len, VARDATA(res)); rlen = c->decode(VARDATA(arg), len, VARDATA(res));
VARATT_SIZEP(res) = rlen + VARHDRSZ; VARATT_SIZEP(res) = rlen + VARHDRSZ;
if (rlen > rlen0) if (rlen > rlen0)
elog(FATAL, "pg_decode: overflow, decode estimate too small"); elog(FATAL, "pg_decode: overflow, decode estimate too small");
PG_FREE_IF_COPY(arg, 0); PG_FREE_IF_COPY(arg, 0);
PG_FREE_IF_COPY(name, 1); PG_FREE_IF_COPY(name, 1);
PG_RETURN_TEXT_P(res); PG_RETURN_TEXT_P(res);
} }
static pg_coding * static pg_coding *
find_coding(pg_coding *dst, text *name, int silent) find_coding(pg_coding * dst, text *name, int silent)
{ {
pg_coding *p; pg_coding *p;
char buf[NAMEDATALEN]; char buf[NAMEDATALEN];
uint len; uint len;
len = VARSIZE(name) - VARHDRSZ; len = VARSIZE(name) - VARHDRSZ;
if (len >= NAMEDATALEN) { if (len >= NAMEDATALEN)
{
if (silent) if (silent)
return NULL; return NULL;
elog(ERROR, "Encoding type does not exist (name too long)"); elog(ERROR, "Encoding type does not exist (name too long)");
} }
memcpy(buf, VARDATA(name), len); memcpy(buf, VARDATA(name), len);
buf[len] = 0; buf[len] = 0;
p = pg_find_coding(dst, buf); p = pg_find_coding(dst, buf);
if (p == NULL && !silent) if (p == NULL && !silent)
@ -151,21 +158,23 @@ static char *hextbl = "0123456789abcdef";
uint uint
hex_encode(uint8 *src, uint len, uint8 *dst) hex_encode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *end = src + len; uint8 *end = src + len;
while (src < end) {
while (src < end)
{
*dst++ = hextbl[(*src >> 4) & 0xF]; *dst++ = hextbl[(*src >> 4) & 0xF];
*dst++ = hextbl[*src & 0xF]; *dst++ = hextbl[*src & 0xF];
src++; src++;
} }
return len*2; return len * 2;
} }
/* probably should use lookup table */ /* probably should use lookup table */
static uint8 static uint8
get_hex(char c) get_hex(char c)
{ {
uint8 res = 0; uint8 res = 0;
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
res = c - '0'; res = c - '0';
else if (c >= 'a' && c <= 'f') else if (c >= 'a' && c <= 'f')
@ -174,19 +183,26 @@ get_hex(char c)
res = c - 'A' + 10; res = c - 'A' + 10;
else else
elog(ERROR, "Bad hex code: '%c'", c); elog(ERROR, "Bad hex code: '%c'", c);
return res; return res;
} }
uint uint
hex_decode(uint8 *src, uint len, uint8 *dst) hex_decode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *s, *srcend, v1, v2, *p = dst; uint8 *s,
*srcend,
v1,
v2,
*p = dst;
srcend = src + len; srcend = src + len;
s = src; p = dst; s = src;
while (s < srcend) { p = dst;
if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r') { while (s < srcend)
{
if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
{
s++; s++;
continue; continue;
} }
@ -196,30 +212,36 @@ hex_decode(uint8 *src, uint len, uint8 *dst)
v2 = get_hex(*s++); v2 = get_hex(*s++);
*p++ = v1 | v2; *p++ = v1 | v2;
} }
return p - dst; return p - dst;
} }
static unsigned char _base64[] = static unsigned char _base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint uint
b64_encode(uint8 *src, uint len, uint8 *dst) b64_encode(uint8 *src, uint len, uint8 *dst)
{ {
uint8 *s, *p, *end = src + len, *lend = dst + 76; uint8 *s,
int pos = 2; *p,
*end = src + len,
*lend = dst + 76;
int pos = 2;
unsigned long buf = 0; unsigned long buf = 0;
s = src; p = dst; s = src;
p = dst;
while (s < end) {
while (s < end)
{
buf |= *s << (pos << 3); buf |= *s << (pos << 3);
pos--; pos--;
s++; s++;
/* write it out */ /* write it out */
if (pos < 0) { if (pos < 0)
{
*p++ = _base64[(buf >> 18) & 0x3f]; *p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f]; *p++ = _base64[(buf >> 12) & 0x3f];
*p++ = _base64[(buf >> 6) & 0x3f]; *p++ = _base64[(buf >> 6) & 0x3f];
@ -228,12 +250,14 @@ b64_encode(uint8 *src, uint len, uint8 *dst)
pos = 2; pos = 2;
buf = 0; buf = 0;
} }
if (p >= lend) { if (p >= lend)
{
*p++ = '\n'; *p++ = '\n';
lend = p + 76; lend = p + 76;
} }
} }
if (pos != 2) { if (pos != 2)
{
*p++ = _base64[(buf >> 18) & 0x3f]; *p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f]; *p++ = _base64[(buf >> 12) & 0x3f];
*p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '='; *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
@ -247,14 +271,17 @@ b64_encode(uint8 *src, uint len, uint8 *dst)
uint uint
b64_decode(uint8 *src, uint len, uint8 *dst) b64_decode(uint8 *src, uint len, uint8 *dst)
{ {
char *srcend = src + len, *s = src; char *srcend = src + len,
uint8 *p = dst; *s = src;
char c; uint8 *p = dst;
uint b = 0; char c;
uint b = 0;
unsigned long buf = 0; unsigned long buf = 0;
int pos = 0, end = 0; int pos = 0,
end = 0;
while (s < srcend) {
while (s < srcend)
{
c = *s++; c = *s++;
if (c >= 'A' && c <= 'Z') if (c >= 'A' && c <= 'Z')
b = c - 'A'; b = c - 'A';
@ -266,16 +293,21 @@ b64_decode(uint8 *src, uint len, uint8 *dst)
b = 62; b = 62;
else if (c == '/') else if (c == '/')
b = 63; b = 63;
else if (c == '=') { else if (c == '=')
{
/* end sequence */ /* end sequence */
if (!end) { if (!end)
if (pos == 2) end = 1; {
else if (pos == 3) end = 2; if (pos == 2)
end = 1;
else if (pos == 3)
end = 2;
else else
elog(ERROR, "base64: unexpected '='"); elog(ERROR, "base64: unexpected '='");
} }
b = 0; b = 0;
} else if (c == ' ' || c == '\t' || c == '\n' || c == '\r') }
else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue; continue;
else else
elog(ERROR, "base64: Invalid symbol"); elog(ERROR, "base64: Invalid symbol");
@ -283,7 +315,8 @@ b64_decode(uint8 *src, uint len, uint8 *dst)
/* add it to buffer */ /* add it to buffer */
buf = (buf << 6) + b; buf = (buf << 6) + b;
pos++; pos++;
if (pos == 4) { if (pos == 4)
{
*p++ = (buf >> 16) & 255; *p++ = (buf >> 16) & 255;
if (end == 0 || end > 1) if (end == 0 || end > 1)
*p++ = (buf >> 8) & 255; *p++ = (buf >> 8) & 255;
@ -326,21 +359,22 @@ b64_dec_len(uint srclen)
} }
static pg_coding static pg_coding
encoding_list [] = { encoding_list[] = {
{ "hex", hex_enc_len, hex_dec_len, hex_encode, hex_decode}, {"hex", hex_enc_len, hex_dec_len, hex_encode, hex_decode},
{ "base64", b64_enc_len, b64_dec_len, b64_encode, b64_decode}, {"base64", b64_enc_len, b64_dec_len, b64_encode, b64_decode},
{ NULL, NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL, NULL}
}; };
static pg_coding * static pg_coding *
pg_find_coding(pg_coding *res, char *name) pg_find_coding(pg_coding * res, char *name)
{ {
pg_coding *p; pg_coding *p;
for (p = encoding_list; p->name; p++) {
for (p = encoding_list; p->name; p++)
{
if (!strcasecmp(p->name, name)) if (!strcasecmp(p->name, name))
return p; return p;
} }
return NULL; return NULL;
} }

View File

@ -1,7 +1,7 @@
/* /*
* pg_encode.h * pg_encode.h
* encode.c * encode.c
* *
* Copyright (c) 2001 Marko Kreen * Copyright (c) 2001 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,35 +26,35 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: encode.h,v 1.1 2001/01/24 03:46:16 momjian Exp $ * $Id: encode.h,v 1.2 2001/03/22 03:59:10 momjian Exp $
*/ */
#ifndef __PG_ENCODE_H #ifndef __PG_ENCODE_H
#define __PG_ENCODE_H #define __PG_ENCODE_H
/* exported functions */ /* exported functions */
Datum encode(PG_FUNCTION_ARGS); Datum encode(PG_FUNCTION_ARGS);
Datum decode(PG_FUNCTION_ARGS); Datum decode(PG_FUNCTION_ARGS);
typedef struct _pg_coding pg_coding; typedef struct _pg_coding pg_coding;
struct _pg_coding { struct _pg_coding
char *name; {
uint (*encode_len)(uint dlen); char *name;
uint (*decode_len)(uint dlen); uint (*encode_len) (uint dlen);
uint (*encode)(uint8 *data, uint dlen, uint8 *res); uint (*decode_len) (uint dlen);
uint (*decode)(uint8 *data, uint dlen, uint8 *res); uint (*encode) (uint8 *data, uint dlen, uint8 *res);
uint (*decode) (uint8 *data, uint dlen, uint8 *res);
}; };
/* They are for outside usage in C code, if needed */ /* They are for outside usage in C code, if needed */
uint hex_encode(uint8 *src, uint len, uint8 *dst); uint hex_encode(uint8 *src, uint len, uint8 *dst);
uint hex_decode(uint8 *src, uint len, uint8 *dst); uint hex_decode(uint8 *src, uint len, uint8 *dst);
uint b64_encode(uint8 *src, uint len, uint8 *dst); uint b64_encode(uint8 *src, uint len, uint8 *dst);
uint b64_decode(uint8 *src, uint len, uint8 *dst); uint b64_decode(uint8 *src, uint len, uint8 *dst);
uint hex_enc_len(uint srclen); uint hex_enc_len(uint srclen);
uint hex_dec_len(uint srclen); uint hex_dec_len(uint srclen);
uint b64_enc_len(uint srclen); uint b64_enc_len(uint srclen);
uint b64_dec_len(uint srclen); uint b64_dec_len(uint srclen);
#endif /* __PG_ENCODE_H */
#endif /* __PG_ENCODE_H */

View File

@ -1,7 +1,7 @@
/* /*
* internal.c * internal.c
* Wrapper for builtin functions * Wrapper for builtin functions
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: internal.c,v 1.2 2001/02/10 02:31:25 tgl Exp $ * $Id: internal.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -49,31 +49,32 @@
#endif #endif
static uint static uint
pg_md5_len(pg_digest *h); pg_md5_len(pg_digest * h);
static uint8 * static uint8 *
pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf); pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static uint static uint
pg_sha1_len(pg_digest *h); pg_sha1_len(pg_digest * h);
static uint8 * static uint8 *
pg_sha1_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf); pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static pg_digest static pg_digest
int_digest_list [] = { int_digest_list[] = {
{ "md5", pg_md5_len, pg_md5_digest, {0}}, {"md5", pg_md5_len, pg_md5_digest, {0}},
{ "sha1", pg_sha1_len, pg_sha1_digest, {0}}, {"sha1", pg_sha1_len, pg_sha1_digest, {0}},
{ NULL, NULL, NULL, {0}} {NULL, NULL, NULL, {0}}
}; };
static uint static uint
pg_md5_len(pg_digest *h) { pg_md5_len(pg_digest * h)
{
return MD5_DIGEST_LENGTH; return MD5_DIGEST_LENGTH;
} }
static uint8 * static uint8 *
pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf) pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{ {
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5Init(&ctx);
MD5Update(&ctx, src, len); MD5Update(&ctx, src, len);
@ -83,32 +84,31 @@ pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf)
} }
static uint static uint
pg_sha1_len(pg_digest *h) { pg_sha1_len(pg_digest * h)
{
return SHA1_DIGEST_LENGTH; return SHA1_DIGEST_LENGTH;
} }
static uint8 * static uint8 *
pg_sha1_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf) pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{ {
SHA1_CTX ctx; SHA1_CTX ctx;
SHA1Init(&ctx); SHA1Init(&ctx);
SHA1Update(&ctx, src, len); SHA1Update(&ctx, src, len);
SHA1Final(buf, &ctx); SHA1Final(buf, &ctx);
return buf; return buf;
} }
pg_digest * pg_digest *
pg_find_digest(pg_digest *h, char *name) pg_find_digest(pg_digest * h, char *name)
{ {
pg_digest *p; pg_digest *p;
for (p = int_digest_list; p->name; p++) for (p = int_digest_list; p->name; p++)
if (!strcasecmp(p->name, name)) if (!strcasecmp(p->name, name))
return p; return p;
return NULL; return NULL;
} }

View File

@ -1,7 +1,7 @@
/* /*
* krb.c * krb.c
* Wrapper for Kerberos5 libdes SHA1/MD5. * Wrapper for Kerberos5 libdes SHA1/MD5.
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,12 +26,12 @@
* 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.
* *
* *
* NOTES * NOTES
* It is possible that this works with other SHA1/MD5 * It is possible that this works with other SHA1/MD5
* implementations too. * implementations too.
* *
* $Id: krb.c,v 1.3 2001/02/20 15:34:14 momjian Exp $ * $Id: krb.c,v 1.4 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -54,31 +54,32 @@
#endif #endif
static uint static uint
pg_md5_len(pg_digest *h); pg_md5_len(pg_digest * h);
static uint8 * static uint8 *
pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf); pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static uint static uint
pg_sha1_len(pg_digest *h); pg_sha1_len(pg_digest * h);
static uint8 * static uint8 *
pg_sha1_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf); pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static pg_digest static pg_digest
int_digest_list [] = { int_digest_list[] = {
{ "md5", pg_md5_len, pg_md5_digest, {0}}, {"md5", pg_md5_len, pg_md5_digest, {0}},
{ "sha1", pg_sha1_len, pg_sha1_digest, {0}}, {"sha1", pg_sha1_len, pg_sha1_digest, {0}},
{ NULL, NULL, NULL, {0}} {NULL, NULL, NULL, {0}}
}; };
static uint static uint
pg_md5_len(pg_digest *h) { pg_md5_len(pg_digest * h)
{
return MD5_DIGEST_LENGTH; return MD5_DIGEST_LENGTH;
} }
static uint8 * static uint8 *
pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf) pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{ {
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5Init(&ctx);
MD5Update(&ctx, src, len); MD5Update(&ctx, src, len);
@ -88,32 +89,31 @@ pg_md5_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf)
} }
static uint static uint
pg_sha1_len(pg_digest *h) { pg_sha1_len(pg_digest * h)
{
return SHA1_DIGEST_LENGTH; return SHA1_DIGEST_LENGTH;
} }
static uint8 * static uint8 *
pg_sha1_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf) pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{ {
SHA1_CTX ctx; SHA1_CTX ctx;
SHA1Init(&ctx); SHA1Init(&ctx);
SHA1Update(&ctx, src, len); SHA1Update(&ctx, src, len);
SHA1Final(buf, &ctx); SHA1Final(buf, &ctx);
return buf; return buf;
} }
pg_digest * pg_digest *
pg_find_digest(pg_digest *h, char *name) pg_find_digest(pg_digest * h, char *name)
{ {
pg_digest *p; pg_digest *p;
for (p = int_digest_list; p->name; p++) for (p = int_digest_list; p->name; p++)
if (!strcasecmp(p->name, name)) if (!strcasecmp(p->name, name))
return p; return p;
return NULL; return NULL;
} }

View File

@ -1,5 +1,5 @@
/* $Id: md5.c,v 1.4 2001/02/10 02:31:25 tgl Exp $ */ /* $Id: md5.c,v 1.5 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ /* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */
/* /*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -9,18 +9,18 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors * 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -93,42 +93,43 @@
/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */ /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
static const uint32 T[65] = { static const uint32 T[65] = {
0, 0,
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
}; };
static const uint8 md5_paddat[MD5_BUFLEN] = { static const uint8 md5_paddat[MD5_BUFLEN] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}; };
static void md5_calc (uint8 *, md5_ctxt *); static void md5_calc(uint8 *, md5_ctxt *);
void md5_init(ctxt) void
md5_ctxt *ctxt; md5_init(ctxt)
md5_ctxt *ctxt;
{ {
ctxt->md5_n = 0; ctxt->md5_n = 0;
ctxt->md5_i = 0; ctxt->md5_i = 0;
@ -139,56 +140,64 @@ void md5_init(ctxt)
bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf)); bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
} }
void md5_loop(ctxt, input, len) void
md5_ctxt *ctxt; md5_loop(ctxt, input, len)
uint8 *input; md5_ctxt *ctxt;
unsigned int len; /* number of bytes */ uint8 *input;
unsigned int len; /* number of bytes */
{ {
unsigned int gap, i; unsigned int gap,
i;
ctxt->md5_n += len * 8; /* byte to bit */ ctxt->md5_n += len * 8; /* byte to bit */
gap = MD5_BUFLEN - ctxt->md5_i; gap = MD5_BUFLEN - ctxt->md5_i;
if (len >= gap) { if (len >= gap)
bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i), {
gap); bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i),
gap);
md5_calc(ctxt->md5_buf, ctxt); md5_calc(ctxt->md5_buf, ctxt);
for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) { for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN)
md5_calc((uint8 *)(input + i), ctxt); md5_calc((uint8 *) (input + i), ctxt);
}
ctxt->md5_i = len - i; ctxt->md5_i = len - i;
bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i); bcopy((void *) (input + i), (void *) ctxt->md5_buf, ctxt->md5_i);
} else { }
bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i), else
len); {
bcopy((void *) input, (void *) (ctxt->md5_buf + ctxt->md5_i),
len);
ctxt->md5_i += len; ctxt->md5_i += len;
} }
} }
void md5_pad(ctxt) void
md5_ctxt *ctxt; md5_pad(ctxt)
md5_ctxt *ctxt;
{ {
unsigned int gap; unsigned int gap;
/* Don't count up padding. Keep md5_n. */ /* Don't count up padding. Keep md5_n. */
gap = MD5_BUFLEN - ctxt->md5_i; gap = MD5_BUFLEN - ctxt->md5_i;
if (gap > 8) { if (gap > 8)
bcopy((void *)md5_paddat, {
(void *)(ctxt->md5_buf + ctxt->md5_i), bcopy((void *) md5_paddat,
gap - sizeof(ctxt->md5_n)); (void *) (ctxt->md5_buf + ctxt->md5_i),
} else { gap - sizeof(ctxt->md5_n));
}
else
{
/* including gap == 8 */ /* including gap == 8 */
bcopy((void *)md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i), bcopy((void *) md5_paddat, (void *) (ctxt->md5_buf + ctxt->md5_i),
gap); gap);
md5_calc(ctxt->md5_buf, ctxt); md5_calc(ctxt->md5_buf, ctxt);
bcopy((void *)(md5_paddat + gap), bcopy((void *) (md5_paddat + gap),
(void *)ctxt->md5_buf, (void *) ctxt->md5_buf,
MD5_BUFLEN - sizeof(ctxt->md5_n)); MD5_BUFLEN - sizeof(ctxt->md5_n));
} }
/* 8 byte word */ /* 8 byte word */
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8); bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8);
#endif #endif
@ -206,98 +215,192 @@ void md5_pad(ctxt)
md5_calc(ctxt->md5_buf, ctxt); md5_calc(ctxt->md5_buf, ctxt);
} }
void md5_result(digest, ctxt) void
uint8 *digest; md5_result(digest, ctxt)
md5_ctxt *ctxt; uint8 *digest;
md5_ctxt *ctxt;
{ {
/* 4 byte words */ /* 4 byte words */
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
bcopy(&ctxt->md5_st8[0], digest, 16); bcopy(&ctxt->md5_st8[0], digest, 16);
#endif #endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2]; digest[0] = ctxt->md5_st8[3];
digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0]; digest[1] = ctxt->md5_st8[2];
digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6]; digest[2] = ctxt->md5_st8[1];
digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4]; digest[3] = ctxt->md5_st8[0];
digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10]; digest[4] = ctxt->md5_st8[7];
digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8]; digest[5] = ctxt->md5_st8[6];
digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14]; digest[6] = ctxt->md5_st8[5];
digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12]; digest[7] = ctxt->md5_st8[4];
digest[8] = ctxt->md5_st8[11];
digest[9] = ctxt->md5_st8[10];
digest[10] = ctxt->md5_st8[9];
digest[11] = ctxt->md5_st8[8];
digest[12] = ctxt->md5_st8[15];
digest[13] = ctxt->md5_st8[14];
digest[14] = ctxt->md5_st8[13];
digest[15] = ctxt->md5_st8[12];
#endif #endif
} }
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
uint32 X[16]; uint32 X[16];
#endif #endif
static void md5_calc(b64, ctxt) static void
uint8 *b64; md5_calc(b64, ctxt)
md5_ctxt *ctxt; uint8 *b64;
md5_ctxt *ctxt;
{ {
uint32 A = ctxt->md5_sta; uint32 A = ctxt->md5_sta;
uint32 B = ctxt->md5_stb; uint32 B = ctxt->md5_stb;
uint32 C = ctxt->md5_stc; uint32 C = ctxt->md5_stc;
uint32 D = ctxt->md5_std; uint32 D = ctxt->md5_std;
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
uint32 *X = (uint32 *)b64; uint32 *X = (uint32 *) b64;
#endif
#endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
/* 4 byte words */ /* 4 byte words */
/* what a brute force but fast! */ /* what a brute force but fast! */
uint8 *y = (uint8 *)X; uint8 *y = (uint8 *) X;
y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4]; y[0] = b64[3];
y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8]; y[1] = b64[2];
y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12]; y[2] = b64[1];
y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16]; y[3] = b64[0];
y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20]; y[4] = b64[7];
y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24]; y[5] = b64[6];
y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28]; y[6] = b64[5];
y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32]; y[7] = b64[4];
y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36]; y[8] = b64[11];
y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40]; y[9] = b64[10];
y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44]; y[10] = b64[9];
y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48]; y[11] = b64[8];
y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52]; y[12] = b64[15];
y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56]; y[13] = b64[14];
y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60]; y[14] = b64[13];
y[15] = b64[12];
y[16] = b64[19];
y[17] = b64[18];
y[18] = b64[17];
y[19] = b64[16];
y[20] = b64[23];
y[21] = b64[22];
y[22] = b64[21];
y[23] = b64[20];
y[24] = b64[27];
y[25] = b64[26];
y[26] = b64[25];
y[27] = b64[24];
y[28] = b64[31];
y[29] = b64[30];
y[30] = b64[29];
y[31] = b64[28];
y[32] = b64[35];
y[33] = b64[34];
y[34] = b64[33];
y[35] = b64[32];
y[36] = b64[39];
y[37] = b64[38];
y[38] = b64[37];
y[39] = b64[36];
y[40] = b64[43];
y[41] = b64[42];
y[42] = b64[41];
y[43] = b64[40];
y[44] = b64[47];
y[45] = b64[46];
y[46] = b64[45];
y[47] = b64[44];
y[48] = b64[51];
y[49] = b64[50];
y[50] = b64[49];
y[51] = b64[48];
y[52] = b64[55];
y[53] = b64[54];
y[54] = b64[53];
y[55] = b64[52];
y[56] = b64[59];
y[57] = b64[58];
y[58] = b64[57];
y[59] = b64[56];
y[60] = b64[63];
y[61] = b64[62];
y[62] = b64[61];
y[63] = b64[60];
#endif #endif
ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2); ROUND1(A, B, C, D, 0, Sa, 1);
ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4); ROUND1(D, A, B, C, 1, Sb, 2);
ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6); ROUND1(C, D, A, B, 2, Sc, 3);
ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8); ROUND1(B, C, D, A, 3, Sd, 4);
ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10); ROUND1(A, B, C, D, 4, Sa, 5);
ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12); ROUND1(D, A, B, C, 5, Sb, 6);
ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14); ROUND1(C, D, A, B, 6, Sc, 7);
ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16); ROUND1(B, C, D, A, 7, Sd, 8);
ROUND1(A, B, C, D, 8, Sa, 9);
ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18); ROUND1(D, A, B, C, 9, Sb, 10);
ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20); ROUND1(C, D, A, B, 10, Sc, 11);
ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22); ROUND1(B, C, D, A, 11, Sd, 12);
ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24); ROUND1(A, B, C, D, 12, Sa, 13);
ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26); ROUND1(D, A, B, C, 13, Sb, 14);
ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28); ROUND1(C, D, A, B, 14, Sc, 15);
ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30); ROUND1(B, C, D, A, 15, Sd, 16);
ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34); ROUND2(A, B, C, D, 1, Se, 17);
ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36); ROUND2(D, A, B, C, 6, Sf, 18);
ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38); ROUND2(C, D, A, B, 11, Sg, 19);
ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40); ROUND2(B, C, D, A, 0, Sh, 20);
ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42); ROUND2(A, B, C, D, 5, Se, 21);
ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44); ROUND2(D, A, B, C, 10, Sf, 22);
ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46); ROUND2(C, D, A, B, 15, Sg, 23);
ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48); ROUND2(B, C, D, A, 4, Sh, 24);
ROUND2(A, B, C, D, 9, Se, 25);
ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50); ROUND2(D, A, B, C, 14, Sf, 26);
ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52); ROUND2(C, D, A, B, 3, Sg, 27);
ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54); ROUND2(B, C, D, A, 8, Sh, 28);
ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56); ROUND2(A, B, C, D, 13, Se, 29);
ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58); ROUND2(D, A, B, C, 2, Sf, 30);
ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60); ROUND2(C, D, A, B, 7, Sg, 31);
ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62); ROUND2(B, C, D, A, 12, Sh, 32);
ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64);
ROUND3(A, B, C, D, 5, Si, 33);
ROUND3(D, A, B, C, 8, Sj, 34);
ROUND3(C, D, A, B, 11, Sk, 35);
ROUND3(B, C, D, A, 14, Sl, 36);
ROUND3(A, B, C, D, 1, Si, 37);
ROUND3(D, A, B, C, 4, Sj, 38);
ROUND3(C, D, A, B, 7, Sk, 39);
ROUND3(B, C, D, A, 10, Sl, 40);
ROUND3(A, B, C, D, 13, Si, 41);
ROUND3(D, A, B, C, 0, Sj, 42);
ROUND3(C, D, A, B, 3, Sk, 43);
ROUND3(B, C, D, A, 6, Sl, 44);
ROUND3(A, B, C, D, 9, Si, 45);
ROUND3(D, A, B, C, 12, Sj, 46);
ROUND3(C, D, A, B, 15, Sk, 47);
ROUND3(B, C, D, A, 2, Sl, 48);
ROUND4(A, B, C, D, 0, Sm, 49);
ROUND4(D, A, B, C, 7, Sn, 50);
ROUND4(C, D, A, B, 14, So, 51);
ROUND4(B, C, D, A, 5, Sp, 52);
ROUND4(A, B, C, D, 12, Sm, 53);
ROUND4(D, A, B, C, 3, Sn, 54);
ROUND4(C, D, A, B, 10, So, 55);
ROUND4(B, C, D, A, 1, Sp, 56);
ROUND4(A, B, C, D, 8, Sm, 57);
ROUND4(D, A, B, C, 15, Sn, 58);
ROUND4(C, D, A, B, 6, So, 59);
ROUND4(B, C, D, A, 13, Sp, 60);
ROUND4(A, B, C, D, 4, Sm, 61);
ROUND4(D, A, B, C, 11, Sn, 62);
ROUND4(C, D, A, B, 2, So, 63);
ROUND4(B, C, D, A, 9, Sp, 64);
ctxt->md5_sta += A; ctxt->md5_sta += A;
ctxt->md5_stb += B; ctxt->md5_stb += B;

View File

@ -1,5 +1,5 @@
/* $Id: md5.h,v 1.3 2001/01/09 16:07:13 momjian Exp $ */ /* $Id: md5.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/* /*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -9,18 +9,18 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors * 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -35,11 +35,13 @@
#define MD5_BUFLEN 64 #define MD5_BUFLEN 64
typedef struct { typedef struct
union { {
union
{
uint32 md5_state32[4]; uint32 md5_state32[4];
uint8 md5_state8[16]; uint8 md5_state8[16];
} md5_st; } md5_st;
#define md5_sta md5_st.md5_state32[0] #define md5_sta md5_st.md5_state32[0]
#define md5_stb md5_st.md5_state32[1] #define md5_stb md5_st.md5_state32[1]
@ -47,21 +49,22 @@ typedef struct {
#define md5_std md5_st.md5_state32[3] #define md5_std md5_st.md5_state32[3]
#define md5_st8 md5_st.md5_state8 #define md5_st8 md5_st.md5_state8
union { union
{
uint64 md5_count64; uint64 md5_count64;
uint8 md5_count8[8]; uint8 md5_count8[8];
} md5_count; } md5_count;
#define md5_n md5_count.md5_count64 #define md5_n md5_count.md5_count64
#define md5_n8 md5_count.md5_count8 #define md5_n8 md5_count.md5_count8
unsigned int md5_i; unsigned int md5_i;
uint8 md5_buf[MD5_BUFLEN]; uint8 md5_buf[MD5_BUFLEN];
} md5_ctxt; } md5_ctxt;
extern void md5_init (md5_ctxt *); extern void md5_init(md5_ctxt *);
extern void md5_loop (md5_ctxt *, uint8 *, unsigned int); extern void md5_loop(md5_ctxt *, uint8 *, unsigned int);
extern void md5_pad (md5_ctxt *); extern void md5_pad(md5_ctxt *);
extern void md5_result (uint8 *, md5_ctxt *); extern void md5_result(uint8 *, md5_ctxt *);
/* compatibility */ /* compatibility */
#define MD5_CTX md5_ctxt #define MD5_CTX md5_ctxt
@ -73,4 +76,4 @@ do { \
md5_result((x), (y)); \ md5_result((x), (y)); \
} while (0) } while (0)
#endif /* ! _NETINET6_MD5_H_*/ #endif /* ! _NETINET6_MD5_H_ */

View File

@ -1,7 +1,7 @@
/* /*
* mhash.c * mhash.c
* Wrapper for mhash library. * Wrapper for mhash library.
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: mhash.c,v 1.2 2001/02/10 02:31:26 tgl Exp $ * $Id: mhash.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -36,45 +36,50 @@
#include <mhash.h> #include <mhash.h>
static uint static uint
pg_mhash_len(pg_digest *hash); pg_mhash_len(pg_digest * hash);
static uint8 * static uint8 *pg_mhash_digest(pg_digest * hash, uint8 *src,
pg_mhash_digest(pg_digest *hash, uint8 *src, uint len, uint8 *buf);
uint len, uint8 *buf);
static uint static uint
pg_mhash_len(pg_digest *h) { pg_mhash_len(pg_digest * h)
{
return mhash_get_block_size(h->misc.code); return mhash_get_block_size(h->misc.code);
} }
static uint8 * static uint8 *
pg_mhash_digest(pg_digest *h, uint8 *src, uint len, uint8 *dst) pg_mhash_digest(pg_digest * h, uint8 *src, uint len, uint8 *dst)
{ {
uint8 *res; uint8 *res;
MHASH mh = mhash_init(h->misc.code); MHASH mh = mhash_init(h->misc.code);
mhash(mh, src, len); mhash(mh, src, len);
res = mhash_end(mh); res = mhash_end(mh);
memcpy(dst, res, mhash_get_block_size(h->misc.code)); memcpy(dst, res, mhash_get_block_size(h->misc.code));
mhash_free(res); mhash_free(res);
return dst; return dst;
} }
pg_digest * pg_digest *
pg_find_digest(pg_digest *h, char *name) pg_find_digest(pg_digest * h, char *name)
{ {
size_t hnum, i, b; size_t hnum,
char *mname; i,
b;
char *mname;
hnum = mhash_count(); hnum = mhash_count();
for (i = 0; i <= hnum; i++) { for (i = 0; i <= hnum; i++)
{
mname = mhash_get_hash_name(i); mname = mhash_get_hash_name(i);
if (mname == NULL) if (mname == NULL)
continue; continue;
b = strcasecmp(name, mname); b = strcasecmp(name, mname);
free(mname); free(mname);
if (!b) { if (!b)
{
h->name = mhash_get_hash_name(i); h->name = mhash_get_hash_name(i);
h->length = pg_mhash_len; h->length = pg_mhash_len;
h->digest = pg_mhash_digest; h->digest = pg_mhash_digest;
@ -84,4 +89,3 @@ pg_find_digest(pg_digest *h, char *name)
} }
return NULL; return NULL;
} }

View File

@ -1,7 +1,7 @@
/* /*
* openssl.c * openssl.c
* Wrapper for OpenSSL library. * Wrapper for OpenSSL library.
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: openssl.c,v 1.2 2001/02/10 02:31:26 tgl Exp $ * $Id: openssl.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -36,50 +36,50 @@
#include <evp.h> #include <evp.h>
static uint static uint
pg_ossl_len(pg_digest *h); pg_ossl_len(pg_digest * h);
static uint8 * static uint8 *
pg_ossl_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf); pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
static uint static uint
pg_ossl_len(pg_digest *h) { pg_ossl_len(pg_digest * h)
return EVP_MD_size((EVP_MD*)h->misc.ptr); {
return EVP_MD_size((EVP_MD *) h->misc.ptr);
} }
static uint8 * static uint8 *
pg_ossl_digest(pg_digest *h, uint8 *src, uint len, uint8 *buf) pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{ {
EVP_MD *md = (EVP_MD*)h->misc.ptr; EVP_MD *md = (EVP_MD *) h->misc.ptr;
EVP_MD_CTX ctx; EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, md); EVP_DigestInit(&ctx, md);
EVP_DigestUpdate(&ctx, src, len); EVP_DigestUpdate(&ctx, src, len);
EVP_DigestFinal(&ctx, buf, NULL); EVP_DigestFinal(&ctx, buf, NULL);
return buf; return buf;
} }
static int pg_openssl_initialized = 0; static int pg_openssl_initialized = 0;
pg_digest * pg_digest *
pg_find_digest(pg_digest *h, char *name) pg_find_digest(pg_digest * h, char *name)
{ {
const EVP_MD *md; const EVP_MD *md;
if (!pg_openssl_initialized) { if (!pg_openssl_initialized)
{
OpenSSL_add_all_digests(); OpenSSL_add_all_digests();
pg_openssl_initialized = 1; pg_openssl_initialized = 1;
} }
md = EVP_get_digestbyname(name); md = EVP_get_digestbyname(name);
if (md == NULL) if (md == NULL)
return NULL; return NULL;
h->name = name; h->name = name;
h->length = pg_ossl_len; h->length = pg_ossl_len;
h->digest = pg_ossl_digest; h->digest = pg_ossl_digest;
h->misc.ptr = (void*)md; h->misc.ptr = (void *) md;
return h; return h;
} }

View File

@ -1,7 +1,7 @@
/* /*
* pgcrypto.c * pgcrypto.c
* Cryptographic digests for PostgreSQL. * Cryptographic digests for PostgreSQL.
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.c,v 1.6 2001/02/10 02:31:26 tgl Exp $ * $Id: pgcrypto.c,v 1.7 2001/03/22 03:59:10 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -44,12 +44,12 @@
/* exported functions */ /* exported functions */
Datum digest(PG_FUNCTION_ARGS); Datum digest(PG_FUNCTION_ARGS);
Datum digest_exists(PG_FUNCTION_ARGS); Datum digest_exists(PG_FUNCTION_ARGS);
/* private stuff */ /* private stuff */
static pg_digest * static pg_digest *
find_digest(pg_digest *hbuf, text *name, int silent); find_digest(pg_digest * hbuf, text *name, int silent);
/* SQL function: hash(text, text) returns text */ /* SQL function: hash(text, text) returns text */
@ -58,31 +58,33 @@ PG_FUNCTION_INFO_V1(digest);
Datum Datum
digest(PG_FUNCTION_ARGS) digest(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
text *name; text *name;
uint len, hlen; uint len,
pg_digest *h, _hbuf; hlen;
text *res; pg_digest *h,
_hbuf;
text *res;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
PG_RETURN_NULL(); PG_RETURN_NULL();
name = PG_GETARG_TEXT_P(1); name = PG_GETARG_TEXT_P(1);
h = find_digest(&_hbuf, name, 0); /* will give error if fails */ h = find_digest(&_hbuf, name, 0); /* will give error if fails */
hlen = h->length(h); hlen = h->length(h);
res = (text *)palloc(hlen + VARHDRSZ); res = (text *) palloc(hlen + VARHDRSZ);
VARATT_SIZEP(res) = hlen + VARHDRSZ; VARATT_SIZEP(res) = hlen + VARHDRSZ;
arg = PG_GETARG_TEXT_P(0); arg = PG_GETARG_TEXT_P(0);
len = VARSIZE(arg) - VARHDRSZ; len = VARSIZE(arg) - VARHDRSZ;
h->digest(h, VARDATA(arg), len, VARDATA(res)); h->digest(h, VARDATA(arg), len, VARDATA(res));
PG_FREE_IF_COPY(arg, 0); PG_FREE_IF_COPY(arg, 0);
PG_FREE_IF_COPY(name, 1); PG_FREE_IF_COPY(name, 1);
PG_RETURN_TEXT_P(res); PG_RETURN_TEXT_P(res);
} }
@ -92,16 +94,17 @@ PG_FUNCTION_INFO_V1(digest_exists);
Datum Datum
digest_exists(PG_FUNCTION_ARGS) digest_exists(PG_FUNCTION_ARGS)
{ {
text *name; text *name;
pg_digest _hbuf, *res; pg_digest _hbuf,
*res;
if (PG_ARGISNULL(0)) if (PG_ARGISNULL(0))
PG_RETURN_NULL(); PG_RETURN_NULL();
name = PG_GETARG_TEXT_P(0); name = PG_GETARG_TEXT_P(0);
res = find_digest(&_hbuf, name, 1); res = find_digest(&_hbuf, name, 1);
PG_FREE_IF_COPY(name, 0); PG_FREE_IF_COPY(name, 0);
if (res != NULL) if (res != NULL)
@ -110,26 +113,26 @@ digest_exists(PG_FUNCTION_ARGS)
} }
static pg_digest * static pg_digest *
find_digest(pg_digest *hbuf, text *name, int silent) find_digest(pg_digest * hbuf, text *name, int silent)
{ {
pg_digest *p; pg_digest *p;
char buf[NAMEDATALEN]; char buf[NAMEDATALEN];
uint len; uint len;
len = VARSIZE(name) - VARHDRSZ; len = VARSIZE(name) - VARHDRSZ;
if (len >= NAMEDATALEN) { if (len >= NAMEDATALEN)
{
if (silent) if (silent)
return NULL; return NULL;
elog(ERROR, "Hash type does not exist (name too long)"); elog(ERROR, "Hash type does not exist (name too long)");
} }
memcpy(buf, VARDATA(name), len); memcpy(buf, VARDATA(name), len);
buf[len] = 0; buf[len] = 0;
p = pg_find_digest(hbuf, buf); p = pg_find_digest(hbuf, buf);
if (p == NULL && !silent) if (p == NULL && !silent)
elog(ERROR, "Hash type does not exist: '%s'", buf); elog(ERROR, "Hash type does not exist: '%s'", buf);
return p; return p;
} }

View File

@ -1,7 +1,7 @@
/* /*
* pgcrypto.h * pgcrypto.h
* Header file for pgcrypto. * Header file for pgcrypto.
* *
* Copyright (c) 2000 Marko Kreen * Copyright (c) 2000 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,25 +26,27 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.h,v 1.2 2001/01/09 16:07:13 momjian Exp $ * $Id: pgcrypto.h,v 1.3 2001/03/22 03:59:10 momjian Exp $
*/ */
#ifndef _PG_CRYPTO_H #ifndef _PG_CRYPTO_H
#define _PG_CRYPTO_H #define _PG_CRYPTO_H
typedef struct _pg_digest pg_digest; typedef struct _pg_digest pg_digest;
struct _pg_digest { struct _pg_digest
char *name; {
uint (*length)(pg_digest *h); char *name;
uint8 *(*digest)(pg_digest *h, uint8 *data, uint (*length) (pg_digest * h);
uint dlen, uint8 *buf); uint8 *(*digest) (pg_digest * h, uint8 *data,
uint dlen, uint8 *buf);
/* private */ /* private */
union { union
uint code; {
uint code;
const void *ptr; const void *ptr;
} misc; } misc;
}; };
extern pg_digest *pg_find_digest(pg_digest *hbuf, char *name); extern pg_digest *pg_find_digest(pg_digest * hbuf, char *name);
#endif #endif

View File

@ -1,5 +1,5 @@
/* $Id: sha1.c,v 1.4 2001/02/10 02:31:26 tgl Exp $ */ /* $Id: sha1.c,v 1.5 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/* /*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -9,18 +9,18 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors * 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -41,120 +41,182 @@
/* sanity check */ /* sanity check */
#if BYTE_ORDER != BIG_ENDIAN #if BYTE_ORDER != BIG_ENDIAN
# if BYTE_ORDER != LITTLE_ENDIAN #if BYTE_ORDER != LITTLE_ENDIAN
# define unsupported 1 #define unsupported 1
# endif #endif
#endif #endif
#ifndef unsupported #ifndef unsupported
/* constant table */ /* constant table */
static uint32 _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
#define K(t) _K[(t) / 20]
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) #define K(t) _K[(t) / 20]
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
#define S(n, x) (((x) << (n)) | ((x) >> (32 - n))) #define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
#define H(n) (ctxt->h.b32[(n)]) #define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
#define COUNT (ctxt->count)
#define BCOUNT (ctxt->c.b64[0] / 8)
#define W(n) (ctxt->m.b32[(n)])
#define PUTBYTE(x) { \ #define H(n) (ctxt->h.b32[(n)])
#define COUNT (ctxt->count)
#define BCOUNT (ctxt->c.b64[0] / 8)
#define W(n) (ctxt->m.b32[(n)])
#define PUTBYTE(x) { \
ctxt->m.b8[(COUNT % 64)] = (x); \ ctxt->m.b8[(COUNT % 64)] = (x); \
COUNT++; \ COUNT++; \
COUNT %= 64; \ COUNT %= 64; \
ctxt->c.b64[0] += 8; \ ctxt->c.b64[0] += 8; \
if (COUNT % 64 == 0) \ if (COUNT % 64 == 0) \
sha1_step(ctxt); \ sha1_step(ctxt); \
} }
#define PUTPAD(x) { \ #define PUTPAD(x) { \
ctxt->m.b8[(COUNT % 64)] = (x); \ ctxt->m.b8[(COUNT % 64)] = (x); \
COUNT++; \ COUNT++; \
COUNT %= 64; \ COUNT %= 64; \
if (COUNT % 64 == 0) \ if (COUNT % 64 == 0) \
sha1_step(ctxt); \ sha1_step(ctxt); \
} }
static void sha1_step (struct sha1_ctxt *); static void sha1_step(struct sha1_ctxt *);
static void static void
sha1_step(ctxt) sha1_step(ctxt)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
{ {
uint32 a, b, c, d, e; uint32 a,
size_t t, s; b,
uint32 tmp; c,
d,
e;
size_t t,
s;
uint32 tmp;
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
struct sha1_ctxt tctxt; struct sha1_ctxt tctxt;
bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64); bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2]; ctxt->m.b8[0] = tctxt.m.b8[3];
ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0]; ctxt->m.b8[1] = tctxt.m.b8[2];
ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6]; ctxt->m.b8[2] = tctxt.m.b8[1];
ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4]; ctxt->m.b8[3] = tctxt.m.b8[0];
ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10]; ctxt->m.b8[4] = tctxt.m.b8[7];
ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8]; ctxt->m.b8[5] = tctxt.m.b8[6];
ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14]; ctxt->m.b8[6] = tctxt.m.b8[5];
ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12]; ctxt->m.b8[7] = tctxt.m.b8[4];
ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18]; ctxt->m.b8[8] = tctxt.m.b8[11];
ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16]; ctxt->m.b8[9] = tctxt.m.b8[10];
ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22]; ctxt->m.b8[10] = tctxt.m.b8[9];
ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20]; ctxt->m.b8[11] = tctxt.m.b8[8];
ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26]; ctxt->m.b8[12] = tctxt.m.b8[15];
ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24]; ctxt->m.b8[13] = tctxt.m.b8[14];
ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30]; ctxt->m.b8[14] = tctxt.m.b8[13];
ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28]; ctxt->m.b8[15] = tctxt.m.b8[12];
ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34]; ctxt->m.b8[16] = tctxt.m.b8[19];
ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32]; ctxt->m.b8[17] = tctxt.m.b8[18];
ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38]; ctxt->m.b8[18] = tctxt.m.b8[17];
ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36]; ctxt->m.b8[19] = tctxt.m.b8[16];
ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42]; ctxt->m.b8[20] = tctxt.m.b8[23];
ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40]; ctxt->m.b8[21] = tctxt.m.b8[22];
ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46]; ctxt->m.b8[22] = tctxt.m.b8[21];
ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44]; ctxt->m.b8[23] = tctxt.m.b8[20];
ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50]; ctxt->m.b8[24] = tctxt.m.b8[27];
ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48]; ctxt->m.b8[25] = tctxt.m.b8[26];
ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54]; ctxt->m.b8[26] = tctxt.m.b8[25];
ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52]; ctxt->m.b8[27] = tctxt.m.b8[24];
ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58]; ctxt->m.b8[28] = tctxt.m.b8[31];
ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56]; ctxt->m.b8[29] = tctxt.m.b8[30];
ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62]; ctxt->m.b8[30] = tctxt.m.b8[29];
ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60]; ctxt->m.b8[31] = tctxt.m.b8[28];
ctxt->m.b8[32] = tctxt.m.b8[35];
ctxt->m.b8[33] = tctxt.m.b8[34];
ctxt->m.b8[34] = tctxt.m.b8[33];
ctxt->m.b8[35] = tctxt.m.b8[32];
ctxt->m.b8[36] = tctxt.m.b8[39];
ctxt->m.b8[37] = tctxt.m.b8[38];
ctxt->m.b8[38] = tctxt.m.b8[37];
ctxt->m.b8[39] = tctxt.m.b8[36];
ctxt->m.b8[40] = tctxt.m.b8[43];
ctxt->m.b8[41] = tctxt.m.b8[42];
ctxt->m.b8[42] = tctxt.m.b8[41];
ctxt->m.b8[43] = tctxt.m.b8[40];
ctxt->m.b8[44] = tctxt.m.b8[47];
ctxt->m.b8[45] = tctxt.m.b8[46];
ctxt->m.b8[46] = tctxt.m.b8[45];
ctxt->m.b8[47] = tctxt.m.b8[44];
ctxt->m.b8[48] = tctxt.m.b8[51];
ctxt->m.b8[49] = tctxt.m.b8[50];
ctxt->m.b8[50] = tctxt.m.b8[49];
ctxt->m.b8[51] = tctxt.m.b8[48];
ctxt->m.b8[52] = tctxt.m.b8[55];
ctxt->m.b8[53] = tctxt.m.b8[54];
ctxt->m.b8[54] = tctxt.m.b8[53];
ctxt->m.b8[55] = tctxt.m.b8[52];
ctxt->m.b8[56] = tctxt.m.b8[59];
ctxt->m.b8[57] = tctxt.m.b8[58];
ctxt->m.b8[58] = tctxt.m.b8[57];
ctxt->m.b8[59] = tctxt.m.b8[56];
ctxt->m.b8[60] = tctxt.m.b8[63];
ctxt->m.b8[61] = tctxt.m.b8[62];
ctxt->m.b8[62] = tctxt.m.b8[61];
ctxt->m.b8[63] = tctxt.m.b8[60];
#endif #endif
a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); a = H(0);
b = H(1);
c = H(2);
d = H(3);
e = H(4);
for (t = 0; t < 20; t++) { for (t = 0; t < 20; t++)
{
s = t & 0x0f; s = t & 0x0f;
if (t >= 16) { if (t >= 16)
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
}
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 20; t < 40; t++) { for (t = 20; t < 40; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 40; t < 60; t++) { for (t = 40; t < 60; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
for (t = 60; t < 80; t++) { for (t = 60; t < 80; t++)
{
s = t & 0x0f; s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp; e = d;
d = c;
c = S(30, b);
b = a;
a = tmp;
} }
H(0) = H(0) + a; H(0) = H(0) + a;
@ -170,7 +232,7 @@ sha1_step(ctxt)
void void
sha1_init(ctxt) sha1_init(ctxt)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
{ {
bzero(ctxt, sizeof(struct sha1_ctxt)); bzero(ctxt, sizeof(struct sha1_ctxt));
H(0) = 0x67452301; H(0) = 0x67452301;
@ -182,55 +244,65 @@ sha1_init(ctxt)
void void
sha1_pad(ctxt) sha1_pad(ctxt)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
{ {
size_t padlen; /*pad length in bytes*/ size_t padlen; /* pad length in bytes */
size_t padstart; size_t padstart;
PUTPAD(0x80); PUTPAD(0x80);
padstart = COUNT % 64; padstart = COUNT % 64;
padlen = 64 - padstart; padlen = 64 - padstart;
if (padlen < 8) { if (padlen < 8)
{
bzero(&ctxt->m.b8[padstart], padlen); bzero(&ctxt->m.b8[padstart], padlen);
COUNT += padlen; COUNT += padlen;
COUNT %= 64; COUNT %= 64;
sha1_step(ctxt); sha1_step(ctxt);
padstart = COUNT % 64; /* should be 0 */ padstart = COUNT % 64; /* should be 0 */
padlen = 64 - padstart; /* should be 64 */ padlen = 64 - padstart; /* should be 64 */
} }
bzero(&ctxt->m.b8[padstart], padlen - 8); bzero(&ctxt->m.b8[padstart], padlen - 8);
COUNT += (padlen - 8); COUNT += (padlen - 8);
COUNT %= 64; COUNT %= 64;
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[1]);
PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[2]);
PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[3]);
PUTPAD(ctxt->c.b8[4]);
PUTPAD(ctxt->c.b8[5]);
PUTPAD(ctxt->c.b8[6]);
PUTPAD(ctxt->c.b8[7]);
#else #else
PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[6]);
PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[5]);
PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[4]);
PUTPAD(ctxt->c.b8[3]);
PUTPAD(ctxt->c.b8[2]);
PUTPAD(ctxt->c.b8[1]);
PUTPAD(ctxt->c.b8[0]);
#endif #endif
} }
void void
sha1_loop(ctxt, input0, len) sha1_loop(ctxt, input0, len)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
const caddr_t input0; const caddr_t input0;
size_t len; size_t len;
{ {
const uint8 *input; const uint8 *input;
size_t gaplen; size_t gaplen;
size_t gapstart; size_t gapstart;
size_t off; size_t off;
size_t copysiz; size_t copysiz;
input = (const uint8 *)input0; input = (const uint8 *) input0;
off = 0; off = 0;
while (off < len) { while (off < len)
{
gapstart = COUNT % 64; gapstart = COUNT % 64;
gaplen = 64 - gapstart; gaplen = 64 - gapstart;
@ -247,27 +319,37 @@ sha1_loop(ctxt, input0, len)
void void
sha1_result(ctxt, digest0) sha1_result(ctxt, digest0)
struct sha1_ctxt *ctxt; struct sha1_ctxt *ctxt;
caddr_t digest0; caddr_t digest0;
{ {
uint8 *digest; uint8 *digest;
digest = (uint8 *)digest0; digest = (uint8 *) digest0;
sha1_pad(ctxt); sha1_pad(ctxt);
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
bcopy(&ctxt->h.b8[0], digest, 20); bcopy(&ctxt->h.b8[0], digest, 20);
#else #else
digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2]; digest[0] = ctxt->h.b8[3];
digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0]; digest[1] = ctxt->h.b8[2];
digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6]; digest[2] = ctxt->h.b8[1];
digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4]; digest[3] = ctxt->h.b8[0];
digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10]; digest[4] = ctxt->h.b8[7];
digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8]; digest[5] = ctxt->h.b8[6];
digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14]; digest[6] = ctxt->h.b8[5];
digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12]; digest[7] = ctxt->h.b8[4];
digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18]; digest[8] = ctxt->h.b8[11];
digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16]; digest[9] = ctxt->h.b8[10];
digest[10] = ctxt->h.b8[9];
digest[11] = ctxt->h.b8[8];
digest[12] = ctxt->h.b8[15];
digest[13] = ctxt->h.b8[14];
digest[14] = ctxt->h.b8[13];
digest[15] = ctxt->h.b8[12];
digest[16] = ctxt->h.b8[19];
digest[17] = ctxt->h.b8[18];
digest[18] = ctxt->h.b8[17];
digest[19] = ctxt->h.b8[16];
#endif #endif
} }
#endif /*unsupported*/ #endif /* unsupported */

View File

@ -1,5 +1,5 @@
/* $Id: sha1.h,v 1.3 2001/01/09 16:07:13 momjian Exp $ */ /* $Id: sha1.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ */
/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */
/* /*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -9,18 +9,18 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors * 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -38,33 +38,38 @@
#ifndef _NETINET6_SHA1_H_ #ifndef _NETINET6_SHA1_H_
#define _NETINET6_SHA1_H_ #define _NETINET6_SHA1_H_
struct sha1_ctxt { struct sha1_ctxt
union { {
union
{
uint8 b8[20]; uint8 b8[20];
uint32 b32[5]; uint32 b32[5];
} h; } h;
union { union
{
uint8 b8[8]; uint8 b8[8];
uint64 b64[1]; uint64 b64[1];
} c; } c;
union { union
{
uint8 b8[64]; uint8 b8[64];
uint32 b32[16]; uint32 b32[16];
} m; } m;
uint8 count; uint8 count;
}; };
extern void sha1_init (struct sha1_ctxt *); extern void sha1_init(struct sha1_ctxt *);
extern void sha1_pad (struct sha1_ctxt *); extern void sha1_pad(struct sha1_ctxt *);
extern void sha1_loop (struct sha1_ctxt *, const caddr_t, size_t); extern void sha1_loop(struct sha1_ctxt *, const caddr_t, size_t);
extern void sha1_result (struct sha1_ctxt *, caddr_t); extern void sha1_result(struct sha1_ctxt *, caddr_t);
/* compatibilty with other SHA1 source codes */ /* compatibilty with other SHA1 source codes */
typedef struct sha1_ctxt SHA1_CTX; typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Init(x) sha1_init((x)) #define SHA1Init(x) sha1_init((x))
#define SHA1Update(x, y, z) sha1_loop((x), (y), (z)) #define SHA1Update(x, y, z) sha1_loop((x), (y), (z))
#define SHA1Final(x, y) sha1_result((y), (x)) #define SHA1Final(x, y) sha1_result((y), (x))
#define SHA1_RESULTLEN (160/8) #define SHA1_RESULTLEN (160/8)
#endif /*_NETINET6_SHA1_H_*/ #endif /* _NETINET6_SHA1_H_ */

View File

@ -16,18 +16,20 @@
PG_FUNCTION_INFO_V1(_rserv_log_); PG_FUNCTION_INFO_V1(_rserv_log_);
PG_FUNCTION_INFO_V1(_rserv_sync_); PG_FUNCTION_INFO_V1(_rserv_sync_);
PG_FUNCTION_INFO_V1(_rserv_debug_); PG_FUNCTION_INFO_V1(_rserv_debug_);
Datum _rserv_log_(PG_FUNCTION_ARGS); Datum _rserv_log_(PG_FUNCTION_ARGS);
Datum _rserv_sync_(PG_FUNCTION_ARGS); Datum _rserv_sync_(PG_FUNCTION_ARGS);
Datum _rserv_debug_(PG_FUNCTION_ARGS); Datum _rserv_debug_(PG_FUNCTION_ARGS);
#else #else
HeapTuple _rserv_log_(void); HeapTuple _rserv_log_(void);
int32 _rserv_sync_(int32); int32 _rserv_sync_(int32);
int32 _rserv_debug_(int32); int32 _rserv_debug_(int32);
#endif #endif
static int debug = 0; static int debug = 0;
static char* OutputValue(char *key, char *buf, int size); static char *OutputValue(char *key, char *buf, int size);
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
Datum Datum
@ -68,7 +70,7 @@ _rserv_log_()
nargs = trigger->tgnargs; nargs = trigger->tgnargs;
args = trigger->tgargs; args = trigger->tgargs;
if (nargs != 1) /* odd number of arguments! */ if (nargs != 1) /* odd number of arguments! */
elog(ERROR, "_rserv_log_: need in *one* argument"); elog(ERROR, "_rserv_log_: need in *one* argument");
keynum = atoi(args[0]); keynum = atoi(args[0]);
@ -79,7 +81,7 @@ _rserv_log_()
rel = CurrentTriggerData->tg_relation; rel = CurrentTriggerData->tg_relation;
tupdesc = rel->rd_att; tupdesc = rel->rd_att;
deleted = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ? deleted = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ?
1 : 0; 1 : 0;
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
@ -115,7 +117,7 @@ _rserv_log_()
if (strcmp(newkey, key) == 0) if (strcmp(newkey, key) == 0)
newkey = NULL; newkey = NULL;
else else
deleted = 1; /* old key was deleted */ deleted = 1; /* old key was deleted */
} }
if (strpbrk(key, "\\ \n'")) if (strpbrk(key, "\\ \n'"))
@ -124,7 +126,7 @@ _rserv_log_()
okey = key; okey = key;
sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), " sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "
"deleted = %d where reloid = %u and key = '%s'", "deleted = %d where reloid = %u and key = '%s'",
GetCurrentTransactionId(), deleted, rel->rd_id, okey); GetCurrentTransactionId(), deleted, rel->rd_id, okey);
if (debug) if (debug)
@ -145,7 +147,7 @@ _rserv_log_()
sprintf(sql, "insert into _RSERV_LOG_ " sprintf(sql, "insert into _RSERV_LOG_ "
"(reloid, logid, logtime, deleted, key) " "(reloid, logid, logtime, deleted, key) "
"values (%u, %d, now(), %d, '%s')", "values (%u, %d, now(), %d, '%s')",
rel->rd_id, GetCurrentTransactionId(), rel->rd_id, GetCurrentTransactionId(),
deleted, okey); deleted, okey);
if (debug) if (debug)
@ -169,7 +171,7 @@ _rserv_log_()
sprintf(sql, "insert into _RSERV_LOG_ " sprintf(sql, "insert into _RSERV_LOG_ "
"(reloid, logid, logtime, deleted, key) " "(reloid, logid, logtime, deleted, key) "
"values (%u, %d, now(), 0, '%s')", "values (%u, %d, now(), 0, '%s')",
rel->rd_id, GetCurrentTransactionId(), okey); rel->rd_id, GetCurrentTransactionId(), okey);
if (debug) if (debug)
@ -202,13 +204,14 @@ _rserv_sync_(int32 server)
#endif #endif
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 server = PG_GETARG_INT32(0); int32 server = PG_GETARG_INT32(0);
#endif #endif
char sql[8192]; char sql[8192];
char buf[8192]; char buf[8192];
char *active = buf; char *active = buf;
uint32 xcnt; uint32 xcnt;
int ret; int ret;
if (SerializableSnapshot == NULL) if (SerializableSnapshot == NULL)
elog(ERROR, "_rserv_sync_: SerializableSnapshot is NULL"); elog(ERROR, "_rserv_sync_: SerializableSnapshot is NULL");
@ -217,7 +220,7 @@ _rserv_sync_(int32 server)
for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++) for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++)
{ {
sprintf(buf + strlen(buf), "%s%u", (xcnt) ? ", " : "", sprintf(buf + strlen(buf), "%s%u", (xcnt) ? ", " : "",
SerializableSnapshot->xip[xcnt]); SerializableSnapshot->xip[xcnt]);
} }
if ((ret = SPI_connect()) < 0) if ((ret = SPI_connect()) < 0)
@ -225,7 +228,7 @@ _rserv_sync_(int32 server)
sprintf(sql, "insert into _RSERV_SYNC_ " sprintf(sql, "insert into _RSERV_SYNC_ "
"(server, syncid, synctime, status, minid, maxid, active) " "(server, syncid, synctime, status, minid, maxid, active) "
"values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')", "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')",
server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active); server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active);
ret = SPI_exec(sql, 0); ret = SPI_exec(sql, 0);
@ -247,18 +250,19 @@ _rserv_debug_(int32 newval)
#endif #endif
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 newval = PG_GETARG_INT32(0); int32 newval = PG_GETARG_INT32(0);
#endif #endif
int32 oldval = debug; int32 oldval = debug;
debug = newval; debug = newval;
return (oldval); return (oldval);
} }
#define ExtendBy 1024 #define ExtendBy 1024
static char* static char *
OutputValue(char *key, char *buf, int size) OutputValue(char *key, char *buf, int size)
{ {
int i = 0; int i = 0;
@ -267,39 +271,45 @@ OutputValue(char *key, char *buf, int size)
int slen = 0; int slen = 0;
size--; size--;
for ( ; ; ) for (;;)
{ {
switch (*key) switch (*key)
{ {
case '\\': subst ="\\\\"; case '\\':
slen = 2; subst = "\\\\";
break; slen = 2;
case ' ': subst = "\\011"; break;
slen = 4; case ' ':
break; subst = "\\011";
case '\n': subst = "\\012"; slen = 4;
slen = 4; break;
break; case '\n':
case '\'': subst = "\\047"; subst = "\\012";
slen = 4; slen = 4;
break; break;
case '\0': out[i] = 0; case '\'':
return(out); subst = "\\047";
default: slen = 1; slen = 4;
break; break;
case '\0':
out[i] = 0;
return (out);
default:
slen = 1;
break;
} }
if (i + slen >= size) if (i + slen >= size)
{ {
if (out == buf) if (out == buf)
{ {
out = (char*) palloc(size + ExtendBy); out = (char *) palloc(size + ExtendBy);
strncpy(out, buf, i); strncpy(out, buf, i);
size += ExtendBy; size += ExtendBy;
} }
else else
{ {
out = (char*) repalloc(out, size + ExtendBy); out = (char *) repalloc(out, size + ExtendBy);
size += ExtendBy; size += ExtendBy;
} }
} }
@ -314,6 +324,6 @@ OutputValue(char *key, char *buf, int size)
key++; key++;
} }
return(out); return (out);
} }

View File

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

View File

@ -1,8 +1,8 @@
extern void set_parse_buffer( char* s ); extern void set_parse_buffer(char *s);
extern void reset_parse_buffer( void ); extern void reset_parse_buffer(void);
extern int read_parse_buffer( void ); extern int read_parse_buffer(void);
extern char * parse_buffer( void ); extern char *parse_buffer(void);
extern char * parse_buffer_ptr( void ); extern char *parse_buffer_ptr(void);
extern unsigned int parse_buffer_curr_char( void ); extern unsigned int parse_buffer_curr_char(void);
extern unsigned int parse_buffer_pos( void ); extern unsigned int parse_buffer_pos(void);
extern unsigned int parse_buffer_size( void ); extern unsigned int parse_buffer_size(void);

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
typedef struct SEG { typedef struct SEG
float lower; {
float upper; float lower;
char l_sigd; float upper;
char u_sigd; char l_sigd;
char l_ext; char u_sigd;
char u_ext; char l_ext;
} SEG; char u_ext;
} SEG;

View File

@ -1,4 +1,4 @@
/* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.10 2001/02/10 02:31:26 tgl Exp $ */ /* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.11 2001/03/22 03:59:10 momjian Exp $ */
#include "postgres.h" #include "postgres.h"
#include <ctype.h> #include <ctype.h>
@ -7,7 +7,7 @@
#include "utils/builtins.h" #include "utils/builtins.h"
Datum text_soundex(PG_FUNCTION_ARGS); Datum text_soundex(PG_FUNCTION_ARGS);
static void soundex(const char *instr, char *outstr); static void soundex(const char *instr, char *outstr);
@ -37,11 +37,12 @@ text_soundex(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(_textin(outstr)); PG_RETURN_TEXT_P(_textin(outstr));
} }
#endif /* not SOUNDEX_TEST */ #endif /* not SOUNDEX_TEST */
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
static const char *soundex_table = "01230120022455012623010202"; static const char *soundex_table = "01230120022455012623010202";
#define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A'] #define soundex_code(letter) soundex_table[toupper((unsigned char) (letter)) - 'A']
@ -98,7 +99,7 @@ soundex(const char *instr, char *outstr)
#ifdef SOUNDEX_TEST #ifdef SOUNDEX_TEST
int int
main (int argc, char *argv[]) main(int argc, char *argv[])
{ {
if (argc < 2) if (argc < 2)
{ {
@ -107,11 +108,12 @@ main (int argc, char *argv[])
} }
else else
{ {
char output[SOUNDEX_LEN + 1]; char output[SOUNDEX_LEN + 1];
soundex(argv[1], output); soundex(argv[1], output);
printf("soundex(%s) = %s\n", argv[1], output); printf("soundex(%s) = %s\n", argv[1], output);
return 0; return 0;
} }
} }
#endif /* SOUNDEX_TEST */
#endif /* SOUNDEX_TEST */

View File

@ -10,7 +10,7 @@
#include "commands/trigger.h" /* -"- and triggers */ #include "commands/trigger.h" /* -"- and triggers */
#include "miscadmin.h" /* for GetUserName() */ #include "miscadmin.h" /* for GetUserName() */
extern Datum insert_username(PG_FUNCTION_ARGS); extern Datum insert_username(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(insert_username); PG_FUNCTION_INFO_V1(insert_username);
@ -65,7 +65,7 @@ insert_username(PG_FUNCTION_ARGS)
/* create fields containing name */ /* create fields containing name */
newval = DirectFunctionCall1(textin, newval = DirectFunctionCall1(textin,
CStringGetDatum(GetUserName(GetUserId()))); CStringGetDatum(GetUserName(GetUserId())));
/* construct new tuple */ /* construct new tuple */
rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL); rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL);

View File

@ -15,7 +15,7 @@ OH, me, I'm Terry Mackintosh <terry@terrym.com>
#include "executor/spi.h" /* this is what you need to work with SPI */ #include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */ #include "commands/trigger.h" /* -"- and triggers */
extern Datum moddatetime(PG_FUNCTION_ARGS); extern Datum moddatetime(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(moddatetime); PG_FUNCTION_INFO_V1(moddatetime);

View File

@ -373,7 +373,7 @@ set_timetravel(PG_FUNCTION_ARGS)
else else
TTOff = realloc(TTOff, (nTTOff + 1) * sizeof(char *)); TTOff = realloc(TTOff, (nTTOff + 1) * sizeof(char *));
s = rname = DatumGetCString(DirectFunctionCall1(nameout, s = rname = DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(relname))); NameGetDatum(relname)));
d = TTOff[nTTOff] = malloc(strlen(rname) + 1); d = TTOff[nTTOff] = malloc(strlen(rname) + 1);
while (*s) while (*s)
*d++ = tolower((unsigned char) *s++); *d++ = tolower((unsigned char) *s++);

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.57 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.58 2001/03/22 03:59:11 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -51,7 +51,7 @@ getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
*typOutput = pt->typoutput; *typOutput = pt->typoutput;
*typElem = pt->typelem; *typElem = pt->typelem;
*typIsVarlena = (! pt->typbyval) && (pt->typlen == -1); *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
ReleaseSysCache(typeTuple); ReleaseSysCache(typeTuple);
return OidIsValid(*typOutput); return OidIsValid(*typOutput);
} }
@ -200,9 +200,10 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
continue; continue;
if (OidIsValid(thisState->typoutput)) if (OidIsValid(thisState->typoutput))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to avoid * If we have a toasted datum, forcibly detoast it here to
* memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
*/ */
if (thisState->typisvarlena) if (thisState->typisvarlena)
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr)); attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
@ -210,9 +211,9 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
attr = origattr; attr = origattr;
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo, outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
attr, attr,
ObjectIdGetDatum(thisState->typelem), ObjectIdGetDatum(thisState->typelem),
Int32GetDatum(typeinfo->attrs[i]->atttypmod))); Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
pq_sendcountedtext(&buf, outputstr, strlen(outputstr)); pq_sendcountedtext(&buf, outputstr, strlen(outputstr));
@ -308,9 +309,10 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid, if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
&typoutput, &typelem, &typisvarlena)) &typoutput, &typelem, &typisvarlena))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to avoid * If we have a toasted datum, forcibly detoast it here to
* memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
*/ */
if (typisvarlena) if (typisvarlena)
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr)); attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
@ -318,9 +320,9 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
attr = origattr; attr = origattr;
value = DatumGetCString(OidFunctionCall3(typoutput, value = DatumGetCString(OidFunctionCall3(typoutput,
attr, attr,
ObjectIdGetDatum(typelem), ObjectIdGetDatum(typelem),
Int32GetDatum(typeinfo->attrs[i]->atttypmod))); Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
printatt((unsigned) i + 1, typeinfo->attrs[i], value); printatt((unsigned) i + 1, typeinfo->attrs[i], value);
@ -405,6 +407,7 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
/* send # of bytes, and opaque data */ /* send # of bytes, and opaque data */
if (thisState->typisvarlena) if (thisState->typisvarlena)
{ {
/* /*
* If we have a toasted datum, must detoast before sending. * If we have a toasted datum, must detoast before sending.
*/ */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -32,8 +32,8 @@ static bool gistindex_keytest(IndexTuple tuple, TupleDesc tupdesc,
Datum Datum
gistgettuple(PG_FUNCTION_ARGS) gistgettuple(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
RetrieveIndexResult res; RetrieveIndexResult res;
/* if we have it cached in the scan desc, just return the value */ /* if we have it cached in the scan desc, just return the value */

View File

@ -72,9 +72,9 @@ gistbeginscan(PG_FUNCTION_ARGS)
Datum Datum
gistrescan(PG_FUNCTION_ARGS) gistrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
ScanKey key = (ScanKey) PG_GETARG_POINTER(2); ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
GISTScanOpaque p; GISTScanOpaque p;
int i; int i;
@ -160,7 +160,7 @@ gistrescan(PG_FUNCTION_ARGS)
Datum Datum
gistmarkpos(PG_FUNCTION_ARGS) gistmarkpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque p; GISTScanOpaque p;
GISTSTACK *o, GISTSTACK *o,
*n, *n,
@ -196,7 +196,7 @@ gistmarkpos(PG_FUNCTION_ARGS)
Datum Datum
gistrestrpos(PG_FUNCTION_ARGS) gistrestrpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque p; GISTScanOpaque p;
GISTSTACK *o, GISTSTACK *o,
*n, *n,
@ -232,8 +232,8 @@ gistrestrpos(PG_FUNCTION_ARGS)
Datum Datum
gistendscan(PG_FUNCTION_ARGS) gistendscan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque p; GISTScanOpaque p;
p = (GISTScanOpaque) s->opaque; p = (GISTScanOpaque) s->opaque;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.49 2001/02/22 21:48:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.50 2001/03/22 03:59:12 momjian Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -41,12 +41,14 @@ bool BuildingHash = false;
Datum Datum
hashbuild(PG_FUNCTION_ARGS) hashbuild(PG_FUNCTION_ARGS)
{ {
Relation heap = (Relation) PG_GETARG_POINTER(0); Relation heap = (Relation) PG_GETARG_POINTER(0);
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -59,9 +61,11 @@ hashbuild(PG_FUNCTION_ARGS)
nitups; nitups;
HashItem hitem; HashItem hitem;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -117,6 +121,7 @@ hashbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -191,9 +196,7 @@ hashbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -241,12 +244,14 @@ hashbuild(PG_FUNCTION_ARGS)
Datum Datum
hashinsert(PG_FUNCTION_ARGS) hashinsert(PG_FUNCTION_ARGS)
{ {
Relation rel = (Relation) PG_GETARG_POINTER(0); Relation rel = (Relation) PG_GETARG_POINTER(0);
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
InsertIndexResult res; InsertIndexResult res;
HashItem hitem; HashItem hitem;
@ -276,8 +281,8 @@ hashinsert(PG_FUNCTION_ARGS)
Datum Datum
hashgettuple(PG_FUNCTION_ARGS) hashgettuple(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
RetrieveIndexResult res; RetrieveIndexResult res;
/* /*
@ -326,11 +331,13 @@ hashbeginscan(PG_FUNCTION_ARGS)
Datum Datum
hashrescan(PG_FUNCTION_ARGS) hashrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;
HashScanOpaque so; HashScanOpaque so;
@ -367,7 +374,7 @@ hashrescan(PG_FUNCTION_ARGS)
Datum Datum
hashendscan(PG_FUNCTION_ARGS) hashendscan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
HashScanOpaque so; HashScanOpaque so;
@ -405,7 +412,7 @@ hashendscan(PG_FUNCTION_ARGS)
Datum Datum
hashmarkpos(PG_FUNCTION_ARGS) hashmarkpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
HashScanOpaque so; HashScanOpaque so;
@ -437,7 +444,7 @@ hashmarkpos(PG_FUNCTION_ARGS)
Datum Datum
hashrestrpos(PG_FUNCTION_ARGS) hashrestrpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
HashScanOpaque so; HashScanOpaque so;
@ -468,8 +475,8 @@ hashrestrpos(PG_FUNCTION_ARGS)
Datum Datum
hashdelete(PG_FUNCTION_ARGS) hashdelete(PG_FUNCTION_ARGS)
{ {
Relation rel = (Relation) PG_GETARG_POINTER(0); Relation rel = (Relation) PG_GETARG_POINTER(0);
ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1); ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1);
/* adjust any active scans that will be affected by this deletion */ /* adjust any active scans that will be affected by this deletion */
_hash_adjscans(rel, tid); _hash_adjscans(rel, tid);
@ -491,8 +498,8 @@ hash_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
elog(STOP, "hash_undo: unimplemented"); elog(STOP, "hash_undo: unimplemented");
} }
void void
hash_desc(char *buf, uint8 xl_info, char* rec) hash_desc(char *buf, uint8 xl_info, char *rec)
{ {
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.29 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.30 2001/03/22 03:59:13 momjian Exp $
* *
* NOTES * NOTES
* These functions are stored in pg_amproc. For each operator class * These functions are stored in pg_amproc. For each operator class
@ -25,32 +25,32 @@
Datum Datum
hashchar(PG_FUNCTION_ARGS) hashchar(PG_FUNCTION_ARGS)
{ {
PG_RETURN_UINT32(~ ((uint32) PG_GETARG_CHAR(0))); PG_RETURN_UINT32(~((uint32) PG_GETARG_CHAR(0)));
} }
Datum Datum
hashint2(PG_FUNCTION_ARGS) hashint2(PG_FUNCTION_ARGS)
{ {
PG_RETURN_UINT32(~ ((uint32) PG_GETARG_INT16(0))); PG_RETURN_UINT32(~((uint32) PG_GETARG_INT16(0)));
} }
Datum Datum
hashint4(PG_FUNCTION_ARGS) hashint4(PG_FUNCTION_ARGS)
{ {
PG_RETURN_UINT32(~ PG_GETARG_UINT32(0)); PG_RETURN_UINT32(~PG_GETARG_UINT32(0));
} }
Datum Datum
hashint8(PG_FUNCTION_ARGS) hashint8(PG_FUNCTION_ARGS)
{ {
/* we just use the low 32 bits... */ /* we just use the low 32 bits... */
PG_RETURN_UINT32(~ ((uint32) PG_GETARG_INT64(0))); PG_RETURN_UINT32(~((uint32) PG_GETARG_INT64(0)));
} }
Datum Datum
hashoid(PG_FUNCTION_ARGS) hashoid(PG_FUNCTION_ARGS)
{ {
PG_RETURN_UINT32(~ ((uint32) PG_GETARG_OID(0))); PG_RETURN_UINT32(~((uint32) PG_GETARG_OID(0)));
} }
Datum Datum
@ -93,7 +93,7 @@ hashint2vector(PG_FUNCTION_ARGS)
Datum Datum
hashname(PG_FUNCTION_ARGS) hashname(PG_FUNCTION_ARGS)
{ {
char *key = NameStr(* PG_GETARG_NAME(0)); char *key = NameStr(*PG_GETARG_NAME(0));
return hash_any((char *) key, NAMEDATALEN); return hash_any((char *) key, NAMEDATALEN);
} }

View File

@ -8,14 +8,14 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.110 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.111 2001/03/22 03:59:13 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* heapgettup - fetch next heap tuple from a scan * heapgettup - fetch next heap tuple from a scan
* heap_open - open a heap relation by relationId * heap_open - open a heap relation by relationId
* heap_openr - open a heap relation by name * heap_openr - open a heap relation by name
* heap_open[r]_nofail - same, but return NULL on failure instead of elog * heap_open[r]_nofail - same, but return NULL on failure instead of elog
* heap_close - close a heap relation * heap_close - close a heap relation
* heap_beginscan - begin relation scan * heap_beginscan - begin relation scan
* heap_rescan - restart a relation scan * heap_rescan - restart a relation scan
@ -88,16 +88,16 @@
#include "access/xlogutils.h" #include "access/xlogutils.h"
XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from, XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup); Buffer newbuf, HeapTuple newtup);
XLogRecPtr log_heap_clean(Relation reln, Buffer buffer, XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
char *unused, int unlen); char *unused, int unlen);
/* comments are in heap_update */ /* comments are in heap_update */
static xl_heaptid _locked_tuple_; static xl_heaptid _locked_tuple_;
static void _heap_unlock_tuple(void *data); static void _heap_unlock_tuple(void *data);
static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf, static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
ItemPointerData from, Buffer newbuf, HeapTuple newtup, bool move); ItemPointerData from, Buffer newbuf, HeapTuple newtup, bool move);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -249,7 +249,7 @@ heapgettup(Relation relation,
OffsetNumber lineoff; OffsetNumber lineoff;
int linesleft; int linesleft;
ItemPointer tid = (tuple->t_data == NULL) ? ItemPointer tid = (tuple->t_data == NULL) ?
(ItemPointer) NULL : &(tuple->t_self); (ItemPointer) NULL : &(tuple->t_self);
/* ---------------- /* ----------------
* increment access statistics * increment access statistics
@ -286,7 +286,7 @@ heapgettup(Relation relation,
if (!ItemPointerIsValid(tid)) if (!ItemPointerIsValid(tid))
Assert(!PointerIsValid(tid)); Assert(!PointerIsValid(tid));
tuple->t_tableOid = relation->rd_id; tuple->t_tableOid = relation->rd_id;
/* ---------------- /* ----------------
@ -538,9 +538,9 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
( (
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ? (tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ?
( (
fetchatt((tupleDesc)->attrs[(attnum) - 1], fetchatt((tupleDesc)->attrs[(attnum) - 1],
(char *) (tup)->t_data + (tup)->t_data->t_hoff + (char *) (tup)->t_data + (tup)->t_data->t_hoff +
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff) (tupleDesc)->attrs[(attnum) - 1]->attcacheoff)
) )
: :
nocachegetattr((tup), (attnum), (tupleDesc), (isnull)) nocachegetattr((tup), (attnum), (tupleDesc), (isnull))
@ -564,7 +564,8 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
) )
); );
} }
#endif /* defined(DISABLE_COMPLEX_MACRO)*/
#endif /* defined(DISABLE_COMPLEX_MACRO) */
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -791,8 +792,8 @@ heap_beginscan(Relation relation,
scan->rs_nkeys = (short) nkeys; scan->rs_nkeys = (short) nkeys;
/* /*
* we do this here instead of in initscan() because heap_rescan * we do this here instead of in initscan() because heap_rescan also
* also calls initscan() and we don't want to allocate memory again * calls initscan() and we don't want to allocate memory again
*/ */
if (nkeys) if (nkeys)
scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
@ -1316,7 +1317,7 @@ heap_get_latest_tid(Relation relation,
Oid Oid
heap_insert(Relation relation, HeapTuple tup) heap_insert(Relation relation, HeapTuple tup)
{ {
Buffer buffer; Buffer buffer;
/* increment access statistics */ /* increment access statistics */
IncrHeapAccessStat(local_insert); IncrHeapAccessStat(local_insert);
@ -1350,7 +1351,7 @@ heap_insert(Relation relation, HeapTuple tup)
* toasted attributes from some other relation, invoke the toaster. * toasted attributes from some other relation, invoke the toaster.
* ---------- * ----------
*/ */
if (HeapTupleHasExtended(tup) || if (HeapTupleHasExtended(tup) ||
(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD)) (MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
heap_tuple_toast_attrs(relation, tup, NULL); heap_tuple_toast_attrs(relation, tup, NULL);
#endif #endif
@ -1364,17 +1365,17 @@ heap_insert(Relation relation, HeapTuple tup)
/* XLOG stuff */ /* XLOG stuff */
{ {
xl_heap_insert xlrec; xl_heap_insert xlrec;
xl_heap_header xlhdr; xl_heap_header xlhdr;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[3]; XLogRecData rdata[3];
Page page = BufferGetPage(buffer); Page page = BufferGetPage(buffer);
uint8 info = XLOG_HEAP_INSERT; uint8 info = XLOG_HEAP_INSERT;
xlrec.target.node = relation->rd_node; xlrec.target.node = relation->rd_node;
xlrec.target.tid = tup->t_self; xlrec.target.tid = tup->t_self;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = SizeOfHeapInsert; rdata[0].len = SizeOfHeapInsert;
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -1383,12 +1384,12 @@ heap_insert(Relation relation, HeapTuple tup)
xlhdr.t_hoff = tup->t_data->t_hoff; xlhdr.t_hoff = tup->t_data->t_hoff;
xlhdr.mask = tup->t_data->t_infomask; xlhdr.mask = tup->t_data->t_infomask;
rdata[1].buffer = buffer; rdata[1].buffer = buffer;
rdata[1].data = (char*)&xlhdr; rdata[1].data = (char *) &xlhdr;
rdata[1].len = SizeOfHeapHeader; rdata[1].len = SizeOfHeapHeader;
rdata[1].next = &(rdata[2]); rdata[1].next = &(rdata[2]);
rdata[2].buffer = buffer; rdata[2].buffer = buffer;
rdata[2].data = (char*) tup->t_data + offsetof(HeapTupleHeaderData, t_bits); rdata[2].data = (char *) tup->t_data + offsetof(HeapTupleHeaderData, t_bits);
rdata[2].len = tup->t_len - offsetof(HeapTupleHeaderData, t_bits); rdata[2].len = tup->t_len - offsetof(HeapTupleHeaderData, t_bits);
rdata[2].next = NULL; rdata[2].next = NULL;
@ -1411,10 +1412,10 @@ heap_insert(Relation relation, HeapTuple tup)
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If tuple is cachable, mark it for rollback from the caches * If tuple is cachable, mark it for rollback from the caches in case
* in case we abort. Note it is OK to do this after WriteBuffer * we abort. Note it is OK to do this after WriteBuffer releases the
* releases the buffer, because the "tup" data structure is all * buffer, because the "tup" data structure is all in local memory,
* in local memory, not in the shared buffer. * not in the shared buffer.
*/ */
RelationMark4RollbackHeapTuple(relation, tup); RelationMark4RollbackHeapTuple(relation, tup);
@ -1513,14 +1514,14 @@ l1:
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
/* XLOG stuff */ /* XLOG stuff */
{ {
xl_heap_delete xlrec; xl_heap_delete xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
xlrec.target.node = relation->rd_node; xlrec.target.node = relation->rd_node;
xlrec.target.tid = tp.t_self; xlrec.target.tid = tp.t_self;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = SizeOfHeapDelete; rdata[0].len = SizeOfHeapDelete;
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -1551,9 +1552,10 @@ l1:
#endif #endif
/* /*
* Mark tuple for invalidation from system caches at next command boundary. * Mark tuple for invalidation from system caches at next command
* We have to do this before WriteBuffer because we need to look at the * boundary. We have to do this before WriteBuffer because we need to
* contents of the tuple, so we need to hold our refcount on the buffer. * look at the contents of the tuple, so we need to hold our refcount
* on the buffer.
*/ */
RelationInvalidateHeapTuple(relation, &tp); RelationInvalidateHeapTuple(relation, &tp);
@ -1567,7 +1569,7 @@ l1:
* *
* This routine may be used to delete a tuple when concurrent updates of * This routine may be used to delete a tuple when concurrent updates of
* the target tuple are not expected (for example, because we have a lock * the target tuple are not expected (for example, because we have a lock
* on the relation associated with the tuple). Any failure is reported * on the relation associated with the tuple). Any failure is reported
* via elog(). * via elog().
*/ */
void void
@ -1636,6 +1638,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp); oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
oldtup.t_len = ItemIdGetLength(lp); oldtup.t_len = ItemIdGetLength(lp);
oldtup.t_self = *otid; oldtup.t_self = *otid;
/* /*
* Note: beyond this point, use oldtup not otid to refer to old tuple. * Note: beyond this point, use oldtup not otid to refer to old tuple.
* otid may very well point at newtup->t_self, which we will overwrite * otid may very well point at newtup->t_self, which we will overwrite
@ -1701,23 +1704,24 @@ l2:
/* /*
* If the toaster needs to be activated, OR if the new tuple will not * If the toaster needs to be activated, OR if the new tuple will not
* fit on the same page as the old, then we need to release the context * fit on the same page as the old, then we need to release the
* lock (but not the pin!) on the old tuple's buffer while we are off * context lock (but not the pin!) on the old tuple's buffer while we
* doing TOAST and/or table-file-extension work. We must mark the old * are off doing TOAST and/or table-file-extension work. We must mark
* tuple to show that it's already being updated, else other processes * the old tuple to show that it's already being updated, else other
* may try to update it themselves. To avoid second XLOG log record, * processes may try to update it themselves. To avoid second XLOG log
* we use xact mgr hook to unlock old tuple without reading log if xact * record, we use xact mgr hook to unlock old tuple without reading
* will abort before update is logged. In the event of crash prio logging, * log if xact will abort before update is logged. In the event of
* TQUAL routines will see HEAP_XMAX_UNLOGGED flag... * crash prio logging, TQUAL routines will see HEAP_XMAX_UNLOGGED
* flag...
* *
* NOTE: this trick is useless currently but saved for future * NOTE: this trick is useless currently but saved for future when we'll
* when we'll implement UNDO and will re-use transaction IDs * implement UNDO and will re-use transaction IDs after postmaster
* after postmaster startup. * startup.
* *
* We need to invoke the toaster if there are already any toasted values * We need to invoke the toaster if there are already any toasted values
* present, or if the new tuple is over-threshold. * present, or if the new tuple is over-threshold.
*/ */
need_toast = (HeapTupleHasExtended(&oldtup) || need_toast = (HeapTupleHasExtended(&oldtup) ||
HeapTupleHasExtended(newtup) || HeapTupleHasExtended(newtup) ||
(MAXALIGN(newtup->t_len) > TOAST_TUPLE_THRESHOLD)); (MAXALIGN(newtup->t_len) > TOAST_TUPLE_THRESHOLD));
@ -1726,7 +1730,7 @@ l2:
{ {
_locked_tuple_.node = relation->rd_node; _locked_tuple_.node = relation->rd_node;
_locked_tuple_.tid = oldtup.t_self; _locked_tuple_.tid = oldtup.t_self;
XactPushRollback(_heap_unlock_tuple, (void*) &_locked_tuple_); XactPushRollback(_heap_unlock_tuple, (void *) &_locked_tuple_);
TransactionIdStore(GetCurrentTransactionId(), TransactionIdStore(GetCurrentTransactionId(),
&(oldtup.t_data->t_xmax)); &(oldtup.t_data->t_xmax));
@ -1762,7 +1766,7 @@ l2:
/* NO ELOG(ERROR) from here till changes are logged */ /* NO ELOG(ERROR) from here till changes are logged */
START_CRIT_SECTION(); START_CRIT_SECTION();
RelationPutHeapTuple(relation, newbuf, newtup); /* insert new tuple */ RelationPutHeapTuple(relation, newbuf, newtup); /* insert new tuple */
if (already_marked) if (already_marked)
{ {
@ -1784,7 +1788,7 @@ l2:
/* XLOG stuff */ /* XLOG stuff */
{ {
XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self, XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self,
newbuf, newtup, false); newbuf, newtup, false);
if (newbuf != buffer) if (newbuf != buffer)
@ -1814,10 +1818,10 @@ l2:
WriteBuffer(buffer); WriteBuffer(buffer);
/* /*
* If new tuple is cachable, mark it for rollback from the caches * If new tuple is cachable, mark it for rollback from the caches in
* in case we abort. Note it is OK to do this after WriteBuffer * case we abort. Note it is OK to do this after WriteBuffer releases
* releases the buffer, because the "newtup" data structure is all * the buffer, because the "newtup" data structure is all in local
* in local memory, not in the shared buffer. * memory, not in the shared buffer.
*/ */
RelationMark4RollbackHeapTuple(relation, newtup); RelationMark4RollbackHeapTuple(relation, newtup);
@ -1829,7 +1833,7 @@ l2:
* *
* This routine may be used to update a tuple when concurrent updates of * This routine may be used to update a tuple when concurrent updates of
* the target tuple are not expected (for example, because we have a lock * the target tuple are not expected (for example, because we have a lock
* on the relation associated with the tuple). Any failure is reported * on the relation associated with the tuple). Any failure is reported
* via elog(). * via elog().
*/ */
void void
@ -2129,14 +2133,14 @@ heap_restrpos(HeapScanDesc scan)
XLogRecPtr XLogRecPtr
log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen) log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen)
{ {
xl_heap_clean xlrec; xl_heap_clean xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[3]; XLogRecData rdata[3];
xlrec.node = reln->rd_node; xlrec.node = reln->rd_node;
xlrec.block = BufferGetBlockNumber(buffer); xlrec.block = BufferGetBlockNumber(buffer);
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = SizeOfHeapClean; rdata[0].len = SizeOfHeapClean;
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -2157,27 +2161,27 @@ log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen)
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CLEAN, rdata); recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CLEAN, rdata);
return(recptr); return (recptr);
} }
static XLogRecPtr static XLogRecPtr
log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup, bool move) Buffer newbuf, HeapTuple newtup, bool move)
{ {
char tbuf[MAXALIGN(sizeof(xl_heap_header)) + 2 * sizeof(TransactionId)]; char tbuf[MAXALIGN(sizeof(xl_heap_header)) + 2 * sizeof(TransactionId)];
xl_heap_update xlrec; xl_heap_update xlrec;
xl_heap_header *xlhdr = (xl_heap_header*) tbuf; xl_heap_header *xlhdr = (xl_heap_header *) tbuf;
int hsize = SizeOfHeapHeader; int hsize = SizeOfHeapHeader;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[4]; XLogRecData rdata[4];
Page page = BufferGetPage(newbuf); Page page = BufferGetPage(newbuf);
uint8 info = (move) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE; uint8 info = (move) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE;
xlrec.target.node = reln->rd_node; xlrec.target.node = reln->rd_node;
xlrec.target.tid = from; xlrec.target.tid = from;
xlrec.newtid = newtup->t_self; xlrec.newtid = newtup->t_self;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = SizeOfHeapUpdate; rdata[0].len = SizeOfHeapUpdate;
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -2190,9 +2194,9 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
xlhdr->t_natts = newtup->t_data->t_natts; xlhdr->t_natts = newtup->t_data->t_natts;
xlhdr->t_hoff = newtup->t_data->t_hoff; xlhdr->t_hoff = newtup->t_data->t_hoff;
xlhdr->mask = newtup->t_data->t_infomask; xlhdr->mask = newtup->t_data->t_infomask;
if (move) /* remember xmin & xmax */ if (move) /* remember xmin & xmax */
{ {
TransactionId xmax; TransactionId xmax;
if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID || if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID ||
newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE) newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
@ -2200,17 +2204,17 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
else else
xmax = newtup->t_data->t_xmax; xmax = newtup->t_data->t_xmax;
memcpy(tbuf + hsize, &xmax, sizeof(TransactionId)); memcpy(tbuf + hsize, &xmax, sizeof(TransactionId));
memcpy(tbuf + hsize + sizeof(TransactionId), memcpy(tbuf + hsize + sizeof(TransactionId),
&(newtup->t_data->t_xmin), sizeof(TransactionId)); &(newtup->t_data->t_xmin), sizeof(TransactionId));
hsize += (2 * sizeof(TransactionId)); hsize += (2 * sizeof(TransactionId));
} }
rdata[2].buffer = newbuf; rdata[2].buffer = newbuf;
rdata[2].data = (char*)xlhdr; rdata[2].data = (char *) xlhdr;
rdata[2].len = hsize; rdata[2].len = hsize;
rdata[2].next = &(rdata[3]); rdata[2].next = &(rdata[3]);
rdata[3].buffer = newbuf; rdata[3].buffer = newbuf;
rdata[3].data = (char*) newtup->t_data + offsetof(HeapTupleHeaderData, t_bits); rdata[3].data = (char *) newtup->t_data + offsetof(HeapTupleHeaderData, t_bits);
rdata[3].len = newtup->t_len - offsetof(HeapTupleHeaderData, t_bits); rdata[3].len = newtup->t_len - offsetof(HeapTupleHeaderData, t_bits);
rdata[3].next = NULL; rdata[3].next = NULL;
@ -2224,23 +2228,23 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
recptr = XLogInsert(RM_HEAP_ID, info, rdata); recptr = XLogInsert(RM_HEAP_ID, info, rdata);
return(recptr); return (recptr);
} }
XLogRecPtr XLogRecPtr
log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from, log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup) Buffer newbuf, HeapTuple newtup)
{ {
return(log_heap_update(reln, oldbuf, from, newbuf, newtup, true)); return (log_heap_update(reln, oldbuf, from, newbuf, newtup, true));
} }
static void static void
heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record) heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_clean *xlrec = (xl_heap_clean*) XLogRecGetData(record); xl_heap_clean *xlrec = (xl_heap_clean *) XLogRecGetData(record);
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1)) if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
return; return;
@ -2266,15 +2270,15 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (record->xl_len > SizeOfHeapClean) if (record->xl_len > SizeOfHeapClean)
{ {
char unbuf[BLCKSZ]; char unbuf[BLCKSZ];
OffsetNumber *unused = (OffsetNumber*)unbuf; OffsetNumber *unused = (OffsetNumber *) unbuf;
char *unend; char *unend;
ItemId lp; ItemId lp;
memcpy(unbuf, (char*)xlrec + SizeOfHeapClean, record->xl_len - SizeOfHeapClean); memcpy(unbuf, (char *) xlrec + SizeOfHeapClean, record->xl_len - SizeOfHeapClean);
unend = unbuf + (record->xl_len - SizeOfHeapClean); unend = unbuf + (record->xl_len - SizeOfHeapClean);
while((char*)unused < unend) while ((char *) unused < unend)
{ {
lp = ((PageHeader) page)->pd_linp + *unused; lp = ((PageHeader) page)->pd_linp + *unused;
lp->lp_flags &= ~LP_USED; lp->lp_flags &= ~LP_USED;
@ -2289,13 +2293,13 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
static void static void
heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record) heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_delete *xlrec = (xl_heap_delete*) XLogRecGetData(record); xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record);
Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node); Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp = NULL;
HeapTupleHeader htup; HeapTupleHeader htup;
if (redo && (record->xl_info & XLR_BKP_BLOCK_1)) if (redo && (record->xl_info & XLR_BKP_BLOCK_1))
return; return;
@ -2303,7 +2307,7 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return; return;
buffer = XLogReadBuffer(false, reln, buffer = XLogReadBuffer(false, reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "heap_delete_%sdo: no block", (redo) ? "re" : "un"); elog(STOP, "heap_delete_%sdo: no block", (redo) ? "re" : "un");
@ -2320,7 +2324,8 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
return; return;
} }
} }
else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_delete_undo: bad page LSN"); elog(STOP, "heap_delete_undo: bad page LSN");
offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid)); offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));
@ -2337,7 +2342,7 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
htup->t_xmax = record->xl_xid; htup->t_xmax = record->xl_xid;
htup->t_cmax = FirstCommandId; htup->t_cmax = FirstCommandId;
htup->t_infomask &= ~(HEAP_XMAX_COMMITTED | htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
@ -2350,12 +2355,12 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
static void static void
heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record) heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_insert *xlrec = (xl_heap_insert*) XLogRecGetData(record); xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record);
Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node); Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
HeapTupleHeader htup; HeapTupleHeader htup;
if (redo && (record->xl_info & XLR_BKP_BLOCK_1)) if (redo && (record->xl_info & XLR_BKP_BLOCK_1))
return; return;
@ -2363,7 +2368,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return; return;
buffer = XLogReadBuffer((redo) ? true : false, reln, buffer = XLogReadBuffer((redo) ? true : false, reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
@ -2375,9 +2380,9 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (redo) if (redo)
{ {
char tbuf[MaxTupleSize]; char tbuf[MaxTupleSize];
xl_heap_header xlhdr; xl_heap_header xlhdr;
uint32 newlen; uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE) if (record->xl_info & XLOG_HEAP_INIT_PAGE)
{ {
@ -2396,9 +2401,9 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
elog(STOP, "heap_insert_redo: invalid max offset number"); elog(STOP, "heap_insert_redo: invalid max offset number");
newlen = record->xl_len - SizeOfHeapInsert - SizeOfHeapHeader; newlen = record->xl_len - SizeOfHeapInsert - SizeOfHeapHeader;
memcpy((char*)&xlhdr, (char*)xlrec + SizeOfHeapInsert, SizeOfHeapHeader); memcpy((char *) &xlhdr, (char *) xlrec + SizeOfHeapInsert, SizeOfHeapHeader);
memcpy(tbuf + offsetof(HeapTupleHeaderData, t_bits), memcpy(tbuf + offsetof(HeapTupleHeaderData, t_bits),
(char*)xlrec + SizeOfHeapInsert + SizeOfHeapHeader, newlen); (char *) xlrec + SizeOfHeapInsert + SizeOfHeapHeader, newlen);
newlen += offsetof(HeapTupleHeaderData, t_bits); newlen += offsetof(HeapTupleHeaderData, t_bits);
htup = (HeapTupleHeader) tbuf; htup = (HeapTupleHeader) tbuf;
htup->t_oid = xlhdr.t_oid; htup->t_oid = xlhdr.t_oid;
@ -2408,19 +2413,20 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
htup->t_cmin = FirstCommandId; htup->t_cmin = FirstCommandId;
htup->t_xmax = htup->t_cmax = 0; htup->t_xmax = htup->t_cmax = 0;
htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask; htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
offnum = PageAddItem(page, (Item)htup, newlen, offnum, offnum = PageAddItem(page, (Item) htup, newlen, offnum,
LP_USED | OverwritePageMode); LP_USED | OverwritePageMode);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(STOP, "heap_insert_redo: failed to add tuple"); elog(STOP, "heap_insert_redo: failed to add tuple");
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); /* prev sui */ PageSetSUI(page, ThisStartUpID); /* prev sui */
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
return; return;
} }
/* undo insert */ /* undo insert */
if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_insert_undo: bad page LSN"); elog(STOP, "heap_insert_undo: bad page LSN");
elog(STOP, "heap_insert_undo: unimplemented"); elog(STOP, "heap_insert_undo: unimplemented");
@ -2432,16 +2438,16 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
static void static void
heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move) heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
{ {
xl_heap_update *xlrec = (xl_heap_update*) XLogRecGetData(record); xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record);
Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node); Relation reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);
Buffer buffer; Buffer buffer;
bool samepage = bool samepage =
(ItemPointerGetBlockNumber(&(xlrec->newtid)) == (ItemPointerGetBlockNumber(&(xlrec->newtid)) ==
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp = NULL;
HeapTupleHeader htup; HeapTupleHeader htup;
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return; return;
@ -2451,7 +2457,7 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
/* Deal with old tuple version */ /* Deal with old tuple version */
buffer = XLogReadBuffer(false, reln, buffer = XLogReadBuffer(false, reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "heap_update_%sdo: no block", (redo) ? "re" : "un"); elog(STOP, "heap_update_%sdo: no block", (redo) ? "re" : "un");
@ -2470,7 +2476,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
goto newt; goto newt;
} }
} }
else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ else if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_update_undo: bad old tuple page LSN"); elog(STOP, "heap_update_undo: bad old tuple page LSN");
offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid)); offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));
@ -2487,7 +2494,7 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
if (move) if (move)
{ {
TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin)); TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin));
htup->t_infomask &= htup->t_infomask &=
~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN); ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
htup->t_infomask |= HEAP_MOVED_OFF; htup->t_infomask |= HEAP_MOVED_OFF;
} }
@ -2496,7 +2503,7 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
htup->t_xmax = record->xl_xid; htup->t_xmax = record->xl_xid;
htup->t_cmax = FirstCommandId; htup->t_cmax = FirstCommandId;
htup->t_infomask &= ~(HEAP_XMAX_COMMITTED | htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
} }
if (samepage) if (samepage)
goto newsame; goto newsame;
@ -2514,11 +2521,11 @@ newt:;
if (redo && if (redo &&
((record->xl_info & XLR_BKP_BLOCK_2) || ((record->xl_info & XLR_BKP_BLOCK_2) ||
((record->xl_info & XLR_BKP_BLOCK_1) && samepage))) ((record->xl_info & XLR_BKP_BLOCK_1) && samepage)))
return; return;
buffer = XLogReadBuffer((redo) ? true : false, reln, buffer = XLogReadBuffer((redo) ? true : false, reln,
ItemPointerGetBlockNumber(&(xlrec->newtid))); ItemPointerGetBlockNumber(&(xlrec->newtid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
@ -2531,10 +2538,10 @@ newsame:;
if (redo) if (redo)
{ {
char tbuf[MaxTupleSize]; char tbuf[MaxTupleSize];
xl_heap_header xlhdr; xl_heap_header xlhdr;
int hsize; int hsize;
uint32 newlen; uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE) if (record->xl_info & XLOG_HEAP_INIT_PAGE)
{ {
@ -2557,9 +2564,9 @@ newsame:;
hsize += (2 * sizeof(TransactionId)); hsize += (2 * sizeof(TransactionId));
newlen = record->xl_len - hsize; newlen = record->xl_len - hsize;
memcpy((char*)&xlhdr, (char*)xlrec + SizeOfHeapUpdate, SizeOfHeapHeader); memcpy((char *) &xlhdr, (char *) xlrec + SizeOfHeapUpdate, SizeOfHeapHeader);
memcpy(tbuf + offsetof(HeapTupleHeaderData, t_bits), memcpy(tbuf + offsetof(HeapTupleHeaderData, t_bits),
(char*)xlrec + hsize, newlen); (char *) xlrec + hsize, newlen);
newlen += offsetof(HeapTupleHeaderData, t_bits); newlen += offsetof(HeapTupleHeaderData, t_bits);
htup = (HeapTupleHeader) tbuf; htup = (HeapTupleHeader) tbuf;
htup->t_oid = xlhdr.t_oid; htup->t_oid = xlhdr.t_oid;
@ -2568,13 +2575,13 @@ newsame:;
if (move) if (move)
{ {
hsize = SizeOfHeapUpdate + SizeOfHeapHeader; hsize = SizeOfHeapUpdate + SizeOfHeapHeader;
memcpy(&(htup->t_xmax), (char*)xlrec + hsize, sizeof(TransactionId)); memcpy(&(htup->t_xmax), (char *) xlrec + hsize, sizeof(TransactionId));
memcpy(&(htup->t_xmin), memcpy(&(htup->t_xmin),
(char*)xlrec + hsize + sizeof(TransactionId), sizeof(TransactionId)); (char *) xlrec + hsize + sizeof(TransactionId), sizeof(TransactionId));
TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin)); TransactionIdStore(record->xl_xid, (TransactionId *) &(htup->t_cmin));
htup->t_infomask = xlhdr.mask; htup->t_infomask = xlhdr.mask;
htup->t_infomask &= ~(HEAP_XMIN_COMMITTED | htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
HEAP_XMIN_INVALID | HEAP_MOVED_OFF); HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
htup->t_infomask |= HEAP_MOVED_IN; htup->t_infomask |= HEAP_MOVED_IN;
} }
else else
@ -2584,19 +2591,20 @@ newsame:;
htup->t_xmax = htup->t_cmax = 0; htup->t_xmax = htup->t_cmax = 0;
htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask; htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
} }
offnum = PageAddItem(page, (Item)htup, newlen, offnum, offnum = PageAddItem(page, (Item) htup, newlen, offnum,
LP_USED | OverwritePageMode); LP_USED | OverwritePageMode);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(STOP, "heap_update_redo: failed to add tuple"); elog(STOP, "heap_update_redo: failed to add tuple");
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); /* prev sui */ PageSetSUI(page, ThisStartUpID); /* prev sui */
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
return; return;
} }
/* undo */ /* undo */
if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied ?! */ if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
* ?! */
elog(STOP, "heap_update_undo: bad new tuple page LSN"); elog(STOP, "heap_update_undo: bad new tuple page LSN");
elog(STOP, "heap_update_undo: unimplemented"); elog(STOP, "heap_update_undo: unimplemented");
@ -2606,19 +2614,19 @@ newsame:;
static void static void
_heap_unlock_tuple(void *data) _heap_unlock_tuple(void *data)
{ {
xl_heaptid *xltid = (xl_heaptid*) data; xl_heaptid *xltid = (xl_heaptid *) data;
Relation reln = XLogOpenRelation(false, RM_HEAP_ID, xltid->node); Relation reln = XLogOpenRelation(false, RM_HEAP_ID, xltid->node);
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
elog(STOP, "_heap_unlock_tuple: can't open relation"); elog(STOP, "_heap_unlock_tuple: can't open relation");
buffer = XLogReadBuffer(false, reln, buffer = XLogReadBuffer(false, reln,
ItemPointerGetBlockNumber(&(xltid->tid))); ItemPointerGetBlockNumber(&(xltid->tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "_heap_unlock_tuple: can't read buffer"); elog(STOP, "_heap_unlock_tuple: can't read buffer");
@ -2636,8 +2644,8 @@ _heap_unlock_tuple(void *data)
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
if (htup->t_xmax != GetCurrentTransactionId() || if (htup->t_xmax != GetCurrentTransactionId() ||
htup->t_cmax != GetCurrentCommandId()) htup->t_cmax != GetCurrentCommandId())
elog(STOP, "_heap_unlock_tuple: invalid xmax/cmax in rollback"); elog(STOP, "_heap_unlock_tuple: invalid xmax/cmax in rollback");
htup->t_infomask &= ~HEAP_XMAX_UNLOGGED; htup->t_infomask &= ~HEAP_XMAX_UNLOGGED;
htup->t_infomask |= HEAP_XMAX_INVALID; htup->t_infomask |= HEAP_XMAX_INVALID;
@ -2645,9 +2653,10 @@ _heap_unlock_tuple(void *data)
return; return;
} }
void heap_redo(XLogRecPtr lsn, XLogRecord *record) void
heap_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
info &= XLOG_HEAP_OPMASK; info &= XLOG_HEAP_OPMASK;
if (info == XLOG_HEAP_INSERT) if (info == XLOG_HEAP_INSERT)
@ -2664,9 +2673,10 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record)
elog(STOP, "heap_redo: unknown op code %u", info); elog(STOP, "heap_redo: unknown op code %u", info);
} }
void heap_undo(XLogRecPtr lsn, XLogRecord *record) void
heap_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
info &= XLOG_HEAP_OPMASK; info &= XLOG_HEAP_OPMASK;
if (info == XLOG_HEAP_INSERT) if (info == XLOG_HEAP_INSERT)
@ -2687,46 +2697,50 @@ static void
out_target(char *buf, xl_heaptid *target) out_target(char *buf, xl_heaptid *target)
{ {
sprintf(buf + strlen(buf), "node %u/%u; tid %u/%u", sprintf(buf + strlen(buf), "node %u/%u; tid %u/%u",
target->node.tblNode, target->node.relNode, target->node.tblNode, target->node.relNode,
ItemPointerGetBlockNumber(&(target->tid)), ItemPointerGetBlockNumber(&(target->tid)),
ItemPointerGetOffsetNumber(&(target->tid))); ItemPointerGetOffsetNumber(&(target->tid)));
} }
void void
heap_desc(char *buf, uint8 xl_info, char* rec) heap_desc(char *buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
info &= XLOG_HEAP_OPMASK; info &= XLOG_HEAP_OPMASK;
if (info == XLOG_HEAP_INSERT) if (info == XLOG_HEAP_INSERT)
{ {
xl_heap_insert *xlrec = (xl_heap_insert*) rec; xl_heap_insert *xlrec = (xl_heap_insert *) rec;
strcat(buf, "insert: "); strcat(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_DELETE) else if (info == XLOG_HEAP_DELETE)
{ {
xl_heap_delete *xlrec = (xl_heap_delete*) rec; xl_heap_delete *xlrec = (xl_heap_delete *) rec;
strcat(buf, "delete: "); strcat(buf, "delete: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE) else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE)
{ {
xl_heap_update *xlrec = (xl_heap_update*) rec; xl_heap_update *xlrec = (xl_heap_update *) rec;
if (info == XLOG_HEAP_UPDATE) if (info == XLOG_HEAP_UPDATE)
strcat(buf, "update: "); strcat(buf, "update: ");
else else
strcat(buf, "move: "); strcat(buf, "move: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; new %u/%u", sprintf(buf + strlen(buf), "; new %u/%u",
ItemPointerGetBlockNumber(&(xlrec->newtid)), ItemPointerGetBlockNumber(&(xlrec->newtid)),
ItemPointerGetOffsetNumber(&(xlrec->newtid))); ItemPointerGetOffsetNumber(&(xlrec->newtid)));
} }
else if (info == XLOG_HEAP_CLEAN) else if (info == XLOG_HEAP_CLEAN)
{ {
xl_heap_clean *xlrec = (xl_heap_clean*) rec; xl_heap_clean *xlrec = (xl_heap_clean *) rec;
sprintf(buf + strlen(buf), "clean: node %u/%u; blk %u", sprintf(buf + strlen(buf), "clean: node %u/%u; blk %u",
xlrec->node.tblNode, xlrec->node.relNode, xlrec->block); xlrec->node.tblNode, xlrec->node.relNode, xlrec->block);
} }
else else
strcat(buf, "UNKNOWN"); strcat(buf, "UNKNOWN");

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Id: hio.c,v 1.35 2001/01/24 19:42:48 momjian Exp $ * $Id: hio.c,v 1.36 2001/03/22 03:59:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,7 +19,7 @@
#include "access/hio.h" #include "access/hio.h"
/* /*
* RelationPutHeapTuple - place tuple at specified page * RelationPutHeapTuple - place tuple at specified page
* *
* !!! ELOG(ERROR) IS DISALLOWED HERE !!! * !!! ELOG(ERROR) IS DISALLOWED HERE !!!
* *
@ -69,7 +69,7 @@ RelationPutHeapTuple(Relation relation,
* *
* Returns (locked) buffer with free space >= given len. * Returns (locked) buffer with free space >= given len.
* *
* Note that we use LockPage to lock relation for extension. We can * Note that we use LockPage to lock relation for extension. We can
* do this as long as in all other places we use page-level locking * do this as long as in all other places we use page-level locking
* for indices only. Alternatively, we could define pseudo-table as * for indices only. Alternatively, we could define pseudo-table as
* we do for transactions with XactLockTable. * we do for transactions with XactLockTable.
@ -92,7 +92,7 @@ RelationGetBufferForTuple(Relation relation, Size len)
*/ */
if (len > MaxTupleSize) if (len > MaxTupleSize)
elog(ERROR, "Tuple is too big: size %lu, max size %ld", elog(ERROR, "Tuple is too big: size %lu, max size %ld",
(unsigned long)len, MaxTupleSize); (unsigned long) len, MaxTupleSize);
if (!relation->rd_myxactonly) if (!relation->rd_myxactonly)
LockPage(relation, 0, ExclusiveLock); LockPage(relation, 0, ExclusiveLock);
@ -140,13 +140,13 @@ RelationGetBufferForTuple(Relation relation, Size len)
{ {
/* We should not get here given the test at the top */ /* We should not get here given the test at the top */
elog(STOP, "Tuple is too big: size %lu", elog(STOP, "Tuple is too big: size %lu",
(unsigned long)len); (unsigned long) len);
} }
} }
if (!relation->rd_myxactonly) if (!relation->rd_myxactonly)
UnlockPage(relation, 0, ExclusiveLock); UnlockPage(relation, 0, ExclusiveLock);
return(buffer); return (buffer);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.17 2001/02/15 20:57:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.18 2001/03/22 03:59:13 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -41,12 +41,12 @@
#undef TOAST_DEBUG #undef TOAST_DEBUG
static void toast_delete(Relation rel, HeapTuple oldtup); static void toast_delete(Relation rel, HeapTuple oldtup);
static void toast_delete_datum(Relation rel, Datum value); static void toast_delete_datum(Relation rel, Datum value);
static void toast_insert_or_update(Relation rel, HeapTuple newtup, static void toast_insert_or_update(Relation rel, HeapTuple newtup,
HeapTuple oldtup); HeapTuple oldtup);
static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value); static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
static varattrib *toast_fetch_datum(varattrib *attr); static varattrib *toast_fetch_datum(varattrib *attr);
/* ---------- /* ----------
@ -70,14 +70,14 @@ heap_tuple_toast_attrs(Relation rel, HeapTuple newtup, HeapTuple oldtup)
/* ---------- /* ----------
* heap_tuple_fetch_attr - * heap_tuple_fetch_attr -
* *
* Public entry point to get back a toasted value * Public entry point to get back a toasted value
* external storage (possibly still in compressed format). * external storage (possibly still in compressed format).
* ---------- * ----------
*/ */
varattrib * varattrib *
heap_tuple_fetch_attr(varattrib *attr) heap_tuple_fetch_attr(varattrib *attr)
{ {
varattrib *result; varattrib *result;
if (VARATT_IS_EXTERNAL(attr)) if (VARATT_IS_EXTERNAL(attr))
{ {
@ -94,7 +94,7 @@ heap_tuple_fetch_attr(varattrib *attr)
* ---------- * ----------
*/ */
result = attr; result = attr;
} }
return result; return result;
} }
@ -107,10 +107,10 @@ heap_tuple_fetch_attr(varattrib *attr)
* or external storage. * or external storage.
* ---------- * ----------
*/ */
varattrib * varattrib *
heap_tuple_untoast_attr(varattrib *attr) heap_tuple_untoast_attr(varattrib *attr)
{ {
varattrib *result; varattrib *result;
if (VARATT_IS_EXTERNAL(attr)) if (VARATT_IS_EXTERNAL(attr))
{ {
@ -121,14 +121,14 @@ heap_tuple_untoast_attr(varattrib *attr)
* Fetch it from the toast heap and decompress. * Fetch it from the toast heap and decompress.
* ---------- * ----------
*/ */
varattrib *tmp; varattrib *tmp;
tmp = toast_fetch_datum(attr); tmp = toast_fetch_datum(attr);
result = (varattrib *)palloc(attr->va_content.va_external.va_rawsize result = (varattrib *) palloc(attr->va_content.va_external.va_rawsize
+ VARHDRSZ); + VARHDRSZ);
VARATT_SIZEP(result) = attr->va_content.va_external.va_rawsize VARATT_SIZEP(result) = attr->va_content.va_external.va_rawsize
+ VARHDRSZ; + VARHDRSZ;
pglz_decompress((PGLZ_Header *)tmp, VARATT_DATA(result)); pglz_decompress((PGLZ_Header *) tmp, VARATT_DATA(result));
pfree(tmp); pfree(tmp);
} }
@ -147,11 +147,11 @@ heap_tuple_untoast_attr(varattrib *attr)
* This is a compressed value inside of the main tuple * This is a compressed value inside of the main tuple
* ---------- * ----------
*/ */
result = (varattrib *)palloc(attr->va_content.va_compressed.va_rawsize result = (varattrib *) palloc(attr->va_content.va_compressed.va_rawsize
+ VARHDRSZ); + VARHDRSZ);
VARATT_SIZEP(result) = attr->va_content.va_compressed.va_rawsize VARATT_SIZEP(result) = attr->va_content.va_compressed.va_rawsize
+ VARHDRSZ; + VARHDRSZ;
pglz_decompress((PGLZ_Header *)attr, VARATT_DATA(result)); pglz_decompress((PGLZ_Header *) attr, VARATT_DATA(result));
} }
else else
/* ---------- /* ----------
@ -173,21 +173,21 @@ heap_tuple_untoast_attr(varattrib *attr)
static void static void
toast_delete(Relation rel, HeapTuple oldtup) toast_delete(Relation rel, HeapTuple oldtup)
{ {
TupleDesc tupleDesc; TupleDesc tupleDesc;
Form_pg_attribute *att; Form_pg_attribute *att;
int numAttrs; int numAttrs;
int i; int i;
Datum value; Datum value;
bool isnull; bool isnull;
/* ---------- /* ----------
* Get the tuple descriptor, the number of and attribute * Get the tuple descriptor, the number of and attribute
* descriptors. * descriptors.
* ---------- * ----------
*/ */
tupleDesc = rel->rd_att; tupleDesc = rel->rd_att;
numAttrs = tupleDesc->natts; numAttrs = tupleDesc->natts;
att = tupleDesc->attrs; att = tupleDesc->attrs;
/* ---------- /* ----------
* Check for external stored attributes and delete them * Check for external stored attributes and delete them
@ -216,35 +216,35 @@ toast_delete(Relation rel, HeapTuple oldtup)
static void static void
toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
{ {
TupleDesc tupleDesc; TupleDesc tupleDesc;
Form_pg_attribute *att; Form_pg_attribute *att;
int numAttrs; int numAttrs;
int i; int i;
bool old_isnull; bool old_isnull;
bool new_isnull; bool new_isnull;
bool need_change = false; bool need_change = false;
bool need_free = false; bool need_free = false;
bool need_delold = false; bool need_delold = false;
bool has_nulls = false; bool has_nulls = false;
Size maxDataLen; Size maxDataLen;
char toast_action[MaxHeapAttributeNumber]; char toast_action[MaxHeapAttributeNumber];
char toast_nulls[MaxHeapAttributeNumber]; char toast_nulls[MaxHeapAttributeNumber];
Datum toast_values[MaxHeapAttributeNumber]; Datum toast_values[MaxHeapAttributeNumber];
int32 toast_sizes[MaxHeapAttributeNumber]; int32 toast_sizes[MaxHeapAttributeNumber];
bool toast_free[MaxHeapAttributeNumber]; bool toast_free[MaxHeapAttributeNumber];
bool toast_delold[MaxHeapAttributeNumber]; bool toast_delold[MaxHeapAttributeNumber];
/* ---------- /* ----------
* Get the tuple descriptor, the number of and attribute * Get the tuple descriptor, the number of and attribute
* descriptors and the location of the tuple values. * descriptors and the location of the tuple values.
* ---------- * ----------
*/ */
tupleDesc = rel->rd_att; tupleDesc = rel->rd_att;
numAttrs = tupleDesc->natts; numAttrs = tupleDesc->natts;
att = tupleDesc->attrs; att = tupleDesc->attrs;
/* ---------- /* ----------
* Then collect information about the values given * Then collect information about the values given
@ -255,14 +255,14 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* 'x' incompressible, but OK to move off * 'x' incompressible, but OK to move off
* ---------- * ----------
*/ */
memset(toast_action, ' ', numAttrs * sizeof(char)); memset(toast_action, ' ', numAttrs * sizeof(char));
memset(toast_nulls, ' ', numAttrs * sizeof(char)); memset(toast_nulls, ' ', numAttrs * sizeof(char));
memset(toast_free, 0, numAttrs * sizeof(bool)); memset(toast_free, 0, numAttrs * sizeof(bool));
memset(toast_delold, 0, numAttrs * sizeof(bool)); memset(toast_delold, 0, numAttrs * sizeof(bool));
for (i = 0; i < numAttrs; i++) for (i = 0; i < numAttrs; i++)
{ {
varattrib *old_value; varattrib *old_value;
varattrib *new_value; varattrib *new_value;
if (oldtup != NULL) if (oldtup != NULL)
{ {
@ -270,25 +270,25 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* For UPDATE get the old and new values of this attribute * For UPDATE get the old and new values of this attribute
* ---------- * ----------
*/ */
old_value = (varattrib *)DatumGetPointer( old_value = (varattrib *) DatumGetPointer(
heap_getattr(oldtup, i + 1, tupleDesc, &old_isnull)); heap_getattr(oldtup, i + 1, tupleDesc, &old_isnull));
toast_values[i] = toast_values[i] =
heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); heap_getattr(newtup, i + 1, tupleDesc, &new_isnull);
new_value = (varattrib *)DatumGetPointer(toast_values[i]); new_value = (varattrib *) DatumGetPointer(toast_values[i]);
/* ---------- /* ----------
* If the old value is an external stored one, check if it * If the old value is an external stored one, check if it
* has changed so we have to delete it later. * has changed so we have to delete it later.
* ---------- * ----------
*/ */
if (!old_isnull && att[i]->attlen == -1 && if (!old_isnull && att[i]->attlen == -1 &&
VARATT_IS_EXTERNAL(old_value)) VARATT_IS_EXTERNAL(old_value))
{ {
if (new_isnull || !VARATT_IS_EXTERNAL(new_value) || if (new_isnull || !VARATT_IS_EXTERNAL(new_value) ||
old_value->va_content.va_external.va_rowid != old_value->va_content.va_external.va_rowid !=
new_value->va_content.va_external.va_rowid || new_value->va_content.va_external.va_rowid ||
old_value->va_content.va_external.va_attno != old_value->va_content.va_external.va_attno !=
new_value->va_content.va_external.va_attno) new_value->va_content.va_external.va_attno)
{ {
/* ---------- /* ----------
* The old external store value isn't needed any * The old external store value isn't needed any
@ -318,8 +318,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* For INSERT simply get the new value * For INSERT simply get the new value
* ---------- * ----------
*/ */
toast_values[i] = toast_values[i] =
heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); heap_getattr(newtup, i + 1, tupleDesc, &new_isnull);
} }
/* ---------- /* ----------
@ -356,7 +356,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i]))) if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
{ {
toast_values[i] = PointerGetDatum(heap_tuple_untoast_attr( toast_values[i] = PointerGetDatum(heap_tuple_untoast_attr(
(varattrib *)DatumGetPointer(toast_values[i]))); (varattrib *) DatumGetPointer(toast_values[i])));
toast_free[i] = true; toast_free[i] = true;
need_change = true; need_change = true;
need_free = true; need_free = true;
@ -366,7 +366,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* Remember the size of this attribute * Remember the size of this attribute
* ---------- * ----------
*/ */
toast_sizes[i] = VARATT_SIZE(DatumGetPointer(toast_values[i])); toast_sizes[i] = VARATT_SIZE(DatumGetPointer(toast_values[i]));
} }
else else
{ {
@ -375,7 +375,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
toast_action[i] = 'p'; toast_action[i] = 'p';
toast_sizes[i] = att[i]->attlen; toast_sizes[i] = att[i]->attlen;
} }
} }
@ -384,7 +384,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* *
* 1: Inline compress attributes with attstorage 'x' * 1: Inline compress attributes with attstorage 'x'
* 2: Store attributes with attstorage 'x' or 'e' external * 2: Store attributes with attstorage 'x' or 'e' external
* 3: Inline compress attributes with attstorage 'm' * 3: Inline compress attributes with attstorage 'm'
* 4: Store attributes with attstorage 'm' external * 4: Store attributes with attstorage 'm' external
* ---------- * ----------
*/ */
@ -398,12 +398,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
maxDataLen) maxDataLen)
{ {
int biggest_attno = -1; int biggest_attno = -1;
int32 biggest_size = MAXALIGN(sizeof(varattrib)); int32 biggest_size = MAXALIGN(sizeof(varattrib));
Datum old_value; Datum old_value;
Datum new_value; Datum new_value;
/* ---------- /* ----------
* Search for the biggest yet uncompressed internal attribute * Search for the biggest yet uncompressed internal attribute
@ -420,7 +420,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (toast_sizes[i] > biggest_size) if (toast_sizes[i] > biggest_size)
{ {
biggest_attno = i; biggest_attno = i;
biggest_size = toast_sizes[i]; biggest_size = toast_sizes[i];
} }
} }
@ -431,24 +431,28 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* Attempt to compress it inline * Attempt to compress it inline
* ---------- * ----------
*/ */
i = biggest_attno; i = biggest_attno;
old_value = toast_values[i]; old_value = toast_values[i];
new_value = toast_compress_datum(old_value); new_value = toast_compress_datum(old_value);
if (DatumGetPointer(new_value) != NULL) if (DatumGetPointer(new_value) != NULL)
{ {
/* successful compression */ /* successful compression */
if (toast_free[i]) if (toast_free[i])
pfree(DatumGetPointer(old_value)); pfree(DatumGetPointer(old_value));
toast_values[i] = new_value; toast_values[i] = new_value;
toast_free[i] = true; toast_free[i] = true;
toast_sizes[i] = VARATT_SIZE(toast_values[i]); toast_sizes[i] = VARATT_SIZE(toast_values[i]);
need_change = true; need_change = true;
need_free = true; need_free = true;
} }
else else
{ {
/* incompressible data, ignore on subsequent compression passes */
/*
* incompressible data, ignore on subsequent compression
* passes
*/
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
} }
@ -459,11 +463,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
{ {
int biggest_attno = -1; int biggest_attno = -1;
int32 biggest_size = MAXALIGN(sizeof(varattrib)); int32 biggest_size = MAXALIGN(sizeof(varattrib));
Datum old_value; Datum old_value;
/* ---------- /* ----------
* Search for the biggest yet inlined attribute with * Search for the biggest yet inlined attribute with
@ -481,7 +485,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (toast_sizes[i] > biggest_size) if (toast_sizes[i] > biggest_size)
{ {
biggest_attno = i; biggest_attno = i;
biggest_size = toast_sizes[i]; biggest_size = toast_sizes[i];
} }
} }
@ -492,21 +496,21 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* Store this external * Store this external
* ---------- * ----------
*/ */
i = biggest_attno; i = biggest_attno;
old_value = toast_values[i]; old_value = toast_values[i];
toast_action[i] = 'p'; toast_action[i] = 'p';
toast_values[i] = toast_save_datum(rel, toast_values[i] = toast_save_datum(rel,
newtup->t_data->t_oid, newtup->t_data->t_oid,
i + 1, i + 1,
toast_values[i]); toast_values[i]);
if (toast_free[i]) if (toast_free[i])
pfree(DatumGetPointer(old_value)); pfree(DatumGetPointer(old_value));
toast_free[i] = true; toast_free[i] = true;
toast_sizes[i] = VARATT_SIZE(toast_values[i]); toast_sizes[i] = VARATT_SIZE(toast_values[i]);
need_change = true; need_change = true;
need_free = true; need_free = true;
} }
/* ---------- /* ----------
@ -515,12 +519,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
maxDataLen) maxDataLen)
{ {
int biggest_attno = -1; int biggest_attno = -1;
int32 biggest_size = MAXALIGN(sizeof(varattrib)); int32 biggest_size = MAXALIGN(sizeof(varattrib));
Datum old_value; Datum old_value;
Datum new_value; Datum new_value;
/* ---------- /* ----------
* Search for the biggest yet uncompressed internal attribute * Search for the biggest yet uncompressed internal attribute
@ -537,7 +541,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (toast_sizes[i] > biggest_size) if (toast_sizes[i] > biggest_size)
{ {
biggest_attno = i; biggest_attno = i;
biggest_size = toast_sizes[i]; biggest_size = toast_sizes[i];
} }
} }
@ -548,24 +552,28 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* Attempt to compress it inline * Attempt to compress it inline
* ---------- * ----------
*/ */
i = biggest_attno; i = biggest_attno;
old_value = toast_values[i]; old_value = toast_values[i];
new_value = toast_compress_datum(old_value); new_value = toast_compress_datum(old_value);
if (DatumGetPointer(new_value) != NULL) if (DatumGetPointer(new_value) != NULL)
{ {
/* successful compression */ /* successful compression */
if (toast_free[i]) if (toast_free[i])
pfree(DatumGetPointer(old_value)); pfree(DatumGetPointer(old_value));
toast_values[i] = new_value; toast_values[i] = new_value;
toast_free[i] = true; toast_free[i] = true;
toast_sizes[i] = VARATT_SIZE(toast_values[i]); toast_sizes[i] = VARATT_SIZE(toast_values[i]);
need_change = true; need_change = true;
need_free = true; need_free = true;
} }
else else
{ {
/* incompressible data, ignore on subsequent compression passes */
/*
* incompressible data, ignore on subsequent compression
* passes
*/
toast_action[i] = 'x'; toast_action[i] = 'x';
} }
} }
@ -575,11 +583,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
{ {
int biggest_attno = -1; int biggest_attno = -1;
int32 biggest_size = MAXALIGN(sizeof(varattrib)); int32 biggest_size = MAXALIGN(sizeof(varattrib));
Datum old_value; Datum old_value;
/* ---------- /* ----------
* Search for the biggest yet inlined attribute with * Search for the biggest yet inlined attribute with
@ -597,7 +605,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (toast_sizes[i] > biggest_size) if (toast_sizes[i] > biggest_size)
{ {
biggest_attno = i; biggest_attno = i;
biggest_size = toast_sizes[i]; biggest_size = toast_sizes[i];
} }
} }
@ -608,21 +616,21 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* Store this external * Store this external
* ---------- * ----------
*/ */
i = biggest_attno; i = biggest_attno;
old_value = toast_values[i]; old_value = toast_values[i];
toast_action[i] = 'p'; toast_action[i] = 'p';
toast_values[i] = toast_save_datum(rel, toast_values[i] = toast_save_datum(rel,
newtup->t_data->t_oid, newtup->t_data->t_oid,
i + 1, i + 1,
toast_values[i]); toast_values[i]);
if (toast_free[i]) if (toast_free[i])
pfree(DatumGetPointer(old_value)); pfree(DatumGetPointer(old_value));
toast_free[i] = true; toast_free[i] = true;
toast_sizes[i] = VARATT_SIZE(toast_values[i]); toast_sizes[i] = VARATT_SIZE(toast_values[i]);
need_change = true; need_change = true;
need_free = true; need_free = true;
} }
/* ---------- /* ----------
@ -632,10 +640,10 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
*/ */
if (need_change) if (need_change)
{ {
char *new_data; char *new_data;
int32 new_len; int32 new_len;
MemoryContext oldcxt; MemoryContext oldcxt;
HeapTupleHeader olddata; HeapTupleHeader olddata;
/* ---------- /* ----------
* Calculate the new size of the tuple * Calculate the new size of the tuple
@ -662,24 +670,24 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* ---------- * ----------
*/ */
memcpy(new_data, newtup->t_data, newtup->t_data->t_hoff); memcpy(new_data, newtup->t_data, newtup->t_data->t_hoff);
newtup->t_data = (HeapTupleHeader)new_data; newtup->t_data = (HeapTupleHeader) new_data;
newtup->t_len = new_len; newtup->t_len = new_len;
DataFill((char *)(MAXALIGN((long)new_data + DataFill((char *) (MAXALIGN((long) new_data +
offsetof(HeapTupleHeaderData, t_bits) + offsetof(HeapTupleHeaderData, t_bits) +
((has_nulls) ? BITMAPLEN(numAttrs) : 0))), ((has_nulls) ? BITMAPLEN(numAttrs) : 0))),
tupleDesc, tupleDesc,
toast_values, toast_values,
toast_nulls, toast_nulls,
&(newtup->t_data->t_infomask), &(newtup->t_data->t_infomask),
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, * In the case we modified a previously modified tuple again,
* free the memory from the previous run * free the memory from the previous run
* ---------- * ----------
*/ */
if ((char *)olddata != ((char *)newtup + HEAPTUPLESIZE)) if ((char *) olddata != ((char *) newtup + HEAPTUPLESIZE))
pfree(olddata); pfree(olddata);
/* ---------- /* ----------
@ -723,7 +731,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
Datum Datum
toast_compress_datum(Datum value) toast_compress_datum(Datum value)
{ {
varattrib *tmp; varattrib *tmp;
tmp = (varattrib *) palloc(sizeof(PGLZ_Header) + VARATT_SIZE(value)); tmp = (varattrib *) palloc(sizeof(PGLZ_Header) + VARATT_SIZE(value));
pglz_compress(VARATT_DATA(value), VARATT_SIZE(value) - VARHDRSZ, pglz_compress(VARATT_DATA(value), VARATT_SIZE(value) - VARHDRSZ,
@ -754,45 +762,45 @@ toast_compress_datum(Datum value)
static Datum static Datum
toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
{ {
Relation toastrel; Relation toastrel;
Relation toastidx; Relation toastidx;
HeapTuple toasttup; HeapTuple toasttup;
InsertIndexResult idxres; InsertIndexResult idxres;
TupleDesc toasttupDesc; TupleDesc toasttupDesc;
Datum t_values[3]; Datum t_values[3];
char t_nulls[3]; char t_nulls[3];
varattrib *result; varattrib *result;
char chunk_data[VARHDRSZ + TOAST_MAX_CHUNK_SIZE]; char chunk_data[VARHDRSZ + TOAST_MAX_CHUNK_SIZE];
int32 chunk_size; int32 chunk_size;
int32 chunk_seq = 0; int32 chunk_seq = 0;
char *data_p; char *data_p;
int32 data_todo; int32 data_todo;
/* ---------- /* ----------
* Create the varattrib reference * Create the varattrib reference
* ---------- * ----------
*/ */
result = (varattrib *)palloc(sizeof(varattrib)); result = (varattrib *) palloc(sizeof(varattrib));
result->va_header = sizeof(varattrib) | VARATT_FLAG_EXTERNAL; result->va_header = sizeof(varattrib) | VARATT_FLAG_EXTERNAL;
if (VARATT_IS_COMPRESSED(value)) if (VARATT_IS_COMPRESSED(value))
{ {
result->va_header |= VARATT_FLAG_COMPRESSED; result->va_header |= VARATT_FLAG_COMPRESSED;
result->va_content.va_external.va_rawsize = result->va_content.va_external.va_rawsize =
((varattrib *)value)->va_content.va_compressed.va_rawsize; ((varattrib *) value)->va_content.va_compressed.va_rawsize;
} }
else else
result->va_content.va_external.va_rawsize = VARATT_SIZE(value); result->va_content.va_external.va_rawsize = VARATT_SIZE(value);
result->va_content.va_external.va_extsize = result->va_content.va_external.va_extsize =
VARATT_SIZE(value) - VARHDRSZ; VARATT_SIZE(value) - VARHDRSZ;
result->va_content.va_external.va_valueid = newoid(); result->va_content.va_external.va_valueid = newoid();
result->va_content.va_external.va_toastrelid = result->va_content.va_external.va_toastrelid =
rel->rd_rel->reltoastrelid; rel->rd_rel->reltoastrelid;
result->va_content.va_external.va_toastidxid = result->va_content.va_external.va_toastidxid =
rel->rd_rel->reltoastidxid; rel->rd_rel->reltoastidxid;
result->va_content.va_external.va_rowid = mainoid; result->va_content.va_external.va_rowid = mainoid;
result->va_content.va_external.va_attno = attno; result->va_content.va_external.va_attno = attno;
/* ---------- /* ----------
* Initialize constant parts of the tuple data * Initialize constant parts of the tuple data
@ -808,8 +816,8 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
* Get the data to process * Get the data to process
* ---------- * ----------
*/ */
data_p = VARATT_DATA(value); data_p = VARATT_DATA(value);
data_todo = VARATT_SIZE(value) - VARHDRSZ; data_todo = VARATT_SIZE(value) - VARHDRSZ;
/* ---------- /* ----------
* Open the toast relation * Open the toast relation
@ -818,9 +826,9 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att; toasttupDesc = toastrel->rd_att;
toastidx = index_open(rel->rd_rel->reltoastidxid); toastidx = index_open(rel->rd_rel->reltoastidxid);
/* ---------- /* ----------
* Split up the item into chunks * Split up the item into chunks
* ---------- * ----------
*/ */
while (data_todo > 0) while (data_todo > 0)
@ -848,8 +856,8 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
*/ */
heap_insert(toastrel, toasttup); heap_insert(toastrel, toasttup);
idxres = index_insert(toastidx, t_values, t_nulls, idxres = index_insert(toastidx, t_values, t_nulls,
&(toasttup->t_self), &(toasttup->t_self),
toastrel); toastrel);
if (idxres == NULL) if (idxres == NULL)
elog(ERROR, "Failed to insert index entry for TOAST tuple"); elog(ERROR, "Failed to insert index entry for TOAST tuple");
@ -888,14 +896,14 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
static void static void
toast_delete_datum(Relation rel, Datum value) toast_delete_datum(Relation rel, Datum value)
{ {
register varattrib *attr = (varattrib *)value; register varattrib *attr = (varattrib *) value;
Relation toastrel; Relation toastrel;
Relation toastidx; Relation toastidx;
ScanKeyData toastkey; ScanKeyData toastkey;
IndexScanDesc toastscan; IndexScanDesc toastscan;
HeapTupleData toasttup; HeapTupleData toasttup;
RetrieveIndexResult indexRes; RetrieveIndexResult indexRes;
Buffer buffer; Buffer buffer;
if (!VARATT_IS_EXTERNAL(attr)) if (!VARATT_IS_EXTERNAL(attr))
return; return;
@ -904,8 +912,8 @@ toast_delete_datum(Relation rel, Datum value)
* Open the toast relation and it's index * Open the toast relation and it's index
* ---------- * ----------
*/ */
toastrel = heap_open(attr->va_content.va_external.va_toastrelid, toastrel = heap_open(attr->va_content.va_external.va_toastrelid,
RowExclusiveLock); RowExclusiveLock);
toastidx = index_open(attr->va_content.va_external.va_toastidxid); toastidx = index_open(attr->va_content.va_external.va_toastidxid);
/* ---------- /* ----------
@ -913,10 +921,10 @@ toast_delete_datum(Relation rel, Datum value)
* ---------- * ----------
*/ */
ScanKeyEntryInitialize(&toastkey, ScanKeyEntryInitialize(&toastkey,
(bits16) 0, (bits16) 0,
(AttrNumber) 1, (AttrNumber) 1,
(RegProcedure) F_OIDEQ, (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
/* ---------- /* ----------
* Read the chunks by index * Read the chunks by index
@ -961,36 +969,36 @@ toast_delete_datum(Relation rel, Datum value)
static varattrib * static varattrib *
toast_fetch_datum(varattrib *attr) toast_fetch_datum(varattrib *attr)
{ {
Relation toastrel; Relation toastrel;
Relation toastidx; Relation toastidx;
ScanKeyData toastkey; ScanKeyData toastkey;
IndexScanDesc toastscan; IndexScanDesc toastscan;
HeapTupleData toasttup; HeapTupleData toasttup;
HeapTuple ttup; HeapTuple ttup;
TupleDesc toasttupDesc; TupleDesc toasttupDesc;
RetrieveIndexResult indexRes; RetrieveIndexResult indexRes;
Buffer buffer; Buffer buffer;
varattrib *result; varattrib *result;
int32 ressize; int32 ressize;
int32 residx; int32 residx;
int numchunks; int numchunks;
Pointer chunk; Pointer chunk;
bool isnull; bool isnull;
int32 chunksize; int32 chunksize;
char *chunks_found; char *chunks_found;
char *chunks_expected; char *chunks_expected;
ressize = attr->va_content.va_external.va_extsize; ressize = attr->va_content.va_external.va_extsize;
numchunks = ((ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1; numchunks = ((ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
chunks_found = palloc(numchunks); chunks_found = palloc(numchunks);
chunks_expected = palloc(numchunks); chunks_expected = palloc(numchunks);
memset(chunks_found, 0, numchunks); memset(chunks_found, 0, numchunks);
memset(chunks_expected, 1, numchunks); memset(chunks_expected, 1, numchunks);
result = (varattrib *)palloc(ressize + VARHDRSZ); result = (varattrib *) palloc(ressize + VARHDRSZ);
VARATT_SIZEP(result) = ressize + VARHDRSZ; VARATT_SIZEP(result) = ressize + VARHDRSZ;
if (VARATT_IS_COMPRESSED(attr)) if (VARATT_IS_COMPRESSED(attr))
VARATT_SIZEP(result) |= VARATT_FLAG_COMPRESSED; VARATT_SIZEP(result) |= VARATT_FLAG_COMPRESSED;
@ -999,8 +1007,8 @@ toast_fetch_datum(varattrib *attr)
* Open the toast relation and it's index * Open the toast relation and it's index
* ---------- * ----------
*/ */
toastrel = heap_open(attr->va_content.va_external.va_toastrelid, toastrel = heap_open(attr->va_content.va_external.va_toastrelid,
AccessShareLock); AccessShareLock);
toasttupDesc = toastrel->rd_att; toasttupDesc = toastrel->rd_att;
toastidx = index_open(attr->va_content.va_external.va_toastidxid); toastidx = index_open(attr->va_content.va_external.va_toastidxid);
@ -1009,10 +1017,10 @@ toast_fetch_datum(varattrib *attr)
* ---------- * ----------
*/ */
ScanKeyEntryInitialize(&toastkey, ScanKeyEntryInitialize(&toastkey,
(bits16) 0, (bits16) 0,
(AttrNumber) 1, (AttrNumber) 1,
(RegProcedure) F_OIDEQ, (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
/* ---------- /* ----------
* Read the chunks by index * Read the chunks by index
@ -1049,7 +1057,7 @@ toast_fetch_datum(varattrib *attr)
elog(ERROR, "unexpected chunk number %d for toast value %d", elog(ERROR, "unexpected chunk number %d for toast value %d",
residx, residx,
attr->va_content.va_external.va_valueid); attr->va_content.va_external.va_valueid);
if (residx < numchunks-1) if (residx < numchunks - 1)
{ {
if (chunksize != TOAST_MAX_CHUNK_SIZE) if (chunksize != TOAST_MAX_CHUNK_SIZE)
elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %d", elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %d",
@ -1072,7 +1080,7 @@ toast_fetch_datum(varattrib *attr)
* Copy the data into proper place in our result * Copy the data into proper place in our result
* ---------- * ----------
*/ */
memcpy(((char *)VARATT_DATA(result)) + residx * TOAST_MAX_CHUNK_SIZE, memcpy(((char *) VARATT_DATA(result)) + residx * TOAST_MAX_CHUNK_SIZE,
VARATT_DATA(chunk), VARATT_DATA(chunk),
chunksize); chunksize);
@ -1085,7 +1093,7 @@ toast_fetch_datum(varattrib *attr)
*/ */
if (memcmp(chunks_found, chunks_expected, numchunks) != 0) if (memcmp(chunks_found, chunks_expected, numchunks) != 0)
elog(ERROR, "not all toast chunks found for value %d", elog(ERROR, "not all toast chunks found for value %d",
attr->va_content.va_external.va_valueid); attr->va_content.va_external.va_valueid);
pfree(chunks_expected); pfree(chunks_expected);
pfree(chunks_found); pfree(chunks_found);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.48 2001/01/24 19:42:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.49 2001/03/22 03:59:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -239,8 +239,8 @@ StrategyTermEvaluate(StrategyTerm term,
break; break;
case SK_NEGATE: case SK_NEGATE:
result = ! DatumGetBool(FunctionCall2(&entry->sk_func, result = !DatumGetBool(FunctionCall2(&entry->sk_func,
left, right)); left, right));
break; break;
case SK_COMMUTE: case SK_COMMUTE:
@ -249,8 +249,8 @@ StrategyTermEvaluate(StrategyTerm term,
break; break;
case SK_NEGATE | SK_COMMUTE: case SK_NEGATE | SK_COMMUTE:
result = ! DatumGetBool(FunctionCall2(&entry->sk_func, result = !DatumGetBool(FunctionCall2(&entry->sk_func,
right, left)); right, left));
break; break;
default: default:
@ -263,6 +263,7 @@ StrategyTermEvaluate(StrategyTerm term,
return result; return result;
} }
#endif #endif
/* ---------------- /* ----------------
@ -465,6 +466,7 @@ RelationInvokeStrategy(Relation relation,
} }
#endif #endif
/* ---------------- /* ----------------
@ -519,7 +521,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
if (!RegProcedureIsValid(entry->sk_procedure)) if (!RegProcedureIsValid(entry->sk_procedure))
elog(ERROR, elog(ERROR,
"OperatorRelationFillScanKeyEntry: no procedure for operator %u", "OperatorRelationFillScanKeyEntry: no procedure for operator %u",
operatorObjectId); operatorObjectId);
fmgr_info(entry->sk_procedure, &entry->sk_func); fmgr_info(entry->sk_procedure, &entry->sk_func);
@ -597,9 +599,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
} }
if (cachesearch) if (cachesearch)
{
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
}
else else
{ {
heap_endscan(scan); heap_endscan(scan);

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.50 2001/02/07 23:35:33 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.51 2001/03/22 03:59:14 momjian Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -28,7 +28,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
extern bool FixBTree; /* comments in nbtree.c */ extern bool FixBTree; /* comments in nbtree.c */
extern Buffer _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release); extern Buffer _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release);
/* /*
@ -100,7 +100,7 @@ _bt_metapinit(Relation rel)
* *
* The access type parameter (BT_READ or BT_WRITE) controls whether * The access type parameter (BT_READ or BT_WRITE) controls whether
* a new root page will be created or not. If access = BT_READ, * a new root page will be created or not. If access = BT_READ,
* and no root page exists, we just return InvalidBuffer. For * and no root page exists, we just return InvalidBuffer. For
* BT_WRITE, we try to create the root page if it doesn't exist. * BT_WRITE, we try to create the root page if it doesn't exist.
* NOTE that the returned root page will have only a read lock set * NOTE that the returned root page will have only a read lock set
* on it even if access = BT_WRITE! * on it even if access = BT_WRITE!
@ -178,20 +178,20 @@ _bt_getroot(Relation rel, int access)
/* XLOG stuff */ /* XLOG stuff */
{ {
xl_btree_newroot xlrec; xl_btree_newroot xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata; XLogRecData rdata;
xlrec.node = rel->rd_node; xlrec.node = rel->rd_node;
xlrec.level = 1; xlrec.level = 1;
BlockIdSet(&(xlrec.rootblk), rootblkno); BlockIdSet(&(xlrec.rootblk), rootblkno);
rdata.buffer = InvalidBuffer; rdata.buffer = InvalidBuffer;
rdata.data = (char*)&xlrec; rdata.data = (char *) &xlrec;
rdata.len = SizeOfBtreeNewroot; rdata.len = SizeOfBtreeNewroot;
rdata.next = NULL; rdata.next = NULL;
recptr = XLogInsert(RM_BTREE_ID, recptr = XLogInsert(RM_BTREE_ID,
XLOG_BTREE_NEWROOT|XLOG_BTREE_LEAF, &rdata); XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF, &rdata);
PageSetLSN(rootpage, recptr); PageSetLSN(rootpage, recptr);
PageSetSUI(rootpage, ThisStartUpID); PageSetSUI(rootpage, ThisStartUpID);
@ -212,6 +212,7 @@ _bt_getroot(Relation rel, int access)
} }
else else
{ {
/* /*
* Metadata initialized by someone else. In order to * Metadata initialized by someone else. In order to
* guarantee no deadlocks, we have to release the metadata * guarantee no deadlocks, we have to release the metadata
@ -232,30 +233,31 @@ _bt_getroot(Relation rel, int access)
/* /*
* Race condition: If the root page split between the time we looked * Race condition: If the root page split between the time we looked
* at the metadata page and got the root buffer, then we got the wrong * at the metadata page and got the root buffer, then we got the wrong
* buffer. Release it and try again. * buffer. Release it and try again.
*/ */
rootpage = BufferGetPage(rootbuf); rootpage = BufferGetPage(rootbuf);
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage); rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
if (! P_ISROOT(rootopaque)) if (!P_ISROOT(rootopaque))
{ {
/* /*
* It happened, but if root page splitter failed to create * It happened, but if root page splitter failed to create new
* new root page then we'll go in loop trying to call * root page then we'll go in loop trying to call _bt_getroot
* _bt_getroot again and again. * again and again.
*/ */
if (FixBTree) if (FixBTree)
{ {
Buffer newrootbuf; Buffer newrootbuf;
check_parent:; check_parent:;
if (BTreeInvalidParent(rootopaque)) /* unupdated! */ if (BTreeInvalidParent(rootopaque)) /* unupdated! */
{ {
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK); LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_WRITE); LockBuffer(rootbuf, BT_WRITE);
/* handle concurrent fix of root page */ /* handle concurrent fix of root page */
if (BTreeInvalidParent(rootopaque)) /* unupdated! */ if (BTreeInvalidParent(rootopaque)) /* unupdated! */
{ {
elog(NOTICE, "bt_getroot[%s]: fixing root page", RelationGetRelationName(rel)); elog(NOTICE, "bt_getroot[%s]: fixing root page", RelationGetRelationName(rel));
newrootbuf = _bt_fixroot(rel, rootbuf, true); newrootbuf = _bt_fixroot(rel, rootbuf, true);
@ -266,20 +268,22 @@ check_parent:;
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage); rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
/* New root might be splitted while changing lock */ /* New root might be splitted while changing lock */
if (P_ISROOT(rootopaque)) if (P_ISROOT(rootopaque))
return(rootbuf); return (rootbuf);
/* rootbuf is read locked */ /* rootbuf is read locked */
goto check_parent; goto check_parent;
} }
else /* someone else already fixed root */ else
/* someone else already fixed root */
{ {
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK); LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_READ); LockBuffer(rootbuf, BT_READ);
} }
} }
/* /*
* Ok, here we have old root page with btpo_parent pointing * Ok, here we have old root page with btpo_parent pointing to
* to upper level - check parent page because of there is * upper level - check parent page because of there is good
* good chance that parent is root page. * chance that parent is root page.
*/ */
newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ); newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ);
_bt_relbuf(rel, rootbuf, BT_READ); _bt_relbuf(rel, rootbuf, BT_READ);
@ -287,7 +291,7 @@ check_parent:;
rootpage = BufferGetPage(rootbuf); rootpage = BufferGetPage(rootbuf);
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage); rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
if (P_ISROOT(rootopaque)) if (P_ISROOT(rootopaque))
return(rootbuf); return (rootbuf);
/* no luck -:( */ /* no luck -:( */
} }
@ -366,7 +370,7 @@ _bt_relbuf(Relation rel, Buffer buf, int access)
* and a pin on the buffer. * and a pin on the buffer.
* *
* NOTE: actually, the buffer manager just marks the shared buffer page * NOTE: actually, the buffer manager just marks the shared buffer page
* dirty here, the real I/O happens later. Since we can't persuade the * dirty here, the real I/O happens later. Since we can't persuade the
* Unix kernel to schedule disk writes in a particular order, there's not * Unix kernel to schedule disk writes in a particular order, there's not
* much point in worrying about this. The most we can say is that all the * much point in worrying about this. The most we can say is that all the
* writes will occur before commit. * writes will occur before commit.
@ -468,14 +472,14 @@ _bt_pagedel(Relation rel, ItemPointer tid)
PageIndexTupleDelete(page, offno); PageIndexTupleDelete(page, offno);
/* XLOG stuff */ /* XLOG stuff */
{ {
xl_btree_delete xlrec; xl_btree_delete xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
xlrec.target.node = rel->rd_node; xlrec.target.node = rel->rd_node;
xlrec.target.tid = *tid; xlrec.target.tid = *tid;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = SizeOfBtreeDelete; rdata[0].len = SizeOfBtreeDelete;
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.78 2001/02/07 23:35:33 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.79 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -30,7 +30,8 @@
bool BuildingBtree = false; /* see comment in btbuild() */ bool BuildingBtree = false; /* see comment in btbuild() */
bool FastBuild = true; /* use sort/build instead */ bool FastBuild = true; /* use sort/build instead */
/* of insertion build */
/* of insertion build */
/* /*
@ -52,12 +53,14 @@ static void _bt_restscan(IndexScanDesc scan);
Datum Datum
btbuild(PG_FUNCTION_ARGS) btbuild(PG_FUNCTION_ARGS)
{ {
Relation heap = (Relation) PG_GETARG_POINTER(0); Relation heap = (Relation) PG_GETARG_POINTER(0);
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -69,9 +72,11 @@ btbuild(PG_FUNCTION_ARGS)
int nhtups, int nhtups,
nitups; nitups;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -79,15 +84,16 @@ btbuild(PG_FUNCTION_ARGS)
BTItem btitem; BTItem btitem;
bool usefast; bool usefast;
Snapshot snapshot; Snapshot snapshot;
TransactionId XmaxRecent; TransactionId XmaxRecent;
/* /*
* spool2 is needed only when the index is an unique index. * spool2 is needed only when the index is an unique index. Dead
* Dead tuples are put into spool2 instead of spool in * tuples are put into spool2 instead of spool in order to avoid
* order to avoid uniqueness check. * uniqueness check.
*/ */
BTSpool *spool2 = NULL; BTSpool *spool2 = NULL;
bool tupleIsAlive; bool tupleIsAlive;
int dead_count; int dead_count;
/* note that this is a new btree */ /* note that this is a new btree */
BuildingBtree = true; BuildingBtree = true;
@ -103,7 +109,7 @@ btbuild(PG_FUNCTION_ARGS)
#ifdef BTREE_BUILD_STATS #ifdef BTREE_BUILD_STATS
if (Show_btree_build_stats) if (Show_btree_build_stats)
ResetUsage(); ResetUsage();
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
/* initialize the btree index metadata page (if this is a new index) */ /* initialize the btree index metadata page (if this is a new index) */
if (oldPred == NULL) if (oldPred == NULL)
@ -155,10 +161,10 @@ btbuild(PG_FUNCTION_ARGS)
if (usefast) if (usefast)
{ {
spool = _bt_spoolinit(index, indexInfo->ii_Unique); spool = _bt_spoolinit(index, indexInfo->ii_Unique);
/* /*
* Different from spool,the uniqueness isn't checked * Different from spool,the uniqueness isn't checked for spool2.
* for spool2. */
*/
if (indexInfo->ii_Unique) if (indexInfo->ii_Unique)
spool2 = _bt_spoolinit(index, false); spool2 = _bt_spoolinit(index, false);
} }
@ -187,12 +193,13 @@ btbuild(PG_FUNCTION_ARGS)
} }
else else
tupleIsAlive = true; tupleIsAlive = true;
MemoryContextReset(econtext->ecxt_per_tuple_memory); MemoryContextReset(econtext->ecxt_per_tuple_memory);
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -253,8 +260,7 @@ btbuild(PG_FUNCTION_ARGS)
* btree pages - NULLs greater NOT_NULLs and NULL = NULL is TRUE. * btree pages - NULLs greater NOT_NULLs and NULL = NULL is TRUE.
* Sure, it's just rule for placing/finding items and no more - * Sure, it's just rule for placing/finding items and no more -
* keytest'll return FALSE for a = 5 for items having 'a' isNULL. * keytest'll return FALSE for a = 5 for items having 'a' isNULL.
* Look at _bt_compare for how it works. * Look at _bt_compare for how it works. - vadim 03/23/97
* - vadim 03/23/97
* *
* if (itup->t_info & INDEX_NULL_MASK) { pfree(itup); continue; } * if (itup->t_info & INDEX_NULL_MASK) { pfree(itup); continue; }
*/ */
@ -271,7 +277,8 @@ btbuild(PG_FUNCTION_ARGS)
{ {
if (tupleIsAlive || !spool2) if (tupleIsAlive || !spool2)
_bt_spool(btitem, spool); _bt_spool(btitem, spool);
else /* dead tuples are put into spool2 */ else
/* dead tuples are put into spool2 */
{ {
dead_count++; dead_count++;
_bt_spool(btitem, spool2); _bt_spool(btitem, spool2);
@ -288,7 +295,7 @@ btbuild(PG_FUNCTION_ARGS)
/* okay, all heap tuples are indexed */ /* okay, all heap tuples are indexed */
heap_endscan(hscan); heap_endscan(hscan);
if (spool2 && !dead_count) /* spool2 was found to be unnecessary */ if (spool2 && !dead_count) /* spool2 was found to be unnecessary */
{ {
_bt_spooldestroy(spool2); _bt_spooldestroy(spool2);
spool2 = NULL; spool2 = NULL;
@ -296,9 +303,7 @@ btbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -322,7 +327,7 @@ btbuild(PG_FUNCTION_ARGS)
ShowUsage(); ShowUsage();
ResetUsage(); ResetUsage();
} }
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
/* /*
* Since we just counted the tuples in the heap, we update its stats * Since we just counted the tuples in the heap, we update its stats
@ -368,11 +373,11 @@ btbuild(PG_FUNCTION_ARGS)
Datum Datum
btinsert(PG_FUNCTION_ARGS) btinsert(PG_FUNCTION_ARGS)
{ {
Relation rel = (Relation) PG_GETARG_POINTER(0); Relation rel = (Relation) PG_GETARG_POINTER(0);
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
InsertIndexResult res; InsertIndexResult res;
BTItem btitem; BTItem btitem;
IndexTuple itup; IndexTuple itup;
@ -396,8 +401,8 @@ btinsert(PG_FUNCTION_ARGS)
Datum Datum
btgettuple(PG_FUNCTION_ARGS) btgettuple(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
RetrieveIndexResult res; RetrieveIndexResult res;
/* /*
@ -408,10 +413,11 @@ btgettuple(PG_FUNCTION_ARGS)
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(scan->currentItemData)))
{ {
/* /*
* Restore scan position using heap TID returned by previous call * Restore scan position using heap TID returned by previous call
* to btgettuple(). _bt_restscan() re-grabs the read lock on * to btgettuple(). _bt_restscan() re-grabs the read lock on the
* the buffer, too. * buffer, too.
*/ */
_bt_restscan(scan); _bt_restscan(scan);
res = _bt_next(scan, dir); res = _bt_next(scan, dir);
@ -421,8 +427,8 @@ btgettuple(PG_FUNCTION_ARGS)
/* /*
* Save heap TID to use it in _bt_restscan. Then release the read * Save heap TID to use it in _bt_restscan. Then release the read
* lock on the buffer so that we aren't blocking other backends. * lock on the buffer so that we aren't blocking other backends. NOTE:
* NOTE: we do keep the pin on the buffer! * we do keep the pin on the buffer!
*/ */
if (res) if (res)
{ {
@ -461,11 +467,13 @@ btbeginscan(PG_FUNCTION_ARGS)
Datum Datum
btrescan(PG_FUNCTION_ARGS) btrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;
BTScanOpaque so; BTScanOpaque so;
@ -540,7 +548,7 @@ btmovescan(IndexScanDesc scan, Datum v)
Datum Datum
btendscan(PG_FUNCTION_ARGS) btendscan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
BTScanOpaque so; BTScanOpaque so;
@ -578,7 +586,7 @@ btendscan(PG_FUNCTION_ARGS)
Datum Datum
btmarkpos(PG_FUNCTION_ARGS) btmarkpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
BTScanOpaque so; BTScanOpaque so;
@ -610,7 +618,7 @@ btmarkpos(PG_FUNCTION_ARGS)
Datum Datum
btrestrpos(PG_FUNCTION_ARGS) btrestrpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
ItemPointer iptr; ItemPointer iptr;
BTScanOpaque so; BTScanOpaque so;
@ -640,8 +648,8 @@ btrestrpos(PG_FUNCTION_ARGS)
Datum Datum
btdelete(PG_FUNCTION_ARGS) btdelete(PG_FUNCTION_ARGS)
{ {
Relation rel = (Relation) PG_GETARG_POINTER(0); Relation rel = (Relation) PG_GETARG_POINTER(0);
ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1); ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1);
/* adjust any active scans that will be affected by this deletion */ /* adjust any active scans that will be affected by this deletion */
_bt_adjscans(rel, tid); _bt_adjscans(rel, tid);
@ -671,8 +679,8 @@ _bt_restscan(IndexScanDesc scan)
BlockNumber blkno; BlockNumber blkno;
/* /*
* Get back the read lock we were holding on the buffer. * Get back the read lock we were holding on the buffer. (We still
* (We still have a reference-count pin on it, though.) * have a reference-count pin on it, though.)
*/ */
LockBuffer(buf, BT_READ); LockBuffer(buf, BT_READ);
@ -689,13 +697,13 @@ _bt_restscan(IndexScanDesc scan)
if (!ItemPointerIsValid(&target)) if (!ItemPointerIsValid(&target))
{ {
ItemPointerSetOffsetNumber(current, ItemPointerSetOffsetNumber(current,
OffsetNumberPrev(P_FIRSTDATAKEY(opaque))); OffsetNumberPrev(P_FIRSTDATAKEY(opaque)));
return; return;
} }
/* /*
* The item we were on may have moved right due to insertions. * The item we were on may have moved right due to insertions. Find it
* Find it again. * again.
*/ */
for (;;) for (;;)
{ {
@ -717,7 +725,8 @@ _bt_restscan(IndexScanDesc scan)
} }
/* /*
* By here, the item we're looking for moved right at least one page * By here, the item we're looking for moved right at least one
* page
*/ */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!" elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!"
@ -742,14 +751,14 @@ _bt_restore_page(Page page, char *from, int len)
Size itemsz; Size itemsz;
char *end = from + len; char *end = from + len;
for ( ; from < end; ) for (; from < end;)
{ {
memcpy(&btdata, from, sizeof(BTItemData)); memcpy(&btdata, from, sizeof(BTItemData));
itemsz = IndexTupleDSize(btdata.bti_itup) + itemsz = IndexTupleDSize(btdata.bti_itup) +
(sizeof(BTItemData) - sizeof(IndexTupleData)); (sizeof(BTItemData) - sizeof(IndexTupleData));
itemsz = MAXALIGN(itemsz); itemsz = MAXALIGN(itemsz);
if (PageAddItem(page, (Item) from, itemsz, if (PageAddItem(page, (Item) from, itemsz,
FirstOffsetNumber, LP_USED) == InvalidOffsetNumber) FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
elog(STOP, "_bt_restore_page: can't add item to page"); elog(STOP, "_bt_restore_page: can't add item to page");
from += itemsz; from += itemsz;
} }
@ -758,20 +767,20 @@ _bt_restore_page(Page page, char *from, int len)
static void static void
btree_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record) btree_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_delete *xlrec; xl_btree_delete *xlrec;
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1)) if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
return; return;
xlrec = (xl_btree_delete*) XLogRecGetData(record); xlrec = (xl_btree_delete *) XLogRecGetData(record);
reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node); reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node);
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return; return;
buffer = XLogReadBuffer(false, reln, buffer = XLogReadBuffer(false, reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "btree_delete_redo: block unfound"); elog(STOP, "btree_delete_redo: block unfound");
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
@ -796,21 +805,21 @@ btree_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
static void static void
btree_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record) btree_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_insert *xlrec; xl_btree_insert *xlrec;
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
BTPageOpaque pageop; BTPageOpaque pageop;
if (redo && (record->xl_info & XLR_BKP_BLOCK_1)) if (redo && (record->xl_info & XLR_BKP_BLOCK_1))
return; return;
xlrec = (xl_btree_insert*) XLogRecGetData(record); xlrec = (xl_btree_insert *) XLogRecGetData(record);
reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node); reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node);
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return; return;
buffer = XLogReadBuffer(false, reln, buffer = XLogReadBuffer(false, reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "btree_insert_%sdo: block unfound", (redo) ? "re" : "un"); elog(STOP, "btree_insert_%sdo: block unfound", (redo) ? "re" : "un");
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
@ -825,11 +834,11 @@ btree_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return; return;
} }
if (PageAddItem(page, (Item)((char*)xlrec + SizeOfBtreeInsert), if (PageAddItem(page, (Item) ((char *) xlrec + SizeOfBtreeInsert),
record->xl_len - SizeOfBtreeInsert, record->xl_len - SizeOfBtreeInsert,
ItemPointerGetOffsetNumber(&(xlrec->target.tid)), ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
elog(STOP, "btree_insert_redo: failed to add item"); elog(STOP, "btree_insert_redo: failed to add item");
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
@ -840,7 +849,7 @@ btree_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (XLByteLT(PageGetLSN(page), lsn)) if (XLByteLT(PageGetLSN(page), lsn))
elog(STOP, "btree_insert_undo: bad page LSN"); elog(STOP, "btree_insert_undo: bad page LSN");
if (! P_ISLEAF(pageop)) if (!P_ISLEAF(pageop))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return; return;
@ -855,14 +864,14 @@ btree_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
static void static void
btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record) btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_split *xlrec = (xl_btree_split*) XLogRecGetData(record); xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record);
Relation reln; Relation reln;
BlockNumber blkno; BlockNumber blkno;
Buffer buffer; Buffer buffer;
Page page; Page page;
BTPageOpaque pageop; BTPageOpaque pageop;
char *op = (redo) ? "redo" : "undo"; char *op = (redo) ? "redo" : "undo";
bool isleaf = (record->xl_info & XLOG_BTREE_LEAF); bool isleaf = (record->xl_info & XLOG_BTREE_LEAF);
reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node); reln = XLogOpenRelation(redo, RM_BTREE_ID, xlrec->target.node);
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
@ -870,7 +879,7 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
/* Left (original) sibling */ /* Left (original) sibling */
blkno = (onleft) ? ItemPointerGetBlockNumber(&(xlrec->target.tid)) : blkno = (onleft) ? ItemPointerGetBlockNumber(&(xlrec->target.tid)) :
BlockIdGetBlockNumber(&(xlrec->otherblk)); BlockIdGetBlockNumber(&(xlrec->otherblk));
buffer = XLogReadBuffer(false, reln, blkno); buffer = XLogReadBuffer(false, reln, blkno);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "btree_split_%s: lost left sibling", op); elog(STOP, "btree_split_%s: lost left sibling", op);
@ -892,13 +901,14 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
pageop->btpo_next = ItemPointerGetBlockNumber(&(xlrec->target.tid)); pageop->btpo_next = ItemPointerGetBlockNumber(&(xlrec->target.tid));
pageop->btpo_flags = (isleaf) ? BTP_LEAF : 0; pageop->btpo_flags = (isleaf) ? BTP_LEAF : 0;
_bt_restore_page(page, (char*)xlrec + SizeOfBtreeSplit, xlrec->leftlen); _bt_restore_page(page, (char *) xlrec + SizeOfBtreeSplit, xlrec->leftlen);
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
} }
else /* undo */ else
/* undo */
{ {
if (XLByteLT(PageGetLSN(page), lsn)) if (XLByteLT(PageGetLSN(page), lsn))
elog(STOP, "btree_split_undo: bad left sibling LSN"); elog(STOP, "btree_split_undo: bad left sibling LSN");
@ -906,8 +916,8 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
} }
/* Right (new) sibling */ /* Right (new) sibling */
blkno = (onleft) ? BlockIdGetBlockNumber(&(xlrec->otherblk)) : blkno = (onleft) ? BlockIdGetBlockNumber(&(xlrec->otherblk)) :
ItemPointerGetBlockNumber(&(xlrec->target.tid)); ItemPointerGetBlockNumber(&(xlrec->target.tid));
buffer = XLogReadBuffer((redo) ? true : false, reln, blkno); buffer = XLogReadBuffer((redo) ? true : false, reln, blkno);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "btree_split_%s: lost right sibling", op); elog(STOP, "btree_split_%s: lost right sibling", op);
@ -922,21 +932,22 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
if (redo) if (redo)
{ {
pageop->btpo_parent = BlockIdGetBlockNumber(&(xlrec->parentblk)); pageop->btpo_parent = BlockIdGetBlockNumber(&(xlrec->parentblk));
pageop->btpo_prev = (onleft) ? pageop->btpo_prev = (onleft) ?
ItemPointerGetBlockNumber(&(xlrec->target.tid)) : ItemPointerGetBlockNumber(&(xlrec->target.tid)) :
BlockIdGetBlockNumber(&(xlrec->otherblk)); BlockIdGetBlockNumber(&(xlrec->otherblk));
pageop->btpo_next = BlockIdGetBlockNumber(&(xlrec->rightblk)); pageop->btpo_next = BlockIdGetBlockNumber(&(xlrec->rightblk));
pageop->btpo_flags = (isleaf) ? BTP_LEAF : 0; pageop->btpo_flags = (isleaf) ? BTP_LEAF : 0;
_bt_restore_page(page, _bt_restore_page(page,
(char*)xlrec + SizeOfBtreeSplit + xlrec->leftlen, (char *) xlrec + SizeOfBtreeSplit + xlrec->leftlen,
record->xl_len - SizeOfBtreeSplit - xlrec->leftlen); record->xl_len - SizeOfBtreeSplit - xlrec->leftlen);
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
UnlockAndWriteBuffer(buffer); UnlockAndWriteBuffer(buffer);
} }
else /* undo */ else
/* undo */
{ {
if (XLByteLT(PageGetLSN(page), lsn)) if (XLByteLT(PageGetLSN(page), lsn))
elog(STOP, "btree_split_undo: bad right sibling LSN"); elog(STOP, "btree_split_undo: bad right sibling LSN");
@ -965,9 +976,9 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
return; return;
} }
pageop = (BTPageOpaque) PageGetSpecialPointer(page); pageop = (BTPageOpaque) PageGetSpecialPointer(page);
pageop->btpo_prev = (onleft) ? pageop->btpo_prev = (onleft) ?
BlockIdGetBlockNumber(&(xlrec->otherblk)) : BlockIdGetBlockNumber(&(xlrec->otherblk)) :
ItemPointerGetBlockNumber(&(xlrec->target.tid)); ItemPointerGetBlockNumber(&(xlrec->target.tid));
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
@ -977,14 +988,14 @@ btree_xlog_split(bool redo, bool onleft, XLogRecPtr lsn, XLogRecord *record)
static void static void
btree_xlog_newroot(bool redo, XLogRecPtr lsn, XLogRecord *record) btree_xlog_newroot(bool redo, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_newroot *xlrec = (xl_btree_newroot*) XLogRecGetData(record); xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record);
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
BTPageOpaque pageop; BTPageOpaque pageop;
Buffer metabuf; Buffer metabuf;
Page metapg; Page metapg;
BTMetaPageData md; BTMetaPageData md;
if (!redo) if (!redo)
return; return;
@ -1011,8 +1022,8 @@ btree_xlog_newroot(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (record->xl_len > SizeOfBtreeNewroot) if (record->xl_len > SizeOfBtreeNewroot)
_bt_restore_page(page, _bt_restore_page(page,
(char*)xlrec + SizeOfBtreeNewroot, (char *) xlrec + SizeOfBtreeNewroot,
record->xl_len - SizeOfBtreeNewroot); record->xl_len - SizeOfBtreeNewroot);
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
@ -1037,7 +1048,7 @@ btree_xlog_newroot(bool redo, XLogRecPtr lsn, XLogRecord *record)
void void
btree_redo(XLogRecPtr lsn, XLogRecord *record) btree_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
info &= ~XLOG_BTREE_LEAF; info &= ~XLOG_BTREE_LEAF;
if (info == XLOG_BTREE_DELETE) if (info == XLOG_BTREE_DELETE)
@ -1045,9 +1056,9 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
else if (info == XLOG_BTREE_INSERT) else if (info == XLOG_BTREE_INSERT)
btree_xlog_insert(true, lsn, record); btree_xlog_insert(true, lsn, record);
else if (info == XLOG_BTREE_SPLIT) else if (info == XLOG_BTREE_SPLIT)
btree_xlog_split(true, false, lsn, record); /* new item on the right */ btree_xlog_split(true, false, lsn, record); /* new item on the right */
else if (info == XLOG_BTREE_SPLEFT) else if (info == XLOG_BTREE_SPLEFT)
btree_xlog_split(true, true, lsn, record); /* new item on the left */ btree_xlog_split(true, true, lsn, record); /* new item on the left */
else if (info == XLOG_BTREE_NEWROOT) else if (info == XLOG_BTREE_NEWROOT)
btree_xlog_newroot(true, lsn, record); btree_xlog_newroot(true, lsn, record);
else else
@ -1057,7 +1068,7 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
void void
btree_undo(XLogRecPtr lsn, XLogRecord *record) btree_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
info &= ~XLOG_BTREE_LEAF; info &= ~XLOG_BTREE_LEAF;
if (info == XLOG_BTREE_DELETE) if (info == XLOG_BTREE_DELETE)
@ -1065,9 +1076,9 @@ btree_undo(XLogRecPtr lsn, XLogRecord *record)
else if (info == XLOG_BTREE_INSERT) else if (info == XLOG_BTREE_INSERT)
btree_xlog_insert(false, lsn, record); btree_xlog_insert(false, lsn, record);
else if (info == XLOG_BTREE_SPLIT) else if (info == XLOG_BTREE_SPLIT)
btree_xlog_split(false, false, lsn, record);/* new item on the right */ btree_xlog_split(false, false, lsn, record); /* new item on the right */
else if (info == XLOG_BTREE_SPLEFT) else if (info == XLOG_BTREE_SPLEFT)
btree_xlog_split(false, true, lsn, record); /* new item on the left */ btree_xlog_split(false, true, lsn, record); /* new item on the left */
else if (info == XLOG_BTREE_NEWROOT) else if (info == XLOG_BTREE_NEWROOT)
btree_xlog_newroot(false, lsn, record); btree_xlog_newroot(false, lsn, record);
else else
@ -1078,45 +1089,49 @@ static void
out_target(char *buf, xl_btreetid *target) out_target(char *buf, xl_btreetid *target)
{ {
sprintf(buf + strlen(buf), "node %u/%u; tid %u/%u", sprintf(buf + strlen(buf), "node %u/%u; tid %u/%u",
target->node.tblNode, target->node.relNode, target->node.tblNode, target->node.relNode,
ItemPointerGetBlockNumber(&(target->tid)), ItemPointerGetBlockNumber(&(target->tid)),
ItemPointerGetOffsetNumber(&(target->tid))); ItemPointerGetOffsetNumber(&(target->tid)));
} }
void void
btree_desc(char *buf, uint8 xl_info, char* rec) btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
info &= ~XLOG_BTREE_LEAF; info &= ~XLOG_BTREE_LEAF;
if (info == XLOG_BTREE_INSERT) if (info == XLOG_BTREE_INSERT)
{ {
xl_btree_insert *xlrec = (xl_btree_insert*) rec; xl_btree_insert *xlrec = (xl_btree_insert *) rec;
strcat(buf, "insert: "); strcat(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_BTREE_DELETE) else if (info == XLOG_BTREE_DELETE)
{ {
xl_btree_delete *xlrec = (xl_btree_delete*) rec; xl_btree_delete *xlrec = (xl_btree_delete *) rec;
strcat(buf, "delete: "); strcat(buf, "delete: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_BTREE_SPLIT || info == XLOG_BTREE_SPLEFT) else if (info == XLOG_BTREE_SPLIT || info == XLOG_BTREE_SPLEFT)
{ {
xl_btree_split *xlrec = (xl_btree_split*) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
sprintf(buf + strlen(buf), "split(%s): ",
(info == XLOG_BTREE_SPLIT) ? "right" : "left"); sprintf(buf + strlen(buf), "split(%s): ",
(info == XLOG_BTREE_SPLIT) ? "right" : "left");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; oth %u; rgh %u", sprintf(buf + strlen(buf), "; oth %u; rgh %u",
BlockIdGetBlockNumber(&xlrec->otherblk), BlockIdGetBlockNumber(&xlrec->otherblk),
BlockIdGetBlockNumber(&xlrec->rightblk)); BlockIdGetBlockNumber(&xlrec->rightblk));
} }
else if (info == XLOG_BTREE_NEWROOT) else if (info == XLOG_BTREE_NEWROOT)
{ {
xl_btree_newroot *xlrec = (xl_btree_newroot*) rec; xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
sprintf(buf + strlen(buf), "root: node %u/%u; blk %u", sprintf(buf + strlen(buf), "root: node %u/%u; blk %u",
xlrec->node.tblNode, xlrec->node.relNode, xlrec->node.tblNode, xlrec->node.relNode,
BlockIdGetBlockNumber(&xlrec->rootblk)); BlockIdGetBlockNumber(&xlrec->rootblk));
} }
else else
strcat(buf, "UNKNOWN"); strcat(buf, "UNKNOWN");

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.63 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.64 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -32,20 +32,20 @@ static RetrieveIndexResult _bt_endpoint(IndexScanDesc scan, ScanDirection dir);
* *
* NOTE that the returned buffer is read-locked regardless of the access * NOTE that the returned buffer is read-locked regardless of the access
* parameter. However, access = BT_WRITE will allow an empty root page * parameter. However, access = BT_WRITE will allow an empty root page
* to be created and returned. When access = BT_READ, an empty index * to be created and returned. When access = BT_READ, an empty index
* will result in *bufP being set to InvalidBuffer. * will result in *bufP being set to InvalidBuffer.
*/ */
BTStack BTStack
_bt_search(Relation rel, int keysz, ScanKey scankey, _bt_search(Relation rel, int keysz, ScanKey scankey,
Buffer *bufP, int access) Buffer *bufP, int access)
{ {
BTStack stack_in = NULL; BTStack stack_in = NULL;
/* Get the root page to start with */ /* Get the root page to start with */
*bufP = _bt_getroot(rel, access); *bufP = _bt_getroot(rel, access);
/* If index is empty and access = BT_READ, no root page is created. */ /* If index is empty and access = BT_READ, no root page is created. */
if (! BufferIsValid(*bufP)) if (!BufferIsValid(*bufP))
return (BTStack) NULL; return (BTStack) NULL;
/* Loop iterates once per level descended in the tree */ /* Loop iterates once per level descended in the tree */
@ -79,13 +79,13 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
par_blkno = BufferGetBlockNumber(*bufP); par_blkno = BufferGetBlockNumber(*bufP);
/* /*
* We need to save the bit image of the index entry we chose in the * We need to save the bit image of the index entry we chose in
* parent page on a stack. In case we split the tree, we'll use this * the parent page on a stack. In case we split the tree, we'll
* bit image to figure out what our real parent page is, in case the * use this bit image to figure out what our real parent page is,
* parent splits while we're working lower in the tree. See the paper * in case the parent splits while we're working lower in the
* by Lehman and Yao for how this is detected and handled. (We use the * tree. See the paper by Lehman and Yao for how this is detected
* child link to disambiguate duplicate keys in the index -- Lehman * and handled. (We use the child link to disambiguate duplicate
* and Yao disallow duplicate keys.) * keys in the index -- Lehman and Yao disallow duplicate keys.)
*/ */
new_stack = (BTStack) palloc(sizeof(BTStackData)); new_stack = (BTStack) palloc(sizeof(BTStackData));
new_stack->bts_blkno = par_blkno; new_stack->bts_blkno = par_blkno;
@ -98,9 +98,9 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
/* /*
* Race -- the page we just grabbed may have split since we read its * Race -- the page we just grabbed may have split since we read
* pointer in the parent. If it has, we may need to move right to its * its pointer in the parent. If it has, we may need to move
* new sibling. Do that. * right to its new sibling. Do that.
*/ */
*bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ); *bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ);
@ -127,7 +127,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
* *
* On entry, we have the buffer pinned and a lock of the proper type. * On entry, we have the buffer pinned and a lock of the proper type.
* If we move right, we release the buffer and lock and acquire the * If we move right, we release the buffer and lock and acquire the
* same on the right sibling. Return value is the buffer we stop at. * same on the right sibling. Return value is the buffer we stop at.
*/ */
Buffer Buffer
_bt_moveright(Relation rel, _bt_moveright(Relation rel,
@ -153,7 +153,7 @@ _bt_moveright(Relation rel,
_bt_compare(rel, keysz, scankey, page, P_HIKEY) > 0) _bt_compare(rel, keysz, scankey, page, P_HIKEY) > 0)
{ {
/* step right one page */ /* step right one page */
BlockNumber rblkno = opaque->btpo_next; BlockNumber rblkno = opaque->btpo_next;
_bt_relbuf(rel, buf, access); _bt_relbuf(rel, buf, access);
buf = _bt_getbuf(rel, rblkno, access); buf = _bt_getbuf(rel, rblkno, access);
@ -184,7 +184,7 @@ _bt_moveright(Relation rel,
* find all leaf keys >= given scankey. * find all leaf keys >= given scankey.
* *
* This procedure is not responsible for walking right, it just examines * This procedure is not responsible for walking right, it just examines
* the given page. _bt_binsrch() has no lock or refcount side effects * the given page. _bt_binsrch() has no lock or refcount side effects
* on the buffer. * on the buffer.
*/ */
OffsetNumber OffsetNumber
@ -299,7 +299,7 @@ _bt_compare(Relation rel,
* 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 --- see NOTE above. * page --- see NOTE above.
*/ */
if (! P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque)) if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque))
return 1; return 1;
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
@ -327,7 +327,7 @@ _bt_compare(Relation rel,
datum = index_getattr(itup, entry->sk_attno, itupdesc, &isNull); datum = index_getattr(itup, entry->sk_attno, itupdesc, &isNull);
/* see comments about NULLs handling in btbuild */ /* see comments about NULLs handling in btbuild */
if (entry->sk_flags & SK_ISNULL) /* key is NULL */ if (entry->sk_flags & SK_ISNULL) /* key is NULL */
{ {
if (isNull) if (isNull)
result = 0; /* NULL "=" NULL */ result = 0; /* NULL "=" NULL */
@ -458,10 +458,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
_bt_orderkeys(rel, so); _bt_orderkeys(rel, so);
/* /*
* Quit now if _bt_orderkeys() discovered that the scan keys can * Quit now if _bt_orderkeys() discovered that the scan keys can never
* never be satisfied (eg, x == 1 AND x > 2). * be satisfied (eg, x == 1 AND x > 2).
*/ */
if (! so->qual_ok) if (!so->qual_ok)
return (RetrieveIndexResult) NULL; return (RetrieveIndexResult) NULL;
/* /*
@ -484,17 +484,16 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
strat = _bt_getstrat(rel, attno, strat = _bt_getstrat(rel, attno,
so->keyData[i].sk_procedure); so->keyData[i].sk_procedure);
/* /*
* Can we use this key as a starting boundary for this attr? * Can we use this key as a starting boundary for this attr?
* *
* We can use multiple keys if they look like, say, = >= = * We can use multiple keys if they look like, say, = >= = but we
* but we have to stop after accepting a > or < boundary. * have to stop after accepting a > or < boundary.
*/ */
if (strat == strat_total || if (strat == strat_total ||
strat == BTEqualStrategyNumber) strat == BTEqualStrategyNumber)
{
nKeyIs[keysCount++] = i; nKeyIs[keysCount++] = i;
}
else if (ScanDirectionIsBackward(dir) && else if (ScanDirectionIsBackward(dir) &&
(strat == BTLessStrategyNumber || (strat == BTLessStrategyNumber ||
strat == BTLessEqualStrategyNumber)) strat == BTLessEqualStrategyNumber))
@ -536,7 +535,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
for (i = 0; i < keysCount; i++) for (i = 0; i < keysCount; i++)
{ {
j = nKeyIs[i]; j = nKeyIs[i];
/* _bt_orderkeys disallows it, but it's place to add some code later */
/*
* _bt_orderkeys disallows it, but it's place to add some code
* later
*/
if (so->keyData[j].sk_flags & SK_ISNULL) if (so->keyData[j].sk_flags & SK_ISNULL)
{ {
pfree(nKeyIs); pfree(nKeyIs);
@ -562,7 +565,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* don't need to keep the stack around... */ /* don't need to keep the stack around... */
_bt_freestack(stack); _bt_freestack(stack);
if (! BufferIsValid(buf)) if (!BufferIsValid(buf))
{ {
/* Only get here if index is completely empty */ /* Only get here if index is completely empty */
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
@ -601,6 +604,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
switch (strat_total) switch (strat_total)
{ {
case BTLessStrategyNumber: case BTLessStrategyNumber:
/* /*
* Back up one to arrive at last item < scankey * Back up one to arrive at last item < scankey
*/ */
@ -612,6 +616,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTLessEqualStrategyNumber: case BTLessEqualStrategyNumber:
/* /*
* We need to find the last item <= scankey, so step forward * We need to find the last item <= scankey, so step forward
* till we find one > scankey, then step back one. * till we find one > scankey, then step back one.
@ -645,9 +650,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTEqualStrategyNumber: case BTEqualStrategyNumber:
/* /*
* Make sure we are on the first equal item; might have to step * Make sure we are on the first equal item; might have to
* forward if currently at end of page. * step forward if currently at end of page.
*/ */
if (offnum > PageGetMaxOffsetNumber(page)) if (offnum > PageGetMaxOffsetNumber(page))
{ {
@ -661,7 +667,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
} }
result = _bt_compare(rel, keysCount, scankeys, page, offnum); result = _bt_compare(rel, keysCount, scankeys, page, offnum);
if (result != 0) if (result != 0)
goto nomatches; /* no equal items! */ goto nomatches; /* no equal items! */
/* /*
* If a backward scan was specified, need to start with last * If a backward scan was specified, need to start with last
* equal item not first one. * equal item not first one.
@ -685,6 +692,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTGreaterEqualStrategyNumber: case BTGreaterEqualStrategyNumber:
/* /*
* We want the first item >= scankey, which is where we are... * We want the first item >= scankey, which is where we are...
* unless we're not anywhere at all... * unless we're not anywhere at all...
@ -700,9 +708,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
break; break;
case BTGreaterStrategyNumber: case BTGreaterStrategyNumber:
/* /*
* We want the first item > scankey, so make sure we are on * We want the first item > scankey, so make sure we are on an
* an item and then step over any equal items. * item and then step over any equal items.
*/ */
if (offnum > PageGetMaxOffsetNumber(page)) if (offnum > PageGetMaxOffsetNumber(page))
{ {
@ -850,11 +859,12 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP); page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
/* /*
* If the adjacent page just split, then we have to walk * If the adjacent page just split, then we have to walk
* right to find the block that's now adjacent to where * right to find the block that's now adjacent to where we
* we were. Because pages only split right, we don't have * were. Because pages only split right, we don't have to
* to worry about this failing to terminate. * worry about this failing to terminate.
*/ */
while (opaque->btpo_next != obknum) while (opaque->btpo_next != obknum)
{ {
@ -912,12 +922,12 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* /*
* 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 version of _bt_search(). We don't maintain a stack * simplified version of _bt_search(). We don't maintain a stack
* since we know we won't need it. * since we know we won't need it.
*/ */
buf = _bt_getroot(rel, BT_READ); buf = _bt_getroot(rel, BT_READ);
if (! BufferIsValid(buf)) if (!BufferIsValid(buf))
{ {
/* empty index... */ /* empty index... */
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
@ -981,7 +991,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
Assert(P_RIGHTMOST(opaque)); Assert(P_RIGHTMOST(opaque));
start = PageGetMaxOffsetNumber(page); start = PageGetMaxOffsetNumber(page);
if (start < P_FIRSTDATAKEY(opaque)) /* watch out for empty page */ if (start < P_FIRSTDATAKEY(opaque)) /* watch out for empty
* page */
start = P_FIRSTDATAKEY(opaque); start = P_FIRSTDATAKEY(opaque);
} }
else else
@ -995,8 +1006,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
so->btso_curbuf = buf; so->btso_curbuf = buf;
/* /*
* Left/rightmost page could be empty due to deletions, * Left/rightmost page could be empty due to deletions, if so step
* if so step till we find a nonempty page. * till we find a nonempty page.
*/ */
if (start > maxoff) if (start > maxoff)
{ {

View File

@ -6,7 +6,7 @@
* *
* We use tuplesort.c to sort the given index tuples into order. * We use tuplesort.c to sort the given index tuples into order.
* Then we scan the index tuples in order and build the btree pages * Then we scan the index tuples in order and build the btree pages
* for each level. We load source tuples into leaf-level pages. * for each level. We load source tuples into leaf-level pages.
* Whenever we fill a page at one level, we add a link to it to its * Whenever we fill a page at one level, we add a link to it to its
* parent level (starting a new parent level if necessary). When * parent level (starting a new parent level if necessary). When
* done, we write out each final page on each level, adding it to * done, we write out each final page on each level, adding it to
@ -35,7 +35,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.59 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.60 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -57,7 +57,7 @@ struct BTSpool
}; };
/* /*
* Status record for a btree page being built. We have one of these * Status record for a btree page being built. We have one of these
* for each active tree level. * for each active tree level.
* *
* The reason we need to store a copy of the minimum key is that we'll * The reason we need to store a copy of the minimum key is that we'll
@ -73,11 +73,13 @@ typedef struct BTPageState
{ {
Buffer btps_buf; /* current buffer & page */ Buffer btps_buf; /* current buffer & page */
Page btps_page; Page btps_page;
BTItem btps_minkey; /* copy of minimum key (first item) on page */ BTItem btps_minkey; /* copy of minimum key (first item) on
* page */
OffsetNumber btps_lastoff; /* last item offset loaded */ OffsetNumber btps_lastoff; /* last item offset loaded */
int btps_level; /* tree level (0 = leaf) */ int btps_level; /* tree level (0 = leaf) */
Size btps_full; /* "full" if less than this much free space */ Size btps_full; /* "full" if less than this much free
struct BTPageState *btps_next; /* link to parent level, if any */ * space */
struct BTPageState *btps_next; /* link to parent level, if any */
} BTPageState; } BTPageState;
@ -92,7 +94,7 @@ static void _bt_blnewpage(Relation index, Buffer *buf, Page *page, int flags);
static BTPageState *_bt_pagestate(Relation index, int flags, int level); static BTPageState *_bt_pagestate(Relation index, int flags, int level);
static void _bt_slideleft(Relation index, Buffer buf, Page page); static void _bt_slideleft(Relation index, Buffer buf, Page page);
static void _bt_sortaddtup(Page page, Size itemsize, static void _bt_sortaddtup(Page page, Size itemsize,
BTItem btitem, OffsetNumber itup_off); BTItem btitem, OffsetNumber itup_off);
static void _bt_buildadd(Relation index, BTPageState *state, BTItem bti); static void _bt_buildadd(Relation index, BTPageState *state, BTItem bti);
static void _bt_uppershutdown(Relation index, BTPageState *state); static void _bt_uppershutdown(Relation index, BTPageState *state);
static void _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2); static void _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2);
@ -162,7 +164,7 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
ShowUsage(); ShowUsage();
ResetUsage(); ResetUsage();
} }
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
tuplesort_performsort(btspool->sortstate); tuplesort_performsort(btspool->sortstate);
if (btspool2) if (btspool2)
@ -269,9 +271,9 @@ _bt_sortaddtup(Page page,
OffsetNumber itup_off) OffsetNumber itup_off)
{ {
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
BTItemData truncitem; BTItemData truncitem;
if (! P_ISLEAF(opaque) && itup_off == P_FIRSTKEY) if (!P_ISLEAF(opaque) && itup_off == P_FIRSTKEY)
{ {
memcpy(&truncitem, btitem, sizeof(BTItemData)); memcpy(&truncitem, btitem, sizeof(BTItemData));
truncitem.bti_itup.t_info = sizeof(BTItemData); truncitem.bti_itup.t_info = sizeof(BTItemData);
@ -290,7 +292,7 @@ _bt_sortaddtup(Page page,
* We must be careful to observe the page layout conventions of nbtsearch.c: * We must be careful to observe the page layout conventions of nbtsearch.c:
* - rightmost pages start data items at P_HIKEY instead of at P_FIRSTKEY. * - rightmost pages start data items at P_HIKEY instead of at P_FIRSTKEY.
* - on non-leaf pages, the key portion of the first item need not be * - on non-leaf pages, the key portion of the first item need not be
* stored, we should store only the link. * stored, we should store only the link.
* *
* A leaf page being built looks like: * A leaf page being built looks like:
* *
@ -347,11 +349,12 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
*/ */
if (btisz > (PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)) if (btisz > (PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData))
elog(ERROR, "btree: index item size %lu exceeds maximum %ld", elog(ERROR, "btree: index item size %lu exceeds maximum %ld",
(unsigned long)btisz, (unsigned long) btisz,
(PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) /3 - sizeof(ItemIdData)); (PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData));
if (pgspc < btisz || pgspc < state->btps_full) if (pgspc < btisz || pgspc < state->btps_full)
{ {
/* /*
* Item won't fit on this page, or we feel the page is full enough * Item won't fit on this page, or we feel the page is full enough
* already. Finish off the page and write it out. * already. Finish off the page and write it out.
@ -388,9 +391,9 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
((PageHeader) opage)->pd_lower -= sizeof(ItemIdData); ((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
/* /*
* Link the old buffer into its parent, using its minimum key. * Link the old buffer into its parent, using its minimum key. If
* If we don't have a parent, we have to create one; * we don't have a parent, we have to create one; this adds a new
* this adds a new btree level. * btree level.
*/ */
if (state->btps_next == (BTPageState *) NULL) if (state->btps_next == (BTPageState *) NULL)
{ {
@ -405,8 +408,8 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
/* /*
* Save a copy of the minimum key for the new page. We have to * Save a copy of the minimum key for the new page. We have to
* copy it off the old page, not the new one, in case we are * copy it off the old page, not the new one, in case we are not
* not at leaf level. * at leaf level.
*/ */
state->btps_minkey = _bt_formitem(&(obti->bti_itup)); state->btps_minkey = _bt_formitem(&(obti->bti_itup));
@ -414,13 +417,13 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
* Set the sibling links for both pages, and parent links too. * Set the sibling links for both pages, and parent links too.
* *
* It's not necessary to set the parent link at all, because it's * It's not necessary to set the parent link at all, because it's
* only used for handling concurrent root splits, but we may as well * only used for handling concurrent root splits, but we may as
* do it as a debugging aid. Note we set new page's link as well * well do it as a debugging aid. Note we set new page's link as
* as old's, because if the new page turns out to be the last of * well as old's, because if the new page turns out to be the last
* the level, _bt_uppershutdown won't change it. The links may be * of the level, _bt_uppershutdown won't change it. The links may
* out of date by the time the build finishes, but that's OK; they * be out of date by the time the build finishes, but that's OK;
* need only point to a left-sibling of the true parent. See the * they need only point to a left-sibling of the true parent. See
* README file for more info. * the README file for more info.
*/ */
{ {
BTPageOpaque oopaque = (BTPageOpaque) PageGetSpecialPointer(opage); BTPageOpaque oopaque = (BTPageOpaque) PageGetSpecialPointer(opage);
@ -434,7 +437,7 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
} }
/* /*
* Write out the old page. We never want to see it again, so we * Write out the old page. We never want to see it again, so we
* can give up our lock (if we had one; most likely BuildingBtree * can give up our lock (if we had one; most likely BuildingBtree
* is set, so we aren't locking). * is set, so we aren't locking).
*/ */
@ -449,8 +452,8 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
/* /*
* If the new item is the first for its page, stash a copy for later. * If the new item is the first for its page, stash a copy for later.
* Note this will only happen for the first item on a level; on later * Note this will only happen for the first item on a level; on later
* pages, the first item for a page is copied from the prior page * pages, the first item for a page is copied from the prior page in
* in the code above. * the code above.
*/ */
if (last_off == P_HIKEY) if (last_off == P_HIKEY)
{ {
@ -493,8 +496,8 @@ _bt_uppershutdown(Relation index, BTPageState *state)
* *
* If we're at the top, it's the root, so attach it to the metapage. * If we're at the top, it's the root, so attach it to the metapage.
* Otherwise, add an entry for it to its parent using its minimum * Otherwise, add an entry for it to its parent using its minimum
* key. This may cause the last page of the parent level to split, * key. This may cause the last page of the parent level to
* but that's not a problem -- we haven't gotten to it yet. * split, but that's not a problem -- we haven't gotten to it yet.
*/ */
if (s->btps_next == (BTPageState *) NULL) if (s->btps_next == (BTPageState *) NULL)
{ {
@ -513,7 +516,7 @@ _bt_uppershutdown(Relation index, 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 back one slot. Then we can dump out the page. * slid back one slot. Then we can dump out the page.
*/ */
_bt_slideleft(index, s->btps_buf, s->btps_page); _bt_slideleft(index, s->btps_buf, s->btps_page);
_bt_wrtbuf(index, s->btps_buf); _bt_wrtbuf(index, s->btps_buf);
@ -529,22 +532,29 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
{ {
BTPageState *state = NULL; BTPageState *state = NULL;
bool merge = (btspool2 != NULL); bool merge = (btspool2 != NULL);
BTItem bti, bti2 = NULL; BTItem bti,
bool should_free, should_free2, load1; bti2 = NULL;
bool should_free,
should_free2,
load1;
TupleDesc tupdes = RelationGetDescr(index); TupleDesc tupdes = RelationGetDescr(index);
int i, keysz = RelationGetNumberOfAttributes(index); int i,
keysz = RelationGetNumberOfAttributes(index);
ScanKey indexScanKey = NULL; ScanKey indexScanKey = NULL;
if (merge) if (merge)
{ {
/* /*
* Another BTSpool for dead tuples exists. * Another BTSpool for dead tuples exists. Now we have to merge
* Now we have to merge btspool and btspool2. * btspool and btspool2.
*/ */
ScanKey entry; ScanKey entry;
Datum attrDatum1, attrDatum2; Datum attrDatum1,
bool isFirstNull, isSecondNull; attrDatum2;
int32 compare; bool isFirstNull,
isSecondNull;
int32 compare;
/* the preparation of merge */ /* the preparation of merge */
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free); bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free);
@ -552,7 +562,7 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
indexScanKey = _bt_mkscankey_nodata(index); indexScanKey = _bt_mkscankey_nodata(index);
for (;;) for (;;)
{ {
load1 = true; /* load BTSpool next ? */ load1 = true; /* load BTSpool next ? */
if (NULL == bti2) if (NULL == bti2)
{ {
if (NULL == bti) if (NULL == bti)
@ -564,8 +574,8 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
for (i = 1; i <= keysz; i++) for (i = 1; i <= keysz; i++)
{ {
entry = indexScanKey + i - 1; entry = indexScanKey + i - 1;
attrDatum1 = index_getattr((IndexTuple)bti, i, tupdes, &isFirstNull); attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes, &isFirstNull);
attrDatum2 = index_getattr((IndexTuple)bti2, i, tupdes, &isSecondNull); attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes, &isSecondNull);
if (isFirstNull) if (isFirstNull)
{ {
if (!isSecondNull) if (!isSecondNull)
@ -586,7 +596,7 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
} }
else if (compare < 0) else if (compare < 0)
break; break;
} }
} }
} }
else else
@ -613,7 +623,8 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
} }
_bt_freeskey(indexScanKey); _bt_freeskey(indexScanKey);
} }
else /* merge is unnecessary */ else
/* merge is unnecessary */
{ {
while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL) while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.42 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.43 2001/03/22 03:59:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -124,7 +124,7 @@ _bt_freestack(BTStack stack)
* Construct a BTItem from a plain IndexTuple. * Construct a BTItem from a plain IndexTuple.
* *
* This is now useless code, since a BTItem *is* an index tuple with * This is now useless code, since a BTItem *is* an index tuple with
* no extra stuff. We hang onto it for the moment to preserve the * no extra stuff. We hang onto it for the moment to preserve the
* notational distinction, in case we want to add some extra stuff * notational distinction, in case we want to add some extra stuff
* again someday. * again someday.
*/ */
@ -165,7 +165,7 @@ _bt_formitem(IndexTuple itup)
* are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple
* (1,2,7), but we must continue the scan in case there are tuples (1,3,z). * (1,2,7), but we must continue the scan in case there are tuples (1,3,z).
* But once we reach tuples like (1,4,z) we can stop scanning because no * But once we reach tuples like (1,4,z) we can stop scanning because no
* later tuples could match. This is reflected by setting * later tuples could match. This is reflected by setting
* so->numberOfRequiredKeys to the number of leading keys that must be * so->numberOfRequiredKeys to the number of leading keys that must be
* matched to continue the scan. numberOfRequiredKeys is equal to the * matched to continue the scan. numberOfRequiredKeys is equal to the
* number of leading "=" keys plus the key(s) for the first non "=" * number of leading "=" keys plus the key(s) for the first non "="
@ -178,7 +178,7 @@ _bt_formitem(IndexTuple itup)
* *
* XXX this routine is one of many places that fail to handle SK_COMMUTE * XXX this routine is one of many places that fail to handle SK_COMMUTE
* scankeys properly. Currently, the planner is careful never to generate * scankeys properly. Currently, the planner is careful never to generate
* any indexquals that would require SK_COMMUTE to be set. Someday we ought * any indexquals that would require SK_COMMUTE to be set. Someday we ought
* to try to fix this, though it's not real critical as long as indexable * to try to fix this, though it's not real critical as long as indexable
* operators all have commutators... * operators all have commutators...
* *
@ -191,7 +191,7 @@ _bt_formitem(IndexTuple itup)
void void
_bt_orderkeys(Relation relation, BTScanOpaque so) _bt_orderkeys(Relation relation, BTScanOpaque so)
{ {
ScanKeyData xform[BTMaxStrategyNumber]; ScanKeyData xform[BTMaxStrategyNumber];
bool init[BTMaxStrategyNumber]; bool init[BTMaxStrategyNumber];
uint16 numberOfKeys = so->numberOfKeys; uint16 numberOfKeys = so->numberOfKeys;
ScanKey key; ScanKey key;
@ -240,14 +240,14 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
/* /*
* Initialize for processing of keys for attr 1. * Initialize for processing of keys for attr 1.
* *
* xform[i] holds a copy of the current scan key of strategy type i+1, * xform[i] holds a copy of the current scan key of strategy type i+1, if
* if any; init[i] is TRUE if we have found such a key for this attr. * any; init[i] is TRUE if we have found such a key for this attr.
*/ */
attno = 1; attno = 1;
map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
BTMaxStrategyNumber, BTMaxStrategyNumber,
attno); attno);
MemSet(xform, 0, sizeof(xform)); /* not really necessary */ MemSet(xform, 0, sizeof(xform)); /* not really necessary */
MemSet(init, 0, sizeof(init)); MemSet(init, 0, sizeof(init));
/* /*
@ -255,7 +255,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
* pass to handle after-last-key processing. Actual exit from the * pass to handle after-last-key processing. Actual exit from the
* loop is at the "break" statement below. * loop is at the "break" statement below.
*/ */
for (i = 0; ; cur++, i++) for (i = 0;; cur++, i++)
{ {
if (i < numberOfKeys) if (i < numberOfKeys)
{ {
@ -263,7 +263,9 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (cur->sk_flags & SK_ISNULL) if (cur->sk_flags & SK_ISNULL)
{ {
so->qual_ok = false; so->qual_ok = false;
/* Quit processing so we don't try to invoke comparison
/*
* Quit processing so we don't try to invoke comparison
* routines on NULLs. * routines on NULLs.
*/ */
return; return;
@ -271,8 +273,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
} }
/* /*
* If we are at the end of the keys for a particular attr, * If we are at the end of the keys for a particular attr, finish
* finish up processing and emit the cleaned-up keys. * up processing and emit the cleaned-up keys.
*/ */
if (i == numberOfKeys || cur->sk_attno != attno) if (i == numberOfKeys || cur->sk_attno != attno)
{ {
@ -296,7 +298,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
eq = &xform[BTEqualStrategyNumber - 1]; eq = &xform[BTEqualStrategyNumber - 1];
for (j = BTMaxStrategyNumber; --j >= 0;) for (j = BTMaxStrategyNumber; --j >= 0;)
{ {
if (! init[j] || if (!init[j] ||
j == (BTEqualStrategyNumber - 1)) j == (BTEqualStrategyNumber - 1))
continue; continue;
chk = &xform[j]; chk = &xform[j];
@ -313,6 +315,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
} }
else else
{ {
/* /*
* No "=" for this key, so we're done with required keys * No "=" for this key, so we're done with required keys
*/ */
@ -355,8 +358,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
* Emit the cleaned-up keys back into the key[] array in the * Emit the cleaned-up keys back into the key[] array in the
* correct order. Note we are overwriting our input here! * correct order. Note we are overwriting our input here!
* It's OK because (a) xform[] is a physical copy of the keys * It's OK because (a) xform[] is a physical copy of the keys
* we want, (b) we cannot emit more keys than we input, so * we want, (b) we cannot emit more keys than we input, so we
* we won't overwrite as-yet-unprocessed keys. * won't overwrite as-yet-unprocessed keys.
*/ */
for (j = BTMaxStrategyNumber; --j >= 0;) for (j = BTMaxStrategyNumber; --j >= 0;)
{ {
@ -383,7 +386,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
BTMaxStrategyNumber, BTMaxStrategyNumber,
attno); attno);
MemSet(xform, 0, sizeof(xform)); /* not really necessary */ MemSet(xform, 0, sizeof(xform)); /* not really necessary */
MemSet(init, 0, sizeof(init)); MemSet(init, 0, sizeof(init));
} }
@ -409,7 +412,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (DatumGetBool(test)) if (DatumGetBool(test))
xform[j].sk_argument = cur->sk_argument; xform[j].sk_argument = cur->sk_argument;
else if (j == (BTEqualStrategyNumber - 1)) else if (j == (BTEqualStrategyNumber - 1))
so->qual_ok = false; /* key == a && key == b, but a != b */ so->qual_ok = false; /* key == a && key == b, but a !=
* b */
} }
else else
{ {
@ -473,16 +477,18 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
if (isNull) if (isNull)
{ {
/* /*
* Since NULLs are sorted after non-NULLs, we know we have * Since NULLs are sorted after non-NULLs, we know we have
* reached the upper limit of the range of values for this * reached the upper limit of the range of values for this
* index attr. On a forward scan, we can stop if this qual * index attr. On a forward scan, we can stop if this qual is
* is one of the "must match" subset. On a backward scan, * one of the "must match" subset. On a backward scan,
* however, we should keep going. * however, we should keep going.
*/ */
if (keysok < so->numberOfRequiredKeys && if (keysok < so->numberOfRequiredKeys &&
ScanDirectionIsForward(dir)) ScanDirectionIsForward(dir))
*continuescan = false; *continuescan = false;
/* /*
* In any case, this indextuple doesn't match the qual. * In any case, this indextuple doesn't match the qual.
*/ */
@ -498,9 +504,10 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE)) if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE))
{ {
/* /*
* Tuple fails this qual. If it's a required qual, then * Tuple fails this qual. If it's a required qual, then we
* we can conclude no further tuples will pass, either. * can conclude no further tuples will pass, either.
*/ */
if (keysok < so->numberOfRequiredKeys) if (keysok < so->numberOfRequiredKeys)
*continuescan = false; *continuescan = false;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.24 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.25 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -30,8 +30,8 @@ static ItemPointer rtheapptr(Relation r, ItemPointer itemp);
Datum Datum
rtgettuple(PG_FUNCTION_ARGS) rtgettuple(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
RetrieveIndexResult res; RetrieveIndexResult res;
/* if we have it cached in the scan desc, just return the value */ /* if we have it cached in the scan desc, just return the value */

View File

@ -6,7 +6,7 @@
* NOTE: for largely-historical reasons, the intersection functions should * NOTE: for largely-historical reasons, the intersection functions should
* return a NULL pointer (*not* an SQL null value) to indicate "no * return a NULL pointer (*not* an SQL null value) to indicate "no
* intersection". The size functions must be prepared to accept such * intersection". The size functions must be prepared to accept such
* a pointer and return 0. This convention means that only pass-by-reference * a pointer and return 0. This convention means that only pass-by-reference
* data types can be used as the output of the union and intersection * data types can be used as the output of the union and intersection
* routines, but that's not a big problem. * routines, but that's not a big problem.
* *
@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.31 2001/01/24 19:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.32 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -70,6 +70,7 @@ Datum
rt_box_size(PG_FUNCTION_ARGS) rt_box_size(PG_FUNCTION_ARGS)
{ {
BOX *a = PG_GETARG_BOX_P(0); BOX *a = PG_GETARG_BOX_P(0);
/* NB: size is an output argument */ /* NB: size is an output argument */
float *size = (float *) PG_GETARG_POINTER(1); float *size = (float *) PG_GETARG_POINTER(1);
@ -98,8 +99,8 @@ rt_bigbox_size(PG_FUNCTION_ARGS)
Datum Datum
rt_poly_union(PG_FUNCTION_ARGS) rt_poly_union(PG_FUNCTION_ARGS)
{ {
POLYGON *a = PG_GETARG_POLYGON_P(0); POLYGON *a = PG_GETARG_POLYGON_P(0);
POLYGON *b = PG_GETARG_POLYGON_P(1); POLYGON *b = PG_GETARG_POLYGON_P(1);
POLYGON *p; POLYGON *p;
p = (POLYGON *) palloc(sizeof(POLYGON)); p = (POLYGON *) palloc(sizeof(POLYGON));
@ -122,8 +123,8 @@ rt_poly_union(PG_FUNCTION_ARGS)
Datum Datum
rt_poly_inter(PG_FUNCTION_ARGS) rt_poly_inter(PG_FUNCTION_ARGS)
{ {
POLYGON *a = PG_GETARG_POLYGON_P(0); POLYGON *a = PG_GETARG_POLYGON_P(0);
POLYGON *b = PG_GETARG_POLYGON_P(1); POLYGON *b = PG_GETARG_POLYGON_P(1);
POLYGON *p; POLYGON *p;
p = (POLYGON *) palloc(sizeof(POLYGON)); p = (POLYGON *) palloc(sizeof(POLYGON));
@ -155,13 +156,15 @@ Datum
rt_poly_size(PG_FUNCTION_ARGS) rt_poly_size(PG_FUNCTION_ARGS)
{ {
Pointer aptr = PG_GETARG_POINTER(0); Pointer aptr = PG_GETARG_POINTER(0);
/* NB: size is an output argument */ /* NB: size is an output argument */
float *size = (float *) PG_GETARG_POINTER(1); float *size = (float *) PG_GETARG_POINTER(1);
POLYGON *a; POLYGON *a;
double xdim, double xdim,
ydim; ydim;
/* Can't just use GETARG because of possibility that input is NULL; /*
* Can't just use GETARG because of possibility that input is NULL;
* since POLYGON is toastable, GETARG will try to inspect its value * since POLYGON is toastable, GETARG will try to inspect its value
*/ */
if (aptr == NULL) if (aptr == NULL)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.60 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.61 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -68,12 +68,12 @@ static InsertIndexResult rtdoinsert(Relation r, IndexTuple itup,
static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size, static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size,
RTSTATE *rtstate); RTSTATE *rtstate);
static InsertIndexResult rtdosplit(Relation r, Buffer buffer, RTSTACK *stack, static InsertIndexResult rtdosplit(Relation r, Buffer buffer, RTSTACK *stack,
IndexTuple itup, RTSTATE *rtstate); IndexTuple itup, RTSTATE *rtstate);
static void rtintinsert(Relation r, RTSTACK *stk, IndexTuple ltup, static void rtintinsert(Relation r, RTSTACK *stk, IndexTuple ltup,
IndexTuple rtup, RTSTATE *rtstate); IndexTuple rtup, RTSTATE *rtstate);
static void rtnewroot(Relation r, IndexTuple lt, IndexTuple rt); static void rtnewroot(Relation r, IndexTuple lt, IndexTuple rt);
static void rtpicksplit(Relation r, Page page, SPLITVEC *v, IndexTuple itup, static void rtpicksplit(Relation r, Page page, SPLITVEC *v, IndexTuple itup,
RTSTATE *rtstate); RTSTATE *rtstate);
static void RTInitBuffer(Buffer b, uint32 f); static void RTInitBuffer(Buffer b, uint32 f);
static OffsetNumber choose(Relation r, Page p, IndexTuple it, static OffsetNumber choose(Relation r, Page p, IndexTuple it,
RTSTATE *rtstate); RTSTATE *rtstate);
@ -84,12 +84,14 @@ static void initRtstate(RTSTATE *rtstate, Relation index);
Datum Datum
rtbuild(PG_FUNCTION_ARGS) rtbuild(PG_FUNCTION_ARGS)
{ {
Relation heap = (Relation) PG_GETARG_POINTER(0); Relation heap = (Relation) PG_GETARG_POINTER(0);
Relation index = (Relation) PG_GETARG_POINTER(1); Relation index = (Relation) PG_GETARG_POINTER(1);
IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
Node *oldPred = (Node *) PG_GETARG_POINTER(3); Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif #endif
HeapScanDesc hscan; HeapScanDesc hscan;
HeapTuple htup; HeapTuple htup;
@ -101,9 +103,11 @@ rtbuild(PG_FUNCTION_ARGS)
int nhtups, int nhtups,
nitups; nitups;
Node *pred = indexInfo->ii_Predicate; Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult res = NULL; InsertIndexResult res = NULL;
@ -171,6 +175,7 @@ rtbuild(PG_FUNCTION_ARGS)
nhtups++; nhtups++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -232,9 +237,7 @@ rtbuild(PG_FUNCTION_ARGS)
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL) if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -278,12 +281,14 @@ rtbuild(PG_FUNCTION_ARGS)
Datum Datum
rtinsert(PG_FUNCTION_ARGS) rtinsert(PG_FUNCTION_ARGS)
{ {
Relation r = (Relation) PG_GETARG_POINTER(0); Relation r = (Relation) PG_GETARG_POINTER(0);
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
InsertIndexResult res; InsertIndexResult res;
IndexTuple itup; IndexTuple itup;
@ -412,7 +417,7 @@ rttighten(Relation r,
p = BufferGetPage(b); p = BufferGetPage(b);
oldud = IndexTupleGetDatum(PageGetItem(p, oldud = IndexTupleGetDatum(PageGetItem(p,
PageGetItemId(p, stk->rts_child))); PageGetItemId(p, stk->rts_child)));
FunctionCall2(&rtstate->sizeFn, oldud, FunctionCall2(&rtstate->sizeFn, oldud,
PointerGetDatum(&old_size)); PointerGetDatum(&old_size));
@ -564,7 +569,7 @@ rtdosplit(Relation r,
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData)); res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
/* now insert the new index tuple */ /* now insert the new index tuple */
if (*spl_left == maxoff+1) if (*spl_left == maxoff + 1)
{ {
if (PageAddItem(left, (Item) itup, IndexTupleSize(itup), if (PageAddItem(left, (Item) itup, IndexTupleSize(itup),
leftoff, LP_USED) == InvalidOffsetNumber) leftoff, LP_USED) == InvalidOffsetNumber)
@ -576,7 +581,7 @@ rtdosplit(Relation r,
} }
else else
{ {
Assert(*spl_right == maxoff+1); Assert(*spl_right == maxoff + 1);
if (PageAddItem(right, (Item) itup, IndexTupleSize(itup), if (PageAddItem(right, (Item) itup, IndexTupleSize(itup),
rightoff, LP_USED) == InvalidOffsetNumber) rightoff, LP_USED) == InvalidOffsetNumber)
elog(ERROR, "rtdosplit: failed to add index item to %s", elog(ERROR, "rtdosplit: failed to add index item to %s",
@ -665,10 +670,10 @@ rtintinsert(Relation r,
old = (IndexTuple) PageGetItem(p, PageGetItemId(p, stk->rts_child)); old = (IndexTuple) PageGetItem(p, PageGetItemId(p, stk->rts_child));
/* /*
* This is a hack. Right now, we force rtree internal keys to be constant * This is a hack. Right now, we force rtree internal keys to be
* size. To fix this, need delete the old key and add both left and * constant size. To fix this, need delete the old key and add both
* right for the two new pages. The insertion of left may force a * left and right for the two new pages. The insertion of left may
* split if the new left key is bigger than the old key. * force a split if the new left key is bigger than the old key.
*/ */
if (IndexTupleSize(old) != IndexTupleSize(ltup)) if (IndexTupleSize(old) != IndexTupleSize(ltup))
@ -734,7 +739,7 @@ rtnewroot(Relation r, IndexTuple lt, IndexTuple rt)
* We return two vectors of index item numbers, one for the items to be * We return two vectors of index item numbers, one for the items to be
* put on the left page, one for the items to be put on the right page. * put on the left page, one for the items to be put on the right page.
* In addition, the item to be added (itup) is listed in the appropriate * In addition, the item to be added (itup) is listed in the appropriate
* vector. It is represented by item number N+1 (N = # of items on page). * vector. It is represented by item number N+1 (N = # of items on page).
* *
* Both vectors appear in sequence order with a terminating sentinel value * Both vectors appear in sequence order with a terminating sentinel value
* of InvalidOffsetNumber. * of InvalidOffsetNumber.
@ -747,9 +752,9 @@ rtnewroot(Relation r, IndexTuple lt, IndexTuple rt)
* *
* We must also deal with a consideration not found in Guttman's algorithm: * We must also deal with a consideration not found in Guttman's algorithm:
* variable-length data. In particular, the incoming item might be * variable-length data. In particular, the incoming item might be
* large enough that not just any split will work. In the worst case, * large enough that not just any split will work. In the worst case,
* our "split" may have to be the new item on one page and all the existing * our "split" may have to be the new item on one page and all the existing
* items on the other. Short of that, we have to take care that we do not * items on the other. Short of that, we have to take care that we do not
* make a split that leaves both pages too full for the new item. * make a split that leaves both pages too full for the new item.
*/ */
static void static void
@ -794,9 +799,10 @@ rtpicksplit(Relation r,
right_avail_space; right_avail_space;
/* /*
* First, make sure the new item is not so large that we can't possibly * First, make sure the new item is not so large that we can't
* fit it on a page, even by itself. (It's sufficient to make this test * possibly fit it on a page, even by itself. (It's sufficient to
* here, since any oversize tuple must lead to a page split attempt.) * make this test here, since any oversize tuple must lead to a page
* split attempt.)
*/ */
newitemsz = IndexTupleTotalSize(itup); newitemsz = IndexTupleTotalSize(itup);
if (newitemsz > RTPageAvailSpace) if (newitemsz > RTPageAvailSpace)
@ -804,7 +810,8 @@ rtpicksplit(Relation r,
(unsigned long) newitemsz, (unsigned long) RTPageAvailSpace); (unsigned long) newitemsz, (unsigned long) RTPageAvailSpace);
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
newitemoff = OffsetNumberNext(maxoff); /* phony index for new item */ newitemoff = OffsetNumberNext(maxoff); /* phony index for new
* item */
/* Make arrays big enough for worst case, including sentinel */ /* Make arrays big enough for worst case, including sentinel */
nbytes = (maxoff + 2) * sizeof(OffsetNumber); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
@ -827,8 +834,8 @@ rtpicksplit(Relation r,
item_2_sz = IndexTupleTotalSize(item_2); item_2_sz = IndexTupleTotalSize(item_2);
/* /*
* Ignore seed pairs that don't leave room for the new item * Ignore seed pairs that don't leave room for the new item on
* on either split page. * either split page.
*/ */
if (newitemsz + item_1_sz > RTPageAvailSpace && if (newitemsz + item_1_sz > RTPageAvailSpace &&
newitemsz + item_2_sz > RTPageAvailSpace) newitemsz + item_2_sz > RTPageAvailSpace)
@ -841,8 +848,10 @@ rtpicksplit(Relation r,
PointerGetDatum(&size_union)); PointerGetDatum(&size_union));
inter_d = FunctionCall2(&rtstate->interFn, inter_d = FunctionCall2(&rtstate->interFn,
datum_alpha, datum_beta); datum_alpha, datum_beta);
/* The interFn may return a NULL pointer (not an SQL null!)
* to indicate no intersection. sizeFn must cope with this. /*
* The interFn may return a NULL pointer (not an SQL null!) to
* indicate no intersection. sizeFn must cope with this.
*/ */
FunctionCall2(&rtstate->sizeFn, inter_d, FunctionCall2(&rtstate->sizeFn, inter_d,
PointerGetDatum(&size_inter)); PointerGetDatum(&size_inter));
@ -869,6 +878,7 @@ rtpicksplit(Relation r,
if (firsttime) if (firsttime)
{ {
/* /*
* There is no possible split except to put the new item on its * There is no possible split except to put the new item on its
* own page. Since we still have to compute the union rectangles, * own page. Since we still have to compute the union rectangles,
@ -916,14 +926,14 @@ rtpicksplit(Relation r,
for (i = FirstOffsetNumber; i <= newitemoff; i = OffsetNumberNext(i)) for (i = FirstOffsetNumber; i <= newitemoff; i = OffsetNumberNext(i))
{ {
bool left_feasible, bool left_feasible,
right_feasible, right_feasible,
choose_left; choose_left;
/* /*
* If we've already decided where to place this item, just put it * If we've already decided where to place this item, just put it
* on the correct list. Otherwise, we need to figure out which page * on the correct list. Otherwise, we need to figure out which
* needs the least enlargement in order to store the item. * page needs the least enlargement in order to store the item.
*/ */
if (i == seed_1) if (i == seed_1)
@ -961,12 +971,13 @@ rtpicksplit(Relation r,
PointerGetDatum(&size_beta)); PointerGetDatum(&size_beta));
/* /*
* We prefer the page that shows smaller enlargement of its union area * We prefer the page that shows smaller enlargement of its union
* (Guttman's algorithm), but we must take care that at least one page * area (Guttman's algorithm), but we must take care that at least
* will still have room for the new item after this one is added. * one page will still have room for the new item after this one
* is added.
* *
* (We know that all the old items together can fit on one page, * (We know that all the old items together can fit on one page, so
* so we need not worry about any other problem than failing to fit * we need not worry about any other problem than failing to fit
* the new item.) * the new item.)
*/ */
left_feasible = (left_avail_space >= item_1_sz && left_feasible = (left_avail_space >= item_1_sz &&
@ -987,7 +998,7 @@ rtpicksplit(Relation r,
else else
{ {
elog(ERROR, "rtpicksplit: failed to find a workable page split"); elog(ERROR, "rtpicksplit: failed to find a workable page split");
choose_left = false; /* keep compiler quiet */ choose_left = false;/* keep compiler quiet */
} }
if (choose_left) if (choose_left)
@ -1012,7 +1023,7 @@ rtpicksplit(Relation r,
} }
} }
*left = *right = InvalidOffsetNumber; /* add ending sentinels */ *left = *right = InvalidOffsetNumber; /* add ending sentinels */
v->spl_ldatum = datum_l; v->spl_ldatum = datum_l;
v->spl_rdatum = datum_r; v->spl_rdatum = datum_r;
@ -1096,8 +1107,8 @@ freestack(RTSTACK *s)
Datum Datum
rtdelete(PG_FUNCTION_ARGS) rtdelete(PG_FUNCTION_ARGS)
{ {
Relation r = (Relation) PG_GETARG_POINTER(0); Relation r = (Relation) PG_GETARG_POINTER(0);
ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1); ItemPointer tid = (ItemPointer) PG_GETARG_POINTER(1);
BlockNumber blkno; BlockNumber blkno;
OffsetNumber offnum; OffsetNumber offnum;
Buffer buf; Buffer buf;
@ -1203,14 +1214,14 @@ rtree_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
elog(STOP, "rtree_redo: unimplemented"); elog(STOP, "rtree_redo: unimplemented");
} }
void void
rtree_undo(XLogRecPtr lsn, XLogRecord *record) rtree_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
elog(STOP, "rtree_undo: unimplemented"); elog(STOP, "rtree_undo: unimplemented");
} }
void void
rtree_desc(char *buf, uint8 xl_info, char* rec) rtree_desc(char *buf, uint8 xl_info, char *rec)
{ {
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.35 2001/01/24 19:42:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.36 2001/03/22 03:59:16 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -75,9 +75,9 @@ rtbeginscan(PG_FUNCTION_ARGS)
Datum Datum
rtrescan(PG_FUNCTION_ARGS) rtrescan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
ScanKey key = (ScanKey) PG_GETARG_POINTER(2); ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
RTreeScanOpaque p; RTreeScanOpaque p;
RegProcedure internal_proc; RegProcedure internal_proc;
int i; int i;
@ -162,7 +162,7 @@ rtrescan(PG_FUNCTION_ARGS)
Datum Datum
rtmarkpos(PG_FUNCTION_ARGS) rtmarkpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
RTreeScanOpaque p; RTreeScanOpaque p;
RTSTACK *o, RTSTACK *o,
*n, *n,
@ -198,7 +198,7 @@ rtmarkpos(PG_FUNCTION_ARGS)
Datum Datum
rtrestrpos(PG_FUNCTION_ARGS) rtrestrpos(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
RTreeScanOpaque p; RTreeScanOpaque p;
RTSTACK *o, RTSTACK *o,
*n, *n,
@ -234,7 +234,7 @@ rtrestrpos(PG_FUNCTION_ARGS)
Datum Datum
rtendscan(PG_FUNCTION_ARGS) rtendscan(PG_FUNCTION_ARGS)
{ {
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
RTreeScanOpaque p; RTreeScanOpaque p;
p = (RTreeScanOpaque) s->opaque; p = (RTreeScanOpaque) s->opaque;

View File

@ -9,21 +9,21 @@
#include "storage/smgr.h" #include "storage/smgr.h"
#include "commands/sequence.h" #include "commands/sequence.h"
RmgrData RmgrTable[] = { RmgrData RmgrTable[] = {
{"XLOG", xlog_redo, xlog_undo, xlog_desc}, {"XLOG", xlog_redo, xlog_undo, xlog_desc},
{"Transaction", xact_redo, xact_undo, xact_desc}, {"Transaction", xact_redo, xact_undo, xact_desc},
{"Storage", smgr_redo, smgr_undo, smgr_desc}, {"Storage", smgr_redo, smgr_undo, smgr_desc},
{"Reserved 3", NULL, NULL, NULL}, {"Reserved 3", NULL, NULL, NULL},
{"Reserved 4", NULL, NULL, NULL}, {"Reserved 4", NULL, NULL, NULL},
{"Reserved 5", NULL, NULL, NULL}, {"Reserved 5", NULL, NULL, NULL},
{"Reserved 6", NULL, NULL, NULL}, {"Reserved 6", NULL, NULL, NULL},
{"Reserved 7", NULL, NULL, NULL}, {"Reserved 7", NULL, NULL, NULL},
{"Reserved 8", NULL, NULL, NULL}, {"Reserved 8", NULL, NULL, NULL},
{"Reserved 9", NULL, NULL, NULL}, {"Reserved 9", NULL, NULL, NULL},
{"Heap", heap_redo, heap_undo, heap_desc}, {"Heap", heap_redo, heap_undo, heap_desc},
{"Btree", btree_redo, btree_undo, btree_desc}, {"Btree", btree_redo, btree_undo, btree_desc},
{"Hash", hash_redo, hash_undo, hash_desc}, {"Hash", hash_redo, hash_undo, hash_desc},
{"Rtree", rtree_redo, rtree_undo, rtree_desc}, {"Rtree", rtree_redo, rtree_undo, rtree_desc},
{"Gist", gist_redo, gist_undo, gist_desc}, {"Gist", gist_redo, gist_undo, gist_desc},
{"Sequence", seq_redo, seq_undo, seq_desc} {"Sequence", seq_redo, seq_undo, seq_desc}
}; };

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.41 2001/03/18 20:18:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.42 2001/03/22 03:59:17 momjian Exp $
* *
* NOTES * NOTES
* This file contains the high level access-method interface to the * This file contains the high level access-method interface to the
@ -427,8 +427,8 @@ InitializeTransactionLog(void)
TransactionLogUpdate(AmiTransactionId, XID_COMMIT); TransactionLogUpdate(AmiTransactionId, XID_COMMIT);
TransactionIdStore(AmiTransactionId, &cachedTestXid); TransactionIdStore(AmiTransactionId, &cachedTestXid);
cachedTestXidStatus = XID_COMMIT; cachedTestXidStatus = XID_COMMIT;
Assert(!IsUnderPostmaster && Assert(!IsUnderPostmaster &&
ShmemVariableCache->nextXid <= FirstTransactionId); ShmemVariableCache->nextXid <= FirstTransactionId);
ShmemVariableCache->nextXid = FirstTransactionId; ShmemVariableCache->nextXid = FirstTransactionId;
} }
else if (RecoveryCheckingEnabled()) else if (RecoveryCheckingEnabled())

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.28 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.29 2001/03/22 03:59:17 momjian Exp $
* *
* NOTES * NOTES
* This file contains support functions for the high * This file contains support functions for the high
@ -186,7 +186,7 @@ TransBlockGetXidStatus(Block tblock,
bits8 bit2; bits8 bit2;
BitIndex offset; BitIndex offset;
tblock = (Block) ((char*) tblock + sizeof(XLogRecPtr)); tblock = (Block) ((char *) tblock + sizeof(XLogRecPtr));
/* ---------------- /* ----------------
* calculate the index into the transaction data where * calculate the index into the transaction data where
@ -229,7 +229,7 @@ TransBlockSetXidStatus(Block tblock,
Index index; Index index;
BitIndex offset; BitIndex offset;
tblock = (Block) ((char*) tblock + sizeof(XLogRecPtr)); tblock = (Block) ((char *) tblock + sizeof(XLogRecPtr));
/* ---------------- /* ----------------
* calculate the index into the transaction data where * calculate the index into the transaction data where

View File

@ -6,7 +6,7 @@
* Copyright (c) 2000, PostgreSQL Global Development Group * Copyright (c) 2000, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.37 2001/03/18 20:18:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.38 2001/03/22 03:59:17 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -23,8 +23,8 @@
#define VAR_OID_PREFETCH 8192 #define VAR_OID_PREFETCH 8192
/* Spinlocks for serializing generation of XIDs and OIDs, respectively */ /* Spinlocks for serializing generation of XIDs and OIDs, respectively */
SPINLOCK XidGenLockId; SPINLOCK XidGenLockId;
SPINLOCK OidGenLockId; SPINLOCK OidGenLockId;
/* pointer to "variable cache" in shared memory (set up by shmem.c) */ /* pointer to "variable cache" in shared memory (set up by shmem.c) */
VariableCache ShmemVariableCache = NULL; VariableCache ShmemVariableCache = NULL;
@ -32,9 +32,10 @@ VariableCache ShmemVariableCache = NULL;
void void
GetNewTransactionId(TransactionId *xid) GetNewTransactionId(TransactionId *xid)
{ {
/* /*
* During bootstrap initialization, we return the special * During bootstrap initialization, we return the special bootstrap
* bootstrap transaction id. * transaction id.
*/ */
if (AMI_OVERRIDE) if (AMI_OVERRIDE)
{ {
@ -60,9 +61,10 @@ GetNewTransactionId(TransactionId *xid)
void void
ReadNewTransactionId(TransactionId *xid) ReadNewTransactionId(TransactionId *xid)
{ {
/* /*
* During bootstrap initialization, we return the special * During bootstrap initialization, we return the special bootstrap
* bootstrap transaction id. * transaction id.
*/ */
if (AMI_OVERRIDE) if (AMI_OVERRIDE)
{ {
@ -80,7 +82,7 @@ ReadNewTransactionId(TransactionId *xid)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Oid lastSeenOid = InvalidOid; static Oid lastSeenOid = InvalidOid;
void void
GetNewObjectId(Oid *oid_return) GetNewObjectId(Oid *oid_return)
@ -119,10 +121,10 @@ CheckMaxObjectId(Oid assigned_oid)
} }
/* If we are in the logged oid range, just bump nextOid up */ /* If we are in the logged oid range, just bump nextOid up */
if (assigned_oid <= ShmemVariableCache->nextOid + if (assigned_oid <= ShmemVariableCache->nextOid +
ShmemVariableCache->oidCount - 1) ShmemVariableCache->oidCount - 1)
{ {
ShmemVariableCache->oidCount -= ShmemVariableCache->oidCount -=
assigned_oid - ShmemVariableCache->nextOid + 1; assigned_oid - ShmemVariableCache->nextOid + 1;
ShmemVariableCache->nextOid = assigned_oid + 1; ShmemVariableCache->nextOid = assigned_oid + 1;
SpinRelease(OidGenLockId); SpinRelease(OidGenLockId);
@ -130,10 +132,9 @@ CheckMaxObjectId(Oid assigned_oid)
} }
/* /*
* We have exceeded the logged oid range. * We have exceeded the logged oid range. We should lock the database
* We should lock the database and kill all other backends * and kill all other backends but we are loading oid's that we can
* but we are loading oid's that we can not guarantee are unique * not guarantee are unique anyway, so we must rely on the user.
* anyway, so we must rely on the user.
*/ */
XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH); XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.99 2001/03/13 01:17:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.100 2001/03/22 03:59:18 momjian Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
@ -222,9 +222,10 @@ int DefaultXactIsoLevel = XACT_READ_COMMITTED;
int XactIsoLevel; int XactIsoLevel;
int CommitDelay = 0; /* precommit delay in microseconds */ int CommitDelay = 0; /* precommit delay in microseconds */
int CommitSiblings = 5; /* number of concurrent xacts needed to sleep */ int CommitSiblings = 5; /* number of concurrent xacts needed to
* sleep */
static void (*_RollbackFunc)(void*) = NULL; static void (*_RollbackFunc) (void *) = NULL;
static void *_RollbackData = NULL; static void *_RollbackData = NULL;
/* ---------------- /* ----------------
@ -666,39 +667,40 @@ RecordTransactionCommit()
if (MyLastRecPtr.xrecoff != 0) if (MyLastRecPtr.xrecoff != 0)
{ {
XLogRecData rdata; XLogRecData rdata;
xl_xact_commit xlrec; xl_xact_commit xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
BufmgrCommit(); BufmgrCommit();
xlrec.xtime = time(NULL); xlrec.xtime = time(NULL);
rdata.buffer = InvalidBuffer; rdata.buffer = InvalidBuffer;
rdata.data = (char *)(&xlrec); rdata.data = (char *) (&xlrec);
rdata.len = SizeOfXactCommit; rdata.len = SizeOfXactCommit;
rdata.next = NULL; rdata.next = NULL;
START_CRIT_SECTION(); START_CRIT_SECTION();
/* /*
* SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
*/ */
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata); recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
/* /*
* Sleep before commit! So we can flush more than one * Sleep before commit! So we can flush more than one commit
* commit records per single fsync. (The idea is some other * records per single fsync. (The idea is some other backend may
* backend may do the XLogFlush while we're sleeping. This * do the XLogFlush while we're sleeping. This needs work still,
* needs work still, because on most Unixen, the minimum * because on most Unixen, the minimum select() delay is 10msec or
* select() delay is 10msec or more, which is way too long.) * more, which is way too long.)
* *
* We do not sleep if enableFsync is not turned on, nor if there * We do not sleep if enableFsync is not turned on, nor if there are
* are fewer than CommitSiblings other backends with active * fewer than CommitSiblings other backends with active
* transactions. * transactions.
*/ */
if (CommitDelay > 0 && enableFsync && if (CommitDelay > 0 && enableFsync &&
CountActiveBackends() >= CommitSiblings) CountActiveBackends() >= CommitSiblings)
{ {
struct timeval delay; struct timeval delay;
delay.tv_sec = 0; delay.tv_sec = 0;
delay.tv_usec = CommitDelay; delay.tv_usec = CommitDelay;
@ -812,13 +814,13 @@ RecordTransactionAbort(void)
*/ */
if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid)) if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid))
{ {
XLogRecData rdata; XLogRecData rdata;
xl_xact_abort xlrec; xl_xact_abort xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
xlrec.xtime = time(NULL); xlrec.xtime = time(NULL);
rdata.buffer = InvalidBuffer; rdata.buffer = InvalidBuffer;
rdata.data = (char *)(&xlrec); rdata.data = (char *) (&xlrec);
rdata.len = SizeOfXactAbort; rdata.len = SizeOfXactAbort;
rdata.next = NULL; rdata.next = NULL;
@ -879,7 +881,7 @@ AtAbort_Memory(void)
{ {
/* ---------------- /* ----------------
* Make sure we are in a valid context (not a child of * Make sure we are in a valid context (not a child of
* TransactionCommandContext...). Note that it is possible * TransactionCommandContext...). Note that it is possible
* for this code to be called when we aren't in a transaction * for this code to be called when we aren't in a transaction
* at all; go directly to TopMemoryContext in that case. * at all; go directly to TopMemoryContext in that case.
* ---------------- * ----------------
@ -896,9 +898,7 @@ AtAbort_Memory(void)
MemoryContextResetAndDeleteChildren(TransactionCommandContext); MemoryContextResetAndDeleteChildren(TransactionCommandContext);
} }
else else
{
MemoryContextSwitchTo(TopMemoryContext); MemoryContextSwitchTo(TopMemoryContext);
}
} }
@ -1021,6 +1021,7 @@ CurrentXactInProgress(void)
{ {
return CurrentTransactionState->state == TRANS_INPROGRESS; return CurrentTransactionState->state == TRANS_INPROGRESS;
} }
#endif #endif
/* -------------------------------- /* --------------------------------
@ -1106,7 +1107,7 @@ CommitTransaction(void)
AtCommit_Memory(); AtCommit_Memory();
AtEOXact_Files(); AtEOXact_Files();
SharedBufferChanged = false; /* safest place to do it */ SharedBufferChanged = false;/* safest place to do it */
/* ---------------- /* ----------------
* done with commit processing, set current transaction * done with commit processing, set current transaction
@ -1143,15 +1144,16 @@ AbortTransaction(void)
/* /*
* Release any spinlocks or buffer context locks we might be holding * Release any spinlocks or buffer context locks we might be holding
* as quickly as possible. (Real locks, however, must be held till * as quickly as possible. (Real locks, however, must be held till we
* we finish aborting.) Releasing spinlocks is critical since we * finish aborting.) Releasing spinlocks is critical since we might
* might try to grab them again while cleaning up! * try to grab them again while cleaning up!
*/ */
ProcReleaseSpins(NULL); ProcReleaseSpins(NULL);
UnlockBuffers(); UnlockBuffers();
/* /*
* Also clean up any open wait for lock, since the lock manager * Also clean up any open wait for lock, since the lock manager will
* will choke if we try to wait for another lock before doing this. * choke if we try to wait for another lock before doing this.
*/ */
LockWaitCancel(); LockWaitCancel();
@ -1203,7 +1205,7 @@ AbortTransaction(void)
AtEOXact_Files(); AtEOXact_Files();
AtAbort_Locks(); AtAbort_Locks();
SharedBufferChanged = false; /* safest place to do it */ SharedBufferChanged = false;/* safest place to do it */
/* ---------------- /* ----------------
* State remains TRANS_ABORT until CleanupTransaction(). * State remains TRANS_ABORT until CleanupTransaction().
@ -1327,8 +1329,8 @@ StartTransactionCommand(void)
} }
/* /*
* We must switch to TransactionCommandContext before returning. * We must switch to TransactionCommandContext before returning. This
* This is already done if we called StartTransaction, otherwise not. * is already done if we called StartTransaction, otherwise not.
*/ */
Assert(TransactionCommandContext != NULL); Assert(TransactionCommandContext != NULL);
MemoryContextSwitchTo(TransactionCommandContext); MemoryContextSwitchTo(TransactionCommandContext);
@ -1757,7 +1759,7 @@ IsTransactionBlock(void)
void void
xact_redo(XLogRecPtr lsn, XLogRecord *record) xact_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == XLOG_XACT_COMMIT) if (info == XLOG_XACT_COMMIT)
{ {
@ -1765,9 +1767,7 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
/* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */ /* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */
} }
else if (info == XLOG_XACT_ABORT) else if (info == XLOG_XACT_ABORT)
{
TransactionIdAbort(record->xl_xid); TransactionIdAbort(record->xl_xid);
}
else else
elog(STOP, "xact_redo: unknown op code %u", info); elog(STOP, "xact_redo: unknown op code %u", info);
} }
@ -1775,43 +1775,43 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
void void
xact_undo(XLogRecPtr lsn, XLogRecord *record) xact_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == XLOG_XACT_COMMIT) /* shouldn't be called by XLOG */ if (info == XLOG_XACT_COMMIT) /* shouldn't be called by XLOG */
elog(STOP, "xact_undo: can't undo committed xaction"); elog(STOP, "xact_undo: can't undo committed xaction");
else if (info != XLOG_XACT_ABORT) else if (info != XLOG_XACT_ABORT)
elog(STOP, "xact_redo: unknown op code %u", info); elog(STOP, "xact_redo: unknown op code %u", info);
} }
void void
xact_desc(char *buf, uint8 xl_info, char* rec) xact_desc(char *buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == XLOG_XACT_COMMIT) if (info == XLOG_XACT_COMMIT)
{ {
xl_xact_commit *xlrec = (xl_xact_commit*) rec; xl_xact_commit *xlrec = (xl_xact_commit *) rec;
struct tm *tm = localtime(&xlrec->xtime); struct tm *tm = localtime(&xlrec->xtime);
sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u", sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
} }
else if (info == XLOG_XACT_ABORT) else if (info == XLOG_XACT_ABORT)
{ {
xl_xact_abort *xlrec = (xl_xact_abort*) rec; xl_xact_abort *xlrec = (xl_xact_abort *) rec;
struct tm *tm = localtime(&xlrec->xtime); struct tm *tm = localtime(&xlrec->xtime);
sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u", sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
} }
else else
strcat(buf, "UNKNOWN"); strcat(buf, "UNKNOWN");
} }
void void
XactPushRollback(void (*func) (void *), void* data) XactPushRollback(void (*func) (void *), void *data)
{ {
#ifdef XLOG_II #ifdef XLOG_II
if (_RollbackFunc != NULL) if (_RollbackFunc != NULL)

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: xid.c,v 1.29 2001/01/24 19:42:51 momjian Exp $ * $Id: xid.c,v 1.30 2001/03/22 03:59:18 momjian Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* XXX WARNING * XXX WARNING
@ -26,8 +26,8 @@
/* /*
* TransactionId is typedef'd as uint32, so... * TransactionId is typedef'd as uint32, so...
*/ */
#define PG_GETARG_TRANSACTIONID(n) PG_GETARG_UINT32(n) #define PG_GETARG_TRANSACTIONID(n) PG_GETARG_UINT32(n)
#define PG_RETURN_TRANSACTIONID(x) PG_RETURN_UINT32(x) #define PG_RETURN_TRANSACTIONID(x) PG_RETURN_UINT32(x)
extern TransactionId NullTransactionId; extern TransactionId NullTransactionId;
@ -49,6 +49,7 @@ Datum
xidout(PG_FUNCTION_ARGS) xidout(PG_FUNCTION_ARGS)
{ {
TransactionId transactionId = PG_GETARG_TRANSACTIONID(0); TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
/* maximum 32 bit unsigned integer representation takes 10 chars */ /* maximum 32 bit unsigned integer representation takes 10 chars */
char *representation = palloc(11); char *representation = palloc(11);

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.14 2001/03/13 01:17:05 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.15 2001/03/22 03:59:18 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,26 +37,26 @@
* xaction/command and return * xaction/command and return
* *
* - -1 if not * - -1 if not
* - 0 if there is no tuple at all * - 0 if there is no tuple at all
* - 1 if yes * - 1 if yes
*/ */
int int
XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr, XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
TransactionId xid, CommandId cid) TransactionId xid, CommandId cid)
{ {
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
ItemId lp; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
reln = XLogOpenRelation(false, RM_HEAP_ID, hnode); reln = XLogOpenRelation(false, RM_HEAP_ID, hnode);
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return(0); return (0);
buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr)); buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return(0); return (0);
LockBuffer(buffer, BUFFER_LOCK_SHARE); LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
@ -64,13 +64,13 @@ XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page)) ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(0); return (0);
} }
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr)); lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr));
if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp)) if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(0); return (0);
} }
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@ -79,11 +79,11 @@ XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
if (htup->t_xmin != xid || htup->t_cmin != cid) if (htup->t_xmin != xid || htup->t_cmin != cid)
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(-1); return (-1);
} }
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(1); return (1);
} }
/* /*
@ -95,19 +95,19 @@ XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
bool bool
XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr) XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr)
{ {
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
ItemId lp; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
reln = XLogOpenRelation(false, RM_HEAP_ID, hnode); reln = XLogOpenRelation(false, RM_HEAP_ID, hnode);
if (!RelationIsValid(reln)) if (!RelationIsValid(reln))
return(false); return (false);
buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr)); buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr));
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return(false); return (false);
LockBuffer(buffer, BUFFER_LOCK_SHARE); LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
@ -115,21 +115,21 @@ XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr)
ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page)) ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(false); return (false);
} }
if (PageGetSUI(page) != ThisStartUpID) if (PageGetSUI(page) != ThisStartUpID)
{ {
Assert(PageGetSUI(page) < ThisStartUpID); Assert(PageGetSUI(page) < ThisStartUpID);
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(true); return (true);
} }
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr)); lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr));
if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp)) if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(false); return (false);
} }
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@ -140,22 +140,22 @@ XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr)
{ {
if (htup->t_infomask & HEAP_XMIN_INVALID || if (htup->t_infomask & HEAP_XMIN_INVALID ||
(htup->t_infomask & HEAP_MOVED_IN && (htup->t_infomask & HEAP_MOVED_IN &&
TransactionIdDidAbort((TransactionId)htup->t_cmin)) || TransactionIdDidAbort((TransactionId) htup->t_cmin)) ||
TransactionIdDidAbort(htup->t_xmin)) TransactionIdDidAbort(htup->t_xmin))
{ {
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(false); return (false);
} }
} }
UnlockAndReleaseBuffer(buffer); UnlockAndReleaseBuffer(buffer);
return(true); return (true);
} }
/* /*
* Open pg_log in recovery * Open pg_log in recovery
*/ */
extern Relation LogRelation; /* pg_log relation */ extern Relation LogRelation; /* pg_log relation */
void void
XLogOpenLogRelation(void) XLogOpenLogRelation(void)
@ -189,32 +189,32 @@ XLogOpenLogRelation(void)
Buffer Buffer
XLogReadBuffer(bool extend, Relation reln, BlockNumber blkno) XLogReadBuffer(bool extend, Relation reln, BlockNumber blkno)
{ {
BlockNumber lastblock = RelationGetNumberOfBlocks(reln); BlockNumber lastblock = RelationGetNumberOfBlocks(reln);
Buffer buffer; Buffer buffer;
if (blkno >= lastblock) if (blkno >= lastblock)
{ {
buffer = InvalidBuffer; buffer = InvalidBuffer;
if (extend) /* we do this in recovery only - no locks */ if (extend) /* we do this in recovery only - no locks */
{ {
Assert(InRecovery); Assert(InRecovery);
while (lastblock <= blkno) while (lastblock <= blkno)
{ {
if (buffer != InvalidBuffer) if (buffer != InvalidBuffer)
ReleaseBuffer(buffer); /* must be WriteBuffer()? */ ReleaseBuffer(buffer); /* must be WriteBuffer()? */
buffer = ReadBuffer(reln, P_NEW); buffer = ReadBuffer(reln, P_NEW);
lastblock++; lastblock++;
} }
} }
if (buffer != InvalidBuffer) if (buffer != InvalidBuffer)
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
return(buffer); return (buffer);
} }
buffer = ReadBuffer(reln, blkno); buffer = ReadBuffer(reln, blkno);
if (buffer != InvalidBuffer) if (buffer != InvalidBuffer)
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
return(buffer); return (buffer);
} }
/* /*
@ -223,32 +223,33 @@ XLogReadBuffer(bool extend, Relation reln, BlockNumber blkno)
typedef struct XLogRelDesc typedef struct XLogRelDesc
{ {
RelationData reldata; RelationData reldata;
struct XLogRelDesc *lessRecently; struct XLogRelDesc *lessRecently;
struct XLogRelDesc *moreRecently; struct XLogRelDesc *moreRecently;
} XLogRelDesc; } XLogRelDesc;
typedef struct XLogRelCacheEntry typedef struct XLogRelCacheEntry
{ {
RelFileNode rnode; RelFileNode rnode;
XLogRelDesc *rdesc; XLogRelDesc *rdesc;
} XLogRelCacheEntry; } XLogRelCacheEntry;
static HTAB *_xlrelcache; static HTAB *_xlrelcache;
static XLogRelDesc *_xlrelarr = NULL; static XLogRelDesc *_xlrelarr = NULL;
static Form_pg_class _xlpgcarr = NULL; static Form_pg_class _xlpgcarr = NULL;
static int _xlast = 0; static int _xlast = 0;
static int _xlcnt = 0; static int _xlcnt = 0;
#define _XLOG_RELCACHESIZE 512
#define _XLOG_RELCACHESIZE 512
static void static void
_xl_init_rel_cache(void) _xl_init_rel_cache(void)
{ {
HASHCTL ctl; HASHCTL ctl;
_xlcnt = _XLOG_RELCACHESIZE; _xlcnt = _XLOG_RELCACHESIZE;
_xlast = 0; _xlast = 0;
_xlrelarr = (XLogRelDesc*) malloc(sizeof(XLogRelDesc) * _xlcnt); _xlrelarr = (XLogRelDesc *) malloc(sizeof(XLogRelDesc) * _xlcnt);
memset(_xlrelarr, 0, sizeof(XLogRelDesc) * _xlcnt); memset(_xlrelarr, 0, sizeof(XLogRelDesc) * _xlcnt);
_xlpgcarr = (Form_pg_class) malloc(sizeof(FormData_pg_class) * _xlcnt); _xlpgcarr = (Form_pg_class) malloc(sizeof(FormData_pg_class) * _xlcnt);
memset(_xlpgcarr, 0, sizeof(FormData_pg_class) * _xlcnt); memset(_xlpgcarr, 0, sizeof(FormData_pg_class) * _xlcnt);
@ -258,26 +259,26 @@ _xl_init_rel_cache(void)
memset(&ctl, 0, (int) sizeof(ctl)); memset(&ctl, 0, (int) sizeof(ctl));
ctl.keysize = sizeof(RelFileNode); ctl.keysize = sizeof(RelFileNode);
ctl.datasize = sizeof(XLogRelDesc*); ctl.datasize = sizeof(XLogRelDesc *);
ctl.hash = tag_hash; ctl.hash = tag_hash;
_xlrelcache = hash_create(_XLOG_RELCACHESIZE, &ctl, _xlrelcache = hash_create(_XLOG_RELCACHESIZE, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_FUNCTION);
} }
static void static void
_xl_remove_hash_entry(XLogRelDesc **edata, Datum dummy) _xl_remove_hash_entry(XLogRelDesc **edata, Datum dummy)
{ {
XLogRelCacheEntry *hentry; XLogRelCacheEntry *hentry;
bool found; bool found;
XLogRelDesc *rdesc = *edata; XLogRelDesc *rdesc = *edata;
Form_pg_class tpgc = rdesc->reldata.rd_rel; Form_pg_class tpgc = rdesc->reldata.rd_rel;
rdesc->lessRecently->moreRecently = rdesc->moreRecently; rdesc->lessRecently->moreRecently = rdesc->moreRecently;
rdesc->moreRecently->lessRecently = rdesc->lessRecently; rdesc->moreRecently->lessRecently = rdesc->lessRecently;
hentry = (XLogRelCacheEntry*) hash_search(_xlrelcache, hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache,
(char*)&(rdesc->reldata.rd_node), HASH_REMOVE, &found); (char *) &(rdesc->reldata.rd_node), HASH_REMOVE, &found);
if (hentry == NULL) if (hentry == NULL)
elog(STOP, "_xl_remove_hash_entry: can't delete from cache"); elog(STOP, "_xl_remove_hash_entry: can't delete from cache");
@ -294,16 +295,16 @@ _xl_remove_hash_entry(XLogRelDesc **edata, Datum dummy)
return; return;
} }
static XLogRelDesc* static XLogRelDesc *
_xl_new_reldesc(void) _xl_new_reldesc(void)
{ {
XLogRelDesc *res; XLogRelDesc *res;
_xlast++; _xlast++;
if (_xlast < _xlcnt) if (_xlast < _xlcnt)
{ {
_xlrelarr[_xlast].reldata.rd_rel = &(_xlpgcarr[_xlast]); _xlrelarr[_xlast].reldata.rd_rel = &(_xlpgcarr[_xlast]);
return(&(_xlrelarr[_xlast])); return (&(_xlrelarr[_xlast]));
} }
/* reuse */ /* reuse */
@ -312,7 +313,7 @@ _xl_new_reldesc(void)
_xl_remove_hash_entry(&res, 0); _xl_remove_hash_entry(&res, 0);
_xlast--; _xlast--;
return(res); return (res);
} }
@ -344,12 +345,12 @@ XLogCloseRelationCache(void)
Relation Relation
XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode) XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
{ {
XLogRelDesc *res; XLogRelDesc *res;
XLogRelCacheEntry *hentry; XLogRelCacheEntry *hentry;
bool found; bool found;
hentry = (XLogRelCacheEntry*) hentry = (XLogRelCacheEntry *)
hash_search(_xlrelcache, (char*)&rnode, HASH_FIND, &found); hash_search(_xlrelcache, (char *) &rnode, HASH_FIND, &found);
if (hentry == NULL) if (hentry == NULL)
elog(STOP, "XLogOpenRelation: error in cache"); elog(STOP, "XLogOpenRelation: error in cache");
@ -372,8 +373,8 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode; res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode;
res->reldata.rd_node = rnode; res->reldata.rd_node = rnode;
hentry = (XLogRelCacheEntry*) hentry = (XLogRelCacheEntry *)
hash_search(_xlrelcache, (char*)&rnode, HASH_ENTER, &found); hash_search(_xlrelcache, (char *) &rnode, HASH_ENTER, &found);
if (hentry == NULL) if (hentry == NULL)
elog(STOP, "XLogOpenRelation: can't insert into cache"); elog(STOP, "XLogOpenRelation: can't insert into cache");
@ -385,7 +386,7 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
res->reldata.rd_fd = -1; res->reldata.rd_fd = -1;
res->reldata.rd_fd = smgropen(DEFAULT_SMGR, &(res->reldata), res->reldata.rd_fd = smgropen(DEFAULT_SMGR, &(res->reldata),
true /* allow failure */); true /* allow failure */ );
} }
res->moreRecently = &(_xlrelarr[0]); res->moreRecently = &(_xlrelarr[0]);
@ -393,8 +394,8 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
_xlrelarr[0].lessRecently = res; _xlrelarr[0].lessRecently = res;
res->lessRecently->moreRecently = res; res->lessRecently->moreRecently = res;
if (res->reldata.rd_fd < 0) /* file doesn't exist */ if (res->reldata.rd_fd < 0) /* file doesn't exist */
return(NULL); return (NULL);
return(&(res->reldata)); return (&(res->reldata));
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.46 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.47 2001/03/22 03:59:18 momjian Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
@ -34,7 +34,7 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static int32 aclcheck(char *relname, Acl *acl, AclId id, static int32 aclcheck(char *relname, Acl *acl, AclId id,
AclIdType idtype, AclMode mode); AclIdType idtype, AclMode mode);
/* warning messages, now more explicit. */ /* warning messages, now more explicit. */
/* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */ /* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */
@ -59,7 +59,7 @@ dumpacl(Acl *acl)
for (i = 0; i < ACL_NUM(acl); ++i) for (i = 0; i < ACL_NUM(acl); ++i)
elog(DEBUG, " acl[%d]: %s", i, elog(DEBUG, " acl[%d]: %s", i,
DatumGetCString(DirectFunctionCall1(aclitemout, DatumGetCString(DirectFunctionCall1(aclitemout,
PointerGetDatum(aip + i)))); PointerGetDatum(aip + i))));
} }
#endif #endif
@ -250,8 +250,8 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
num; num;
/* /*
* If ACL is null, default to "OK" --- this should not happen, * If ACL is null, default to "OK" --- this should not happen, since
* since caller should have inserted appropriate default * caller should have inserted appropriate default
*/ */
if (!acl) if (!acl)
{ {
@ -265,8 +265,8 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
/* /*
* We'll treat the empty ACL like that, too, although this is more * We'll treat the empty ACL like that, too, although this is more
* like an error (i.e., you manually blew away your ACL array) -- the * like an error (i.e., you manually blew away your ACL array) -- the
* system never creates an empty ACL, since there must always be * system never creates an empty ACL, since there must always be a
* a "world" entry in the first slot. * "world" entry in the first slot.
*/ */
if (num < 1) if (num < 1)
{ {
@ -352,7 +352,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
{ {
int32 result; int32 result;
HeapTuple tuple; HeapTuple tuple;
char *usename; char *usename;
Datum aclDatum; Datum aclDatum;
bool isNull; bool isNull;
Acl *acl; Acl *acl;
@ -439,7 +439,7 @@ pg_ownercheck(Oid userid,
{ {
HeapTuple tuple; HeapTuple tuple;
AclId owner_id; AclId owner_id;
char *usename; char *usename;
tuple = SearchSysCache(SHADOWSYSID, tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid), ObjectIdGetDatum(userid),

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.39 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.40 2001/03/22 03:59:19 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -105,7 +105,7 @@ relpath_blind(const char *dbname, const char *relname,
return path; return path;
} }
#else /* ! OLD_FILE_NAMING */ #else /* ! OLD_FILE_NAMING */
/* /*
* relpath - construct path to a relation's file * relpath - construct path to a relation's file
@ -118,7 +118,7 @@ relpath(RelFileNode rnode)
{ {
char *path; char *path;
if (rnode.tblNode == (Oid) 0) /* "global tablespace" */ if (rnode.tblNode == (Oid) 0) /* "global tablespace" */
{ {
/* Shared system relations live in {datadir}/global */ /* Shared system relations live in {datadir}/global */
path = (char *) palloc(strlen(DataDir) + 8 + sizeof(NameData) + 1); path = (char *) palloc(strlen(DataDir) + 8 + sizeof(NameData) + 1);
@ -127,8 +127,8 @@ relpath(RelFileNode rnode)
else else
{ {
path = (char *) palloc(strlen(DataDir) + 6 + 2 * sizeof(NameData) + 3); path = (char *) palloc(strlen(DataDir) + 6 + 2 * sizeof(NameData) + 3);
sprintf(path, "%s%cbase%c%u%c%u", DataDir, SEP_CHAR, SEP_CHAR, sprintf(path, "%s%cbase%c%u%c%u", DataDir, SEP_CHAR, SEP_CHAR,
rnode.tblNode, SEP_CHAR, rnode.relNode); rnode.tblNode, SEP_CHAR, rnode.relNode);
} }
return path; return path;
} }
@ -144,7 +144,7 @@ GetDatabasePath(Oid tblNode)
{ {
char *path; char *path;
if (tblNode == (Oid) 0) /* "global tablespace" */ if (tblNode == (Oid) 0) /* "global tablespace" */
{ {
/* Shared system relations live in {datadir}/global */ /* Shared system relations live in {datadir}/global */
path = (char *) palloc(strlen(DataDir) + 8); path = (char *) palloc(strlen(DataDir) + 8);
@ -158,7 +158,7 @@ GetDatabasePath(Oid tblNode)
return path; return path;
} }
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
/* /*
* IsSystemRelationName * IsSystemRelationName

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.160 2001/02/14 21:34:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.161 2001/03/22 03:59:19 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -68,7 +68,7 @@
static void AddNewRelationTuple(Relation pg_class_desc, static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
int natts, char relkind, char *temp_relname); int natts, char relkind, char *temp_relname);
static void DeleteAttributeTuples(Relation rel); static void DeleteAttributeTuples(Relation rel);
static void DeleteRelationTuple(Relation rel); static void DeleteRelationTuple(Relation rel);
@ -76,7 +76,7 @@ static void DeleteTypeTuple(Relation rel);
static void RelationRemoveIndexes(Relation relation); static void RelationRemoveIndexes(Relation relation);
static void RelationRemoveInheritance(Relation relation); static void RelationRemoveInheritance(Relation relation);
static void AddNewRelationType(char *typeName, Oid new_rel_oid, static void AddNewRelationType(char *typeName, Oid new_rel_oid,
Oid new_type_oid); Oid new_type_oid);
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
bool updatePgAttribute); bool updatePgAttribute);
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
@ -178,13 +178,13 @@ heap_create(char *relname,
{ {
static unsigned int uniqueId = 0; static unsigned int uniqueId = 0;
Oid relid; Oid relid;
Relation rel; Relation rel;
bool nailme = false; bool nailme = false;
int natts = tupDesc->natts; int natts = tupDesc->natts;
int i; int i;
MemoryContext oldcxt; MemoryContext oldcxt;
Oid tblNode = MyDatabaseId; Oid tblNode = MyDatabaseId;
/* ---------------- /* ----------------
* sanity checks * sanity checks
@ -270,7 +270,11 @@ heap_create(char *relname,
if (istemp) if (istemp)
{ {
/* replace relname of caller with a unique name for a temp relation */
/*
* replace relname of caller with a unique name for a temp
* relation
*/
snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u", snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",
(int) MyProcPid, uniqueId++); (int) MyProcPid, uniqueId++);
} }
@ -738,6 +742,7 @@ AddNewRelationTuple(Relation pg_class_desc,
static void static void
AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid) AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
{ {
/* /*
* The sizes are set to oid size because it makes implementing sets * The sizes are set to oid size because it makes implementing sets
* MUCH easier, and no one (we hope) uses these fields to figure out * MUCH easier, and no one (we hope) uses these fields to figure out
@ -1025,9 +1030,7 @@ RelationRemoveInheritance(Relation relation)
&entry); &entry);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
simple_heap_delete(catalogRelation, &tuple->t_self); simple_heap_delete(catalogRelation, &tuple->t_self);
}
heap_endscan(scan); heap_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock); heap_close(catalogRelation, RowExclusiveLock);
@ -1152,8 +1155,8 @@ RelationTruncateIndexes(Oid heapId)
/* /*
* We have to re-open the heap rel each time through this loop * We have to re-open the heap rel each time through this loop
* because index_build will close it again. We need grab no lock, * because index_build will close it again. We need grab no lock,
* however, because we assume heap_truncate is holding an exclusive * however, because we assume heap_truncate is holding an
* lock on the heap rel. * exclusive lock on the heap rel.
*/ */
heapRelation = heap_open(heapId, NoLock); heapRelation = heap_open(heapId, NoLock);
@ -1164,8 +1167,8 @@ RelationTruncateIndexes(Oid heapId)
LockRelation(currentIndex, AccessExclusiveLock); LockRelation(currentIndex, AccessExclusiveLock);
/* /*
* Drop any buffers associated with this index. If they're * Drop any buffers associated with this index. If they're dirty,
* dirty, they're just dropped without bothering to flush to disk. * they're just dropped without bothering to flush to disk.
*/ */
DropRelationBuffers(currentIndex); DropRelationBuffers(currentIndex);
@ -1177,6 +1180,7 @@ RelationTruncateIndexes(Oid heapId)
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
currentIndex, accessMethodId); currentIndex, accessMethodId);
index_build(heapRelation, currentIndex, indexInfo, NULL); index_build(heapRelation, currentIndex, indexInfo, NULL);
/* /*
* index_build will close both the heap and index relations (but * index_build will close both the heap and index relations (but
* not give up the locks we hold on them). * not give up the locks we hold on them).
@ -1514,7 +1518,7 @@ heap_drop_with_catalog(const char *relname,
if (has_toasttable) if (has_toasttable)
{ {
char toast_relname[NAMEDATALEN]; char toast_relname[NAMEDATALEN];
sprintf(toast_relname, "pg_toast_%u", rid); sprintf(toast_relname, "pg_toast_%u", rid);
heap_drop_with_catalog(toast_relname, true); heap_drop_with_catalog(toast_relname, true);
@ -1553,16 +1557,16 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
* deparse it * deparse it
*/ */
adsrc = deparse_expression(expr, adsrc = deparse_expression(expr,
deparse_context_for(RelationGetRelationName(rel), deparse_context_for(RelationGetRelationName(rel),
RelationGetRelid(rel)), RelationGetRelid(rel)),
false); false);
values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel); values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
values[Anum_pg_attrdef_adnum - 1] = attnum; values[Anum_pg_attrdef_adnum - 1] = attnum;
values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin, values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin,
CStringGetDatum(adbin)); CStringGetDatum(adbin));
values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin, values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin,
CStringGetDatum(adsrc)); CStringGetDatum(adsrc));
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
tuple = heap_formtuple(adrel->rd_att, values, nulls); tuple = heap_formtuple(adrel->rd_att, values, nulls);
heap_insert(adrel, tuple); heap_insert(adrel, tuple);
@ -1631,17 +1635,17 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
* deparse it * deparse it
*/ */
ccsrc = deparse_expression(expr, ccsrc = deparse_expression(expr,
deparse_context_for(RelationGetRelationName(rel), deparse_context_for(RelationGetRelationName(rel),
RelationGetRelid(rel)), RelationGetRelid(rel)),
false); false);
values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel); values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel);
values[Anum_pg_relcheck_rcname - 1] = DirectFunctionCall1(namein, values[Anum_pg_relcheck_rcname - 1] = DirectFunctionCall1(namein,
CStringGetDatum(ccname)); CStringGetDatum(ccname));
values[Anum_pg_relcheck_rcbin - 1] = DirectFunctionCall1(textin, values[Anum_pg_relcheck_rcbin - 1] = DirectFunctionCall1(textin,
CStringGetDatum(ccbin)); CStringGetDatum(ccbin));
values[Anum_pg_relcheck_rcsrc - 1] = DirectFunctionCall1(textin, values[Anum_pg_relcheck_rcsrc - 1] = DirectFunctionCall1(textin,
CStringGetDatum(ccsrc)); CStringGetDatum(ccsrc));
rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
tuple = heap_formtuple(rcrel->rd_att, values, nulls); tuple = heap_formtuple(rcrel->rd_att, values, nulls);
heap_insert(rcrel, tuple); heap_insert(rcrel, tuple);
@ -1981,9 +1985,7 @@ RemoveAttrDefault(Relation rel)
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key); adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
{
simple_heap_delete(adrel, &tup->t_self); simple_heap_delete(adrel, &tup->t_self);
}
heap_endscan(adscan); heap_endscan(adscan);
heap_close(adrel, RowExclusiveLock); heap_close(adrel, RowExclusiveLock);
@ -2005,9 +2007,7 @@ RemoveRelCheck(Relation rel)
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
{
simple_heap_delete(rcrel, &tup->t_self); simple_heap_delete(rcrel, &tup->t_self);
}
heap_endscan(rcscan); heap_endscan(rcscan);
heap_close(rcrel, RowExclusiveLock); heap_close(rcrel, RowExclusiveLock);
@ -2044,9 +2044,7 @@ RemoveStatistics(Relation rel)
scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key); scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
simple_heap_delete(pgstatistic, &tuple->t_self); simple_heap_delete(pgstatistic, &tuple->t_self);
}
heap_endscan(scan); heap_endscan(scan);
heap_close(pgstatistic, RowExclusiveLock); heap_close(pgstatistic, RowExclusiveLock);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.142 2001/02/23 09:31:52 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.143 2001/03/22 03:59:19 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -63,19 +63,19 @@ static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName,
bool istemp); bool istemp);
static TupleDesc BuildFuncTupleDesc(Oid funcOid); static TupleDesc BuildFuncTupleDesc(Oid funcOid);
static TupleDesc ConstructTupleDescriptor(Relation heapRelation, static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
int numatts, AttrNumber *attNums); int numatts, AttrNumber *attNums);
static void ConstructIndexReldesc(Relation indexRelation, Oid amoid); static void ConstructIndexReldesc(Relation indexRelation, Oid amoid);
static Oid UpdateRelationRelation(Relation indexRelation, char *temp_relname); static Oid UpdateRelationRelation(Relation indexRelation, char *temp_relname);
static void InitializeAttributeOids(Relation indexRelation, static void InitializeAttributeOids(Relation indexRelation,
int numatts, Oid indexoid); int numatts, Oid indexoid);
static void AppendAttributeTuples(Relation indexRelation, int numatts); static void AppendAttributeTuples(Relation indexRelation, int numatts);
static void UpdateIndexRelation(Oid indexoid, Oid heapoid, static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
IndexInfo *indexInfo, IndexInfo *indexInfo,
Oid *classOids, Oid *classOids,
bool islossy, bool primary); bool islossy, bool primary);
static void DefaultBuild(Relation heapRelation, Relation indexRelation, static void DefaultBuild(Relation heapRelation, Relation indexRelation,
IndexInfo *indexInfo, Node *oldPred, IndexInfo *indexInfo, Node *oldPred,
IndexStrategy indexStrategy); IndexStrategy indexStrategy);
static Oid IndexGetRelation(Oid indexId); static Oid IndexGetRelation(Oid indexId);
static bool activate_index(Oid indexId, bool activate, bool inplace); static bool activate_index(Oid indexId, bool activate, bool inplace);
@ -301,7 +301,8 @@ ConstructTupleDescriptor(Relation heapRelation,
memcpy(to, from, ATTRIBUTE_TUPLE_SIZE); memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);
/* /*
* Fix the stuff that should not be the same as the underlying attr * Fix the stuff that should not be the same as the underlying
* attr
*/ */
to->attnum = i + 1; to->attnum = i + 1;
@ -311,9 +312,9 @@ ConstructTupleDescriptor(Relation heapRelation,
to->attcacheoff = -1; to->attcacheoff = -1;
/* /*
* We do not yet have the correct relation OID for the index, * We do not yet have the correct relation OID for the index, so
* so just set it invalid for now. InitializeAttributeOids() * just set it invalid for now. InitializeAttributeOids() will
* will fix it later. * fix it later.
*/ */
to->attrelid = InvalidOid; to->attrelid = InvalidOid;
} }
@ -331,7 +332,7 @@ ConstructTupleDescriptor(Relation heapRelation,
* typically CacheMemoryContext). * typically CacheMemoryContext).
* *
* There was a note here about adding indexing, but I don't see a need * There was a note here about adding indexing, but I don't see a need
* for it. There are so few tuples in pg_am that an indexscan would * for it. There are so few tuples in pg_am that an indexscan would
* surely be slower. * surely be slower.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
@ -394,7 +395,7 @@ static void
ConstructIndexReldesc(Relation indexRelation, Oid amoid) ConstructIndexReldesc(Relation indexRelation, Oid amoid)
{ {
indexRelation->rd_am = AccessMethodObjectIdGetForm(amoid, indexRelation->rd_am = AccessMethodObjectIdGetForm(amoid,
CacheMemoryContext); CacheMemoryContext);
/* ---------------- /* ----------------
* XXX missing the initialization of some other fields * XXX missing the initialization of some other fields
@ -625,12 +626,12 @@ UpdateIndexRelation(Oid indexoid,
{ {
predString = nodeToString(indexInfo->ii_Predicate); predString = nodeToString(indexInfo->ii_Predicate);
predText = DatumGetTextP(DirectFunctionCall1(textin, predText = DatumGetTextP(DirectFunctionCall1(textin,
CStringGetDatum(predString))); CStringGetDatum(predString)));
pfree(predString); pfree(predString);
} }
else else
predText = DatumGetTextP(DirectFunctionCall1(textin, predText = DatumGetTextP(DirectFunctionCall1(textin,
CStringGetDatum(""))); CStringGetDatum("")));
predLen = VARSIZE(predText); predLen = VARSIZE(predText);
itupLen = predLen + sizeof(FormData_pg_index); itupLen = predLen + sizeof(FormData_pg_index);
@ -646,7 +647,7 @@ UpdateIndexRelation(Oid indexoid,
indexForm->indproc = indexInfo->ii_FuncOid; indexForm->indproc = indexInfo->ii_FuncOid;
indexForm->indisclustered = false; indexForm->indisclustered = false;
indexForm->indislossy = islossy; indexForm->indislossy = islossy;
indexForm->indhaskeytype = true; /* not actually used anymore */ indexForm->indhaskeytype = true; /* not actually used anymore */
indexForm->indisunique = indexInfo->ii_Unique; indexForm->indisunique = indexInfo->ii_Unique;
indexForm->indisprimary = primary; indexForm->indisprimary = primary;
memcpy((char *) &indexForm->indpred, (char *) predText, predLen); memcpy((char *) &indexForm->indpred, (char *) predText, predLen);
@ -747,12 +748,12 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
{ {
predString = nodeToString(newPred); predString = nodeToString(newPred);
predText = DatumGetTextP(DirectFunctionCall1(textin, predText = DatumGetTextP(DirectFunctionCall1(textin,
CStringGetDatum(predString))); CStringGetDatum(predString)));
pfree(predString); pfree(predString);
} }
else else
predText = DatumGetTextP(DirectFunctionCall1(textin, predText = DatumGetTextP(DirectFunctionCall1(textin,
CStringGetDatum(""))); CStringGetDatum("")));
/* open the index system catalog relation */ /* open the index system catalog relation */
pg_index = heap_openr(IndexRelationName, RowExclusiveLock); pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
@ -911,15 +912,15 @@ index_create(char *heapRelationName,
else else
indexTupDesc = ConstructTupleDescriptor(heapRelation, indexTupDesc = ConstructTupleDescriptor(heapRelation,
indexInfo->ii_NumKeyAttrs, indexInfo->ii_NumKeyAttrs,
indexInfo->ii_KeyAttrNumbers); indexInfo->ii_KeyAttrNumbers);
if (istemp) if (istemp)
{ {
/* save user relation name because heap_create changes it */ /* save user relation name because heap_create changes it */
temp_relname = pstrdup(indexRelationName); /* save original value */ temp_relname = pstrdup(indexRelationName); /* save original value */
indexRelationName = palloc(NAMEDATALEN); indexRelationName = palloc(NAMEDATALEN);
strcpy(indexRelationName, temp_relname); /* heap_create will strcpy(indexRelationName, temp_relname); /* heap_create will
* change this */ * change this */
} }
/* ---------------- /* ----------------
@ -1008,9 +1009,7 @@ index_create(char *heapRelationName,
/* XXX shouldn't we close the heap and index rels here? */ /* XXX shouldn't we close the heap and index rels here? */
} }
else else
{
index_build(heapRelation, indexRelation, indexInfo, NULL); index_build(heapRelation, indexRelation, indexInfo, NULL);
}
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -1081,12 +1080,12 @@ index_drop(Oid indexId)
heap_freetuple(tuple); heap_freetuple(tuple);
/* /*
* Update the pg_class tuple for the owning relation. We are presently * Update the pg_class tuple for the owning relation. We are
* too lazy to attempt to compute the new correct value of relhasindex * presently too lazy to attempt to compute the new correct value of
* (the next VACUUM will fix it if necessary). But we must send out a * relhasindex (the next VACUUM will fix it if necessary). But we
* shared-cache-inval notice on the owning relation to ensure other * must send out a shared-cache-inval notice on the owning relation to
* backends update their relcache lists of indexes. So, unconditionally * ensure other backends update their relcache lists of indexes. So,
* do setRelhasindex(true). * unconditionally do setRelhasindex(true).
*/ */
setRelhasindex(heapId, true); setRelhasindex(heapId, true);
@ -1160,11 +1159,11 @@ index_drop(Oid indexId)
* *
* IndexInfo stores the information about the index that's needed by * IndexInfo stores the information about the index that's needed by
* FormIndexDatum, which is used for both index_build() and later insertion * FormIndexDatum, which is used for both index_build() and later insertion
* of individual index tuples. Normally we build an IndexInfo for an index * of individual index tuples. Normally we build an IndexInfo for an index
* just once per command, and then use it for (potentially) many tuples. * just once per command, and then use it for (potentially) many tuples.
* ---------------- * ----------------
*/ */
IndexInfo * IndexInfo *
BuildIndexInfo(HeapTuple indexTuple) BuildIndexInfo(HeapTuple indexTuple)
{ {
Form_pg_index indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); Form_pg_index indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
@ -1199,7 +1198,7 @@ BuildIndexInfo(HeapTuple indexTuple)
{ {
ii->ii_NumIndexAttrs = 1; ii->ii_NumIndexAttrs = 1;
/* Do a lookup on the function, too */ /* Do a lookup on the function, too */
fmgr_info(indexStruct->indproc, & ii->ii_FuncInfo); fmgr_info(indexStruct->indproc, &ii->ii_FuncInfo);
} }
else else
ii->ii_NumIndexAttrs = numKeys; ii->ii_NumIndexAttrs = numKeys;
@ -1213,7 +1212,7 @@ BuildIndexInfo(HeapTuple indexTuple)
char *predString; char *predString;
predString = DatumGetCString(DirectFunctionCall1(textout, predString = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(&indexStruct->indpred))); PointerGetDatum(&indexStruct->indpred)));
ii->ii_Predicate = stringToNode(predString); ii->ii_Predicate = stringToNode(predString);
pfree(predString); pfree(predString);
} }
@ -1262,8 +1261,8 @@ FormIndexDatum(IndexInfo *indexInfo,
* Functional index --- compute the single index attribute * Functional index --- compute the single index attribute
* ---------------- * ----------------
*/ */
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
bool anynull = false; bool anynull = false;
MemSet(&fcinfo, 0, sizeof(fcinfo)); MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &indexInfo->ii_FuncInfo; fcinfo.flinfo = &indexInfo->ii_FuncInfo;
@ -1326,8 +1325,8 @@ LockClassinfoForUpdate(Oid relid, HeapTuple rtup,
Relation relationRelation; Relation relationRelation;
/* /*
* NOTE: get and hold RowExclusiveLock on pg_class, because caller will * NOTE: get and hold RowExclusiveLock on pg_class, because caller
* probably modify the rel's pg_class tuple later on. * will probably modify the rel's pg_class tuple later on.
*/ */
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
classTuple = SearchSysCache(RELOID, PointerGetDatum(relid), classTuple = SearchSysCache(RELOID, PointerGetDatum(relid),
@ -1342,7 +1341,7 @@ LockClassinfoForUpdate(Oid relid, HeapTuple rtup,
while (1) while (1)
{ {
ItemPointerData tidsave; ItemPointerData tidsave;
ItemPointerCopy(&(rtup->t_self), &tidsave); ItemPointerCopy(&(rtup->t_self), &tidsave);
test = heap_mark4update(relationRelation, rtup, buffer); test = heap_mark4update(relationRelation, rtup, buffer);
@ -1393,7 +1392,7 @@ IndexesAreActive(Oid relid, bool confirmCommitted)
if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted)) if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
elog(ERROR, "IndexesAreActive couldn't lock %u", relid); elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION && if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE) ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
elog(ERROR, "relation %u isn't an indexable relation", relid); elog(ERROR, "relation %u isn't an indexable relation", relid);
isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex; isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
@ -1438,7 +1437,7 @@ setRelhasindex(Oid relid, bool hasindex)
if (!IsIgnoringSystemIndexes()) if (!IsIgnoringSystemIndexes())
#else #else
if (!IsIgnoringSystemIndexes() && (!IsReindexProcessing() || pg_class->rd_rel->relhasindex)) if (!IsIgnoringSystemIndexes() && (!IsReindexProcessing() || pg_class->rd_rel->relhasindex))
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
{ {
tuple = SearchSysCacheCopy(RELOID, tuple = SearchSysCacheCopy(RELOID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
@ -1513,18 +1512,19 @@ setRelhasindex(Oid relid, bool hasindex)
void void
setNewRelfilenode(Relation relation) setNewRelfilenode(Relation relation)
{ {
Relation pg_class, idescs[Num_pg_class_indices]; Relation pg_class,
Oid newrelfilenode; idescs[Num_pg_class_indices];
Oid newrelfilenode;
bool in_place_update = false; bool in_place_update = false;
HeapTupleData lockTupleData; HeapTupleData lockTupleData;
HeapTuple classTuple = NULL; HeapTuple classTuple = NULL;
Buffer buffer; Buffer buffer;
RelationData workrel; RelationData workrel;
Assert(!IsSystemRelationName(NameStr(relation->rd_rel->relname)) || relation->rd_rel->relkind == RELKIND_INDEX); Assert(!IsSystemRelationName(NameStr(relation->rd_rel->relname)) || relation->rd_rel->relkind == RELKIND_INDEX);
pg_class = heap_openr(RelationRelationName, RowExclusiveLock); pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
/* Fetch and lock the classTuple associated with this relation */ /* Fetch and lock the classTuple associated with this relation */
if (!LockClassinfoForUpdate(relation->rd_id, &lockTupleData, &buffer, true)) if (!LockClassinfoForUpdate(relation->rd_id, &lockTupleData, &buffer, true))
elog(ERROR, "setNewRelfilenode impossible to lock class tuple"); elog(ERROR, "setNewRelfilenode impossible to lock class tuple");
if (IsIgnoringSystemIndexes()) if (IsIgnoringSystemIndexes())
@ -1567,7 +1567,7 @@ setNewRelfilenode(Relation relation)
if (!in_place_update && pg_class->rd_rel->relhasindex) if (!in_place_update && pg_class->rd_rel->relhasindex)
{ {
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
idescs); idescs);
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, classTuple); CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, classTuple);
CatalogCloseIndices(Num_pg_class_indices, idescs); CatalogCloseIndices(Num_pg_class_indices, idescs);
} }
@ -1577,7 +1577,8 @@ setNewRelfilenode(Relation relation)
/* Make sure the relfilenode change */ /* Make sure the relfilenode change */
CommandCounterIncrement(); CommandCounterIncrement();
} }
#endif /* OLD_FILE_NAMING */
#endif /* OLD_FILE_NAMING */
/* ---------------- /* ----------------
* UpdateStats * UpdateStats
@ -1639,7 +1640,7 @@ UpdateStats(Oid relid, long reltuples)
in_place_upd = (IsReindexProcessing() || IsBootstrapProcessingMode()); in_place_upd = (IsReindexProcessing() || IsBootstrapProcessingMode());
#else #else
in_place_upd = (IsIgnoringSystemIndexes() || IsReindexProcessing()); in_place_upd = (IsIgnoringSystemIndexes() || IsReindexProcessing());
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
if (!in_place_upd) if (!in_place_upd)
{ {
@ -1713,9 +1714,10 @@ UpdateStats(Oid relid, long reltuples)
*/ */
if (in_place_upd) if (in_place_upd)
{ {
/* /*
* At bootstrap time, we don't need to worry about concurrency or * At bootstrap time, we don't need to worry about concurrency or
* visibility of changes, so we cheat. Also cheat if REINDEX. * visibility of changes, so we cheat. Also cheat if REINDEX.
*/ */
rd_rel = (Form_pg_class) GETSTRUCT(tuple); rd_rel = (Form_pg_class) GETSTRUCT(tuple);
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE); LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
@ -1777,7 +1779,7 @@ DefaultBuild(Relation heapRelation,
Relation indexRelation, Relation indexRelation,
IndexInfo *indexInfo, IndexInfo *indexInfo,
Node *oldPred, Node *oldPred,
IndexStrategy indexStrategy) /* not used */ IndexStrategy indexStrategy) /* not used */
{ {
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple heapTuple; HeapTuple heapTuple;
@ -1787,9 +1789,11 @@ DefaultBuild(Relation heapRelation,
long reltuples, long reltuples,
indtuples; indtuples;
Node *predicate = indexInfo->ii_Predicate; Node *predicate = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
ExprContext *econtext; ExprContext *econtext;
InsertIndexResult insertResult; InsertIndexResult insertResult;
@ -1855,6 +1859,7 @@ DefaultBuild(Relation heapRelation,
reltuples++; reltuples++;
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* /*
* If oldPred != NULL, this is an EXTEND INDEX command, so skip * If oldPred != NULL, this is an EXTEND INDEX command, so skip
* this tuple if it was already in the existing partial index * this tuple if it was already in the existing partial index
@ -1906,9 +1911,7 @@ DefaultBuild(Relation heapRelation,
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
if (predicate != NULL || oldPred != NULL) if (predicate != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true); ExecDropTupleTable(tupleTable, true);
}
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
FreeExprContext(econtext); FreeExprContext(econtext);
@ -1972,7 +1975,7 @@ index_build(Relation heapRelation,
PointerGetDatum(indexRelation), PointerGetDatum(indexRelation),
PointerGetDatum(indexInfo), PointerGetDatum(indexInfo),
PointerGetDatum(oldPred), PointerGetDatum(oldPred),
PointerGetDatum(RelationGetIndexStrategy(indexRelation))); PointerGetDatum(RelationGetIndexStrategy(indexRelation)));
else else
DefaultBuild(heapRelation, DefaultBuild(heapRelation,
indexRelation, indexRelation,
@ -2087,21 +2090,22 @@ reindex_index(Oid indexId, bool force, bool inplace)
#ifndef OLD_FILE_NAMING #ifndef OLD_FILE_NAMING
if (!inplace) if (!inplace)
{ {
inplace = IsSharedSystemRelationName(NameStr(iRel->rd_rel->relname)); inplace = IsSharedSystemRelationName(NameStr(iRel->rd_rel->relname));
if (!inplace) if (!inplace)
setNewRelfilenode(iRel); setNewRelfilenode(iRel);
} }
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
/* Obtain exclusive lock on it, just to be sure */ /* Obtain exclusive lock on it, just to be sure */
LockRelation(iRel, AccessExclusiveLock); LockRelation(iRel, AccessExclusiveLock);
if (inplace) if (inplace)
{ {
/* /*
* Release any buffers associated with this index. If they're dirty, * Release any buffers associated with this index. If they're
* they're just dropped without bothering to flush to disk. * dirty, they're just dropped without bothering to flush to disk.
*/ */
DropRelationBuffers(iRel); DropRelationBuffers(iRel);
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data and set blocks to zero */
@ -2115,7 +2119,7 @@ reindex_index(Oid indexId, bool force, bool inplace)
/* /*
* index_build will close both the heap and index relations (but not * index_build will close both the heap and index relations (but not
* give up the locks we hold on them). So we're done. * give up the locks we hold on them). So we're done.
*/ */
SetReindexProcessing(old); SetReindexProcessing(old);
@ -2164,31 +2168,37 @@ reindex_relation(Oid relid, bool force)
bool old, bool old,
reindexed; reindexed;
bool deactivate_needed, overwrite, upd_pg_class_inplace; bool deactivate_needed,
overwrite,
upd_pg_class_inplace;
#ifdef OLD_FILE_NAMING #ifdef OLD_FILE_NAMING
overwrite = upd_pg_class_inplace = deactivate_needed = true; overwrite = upd_pg_class_inplace = deactivate_needed = true;
#else #else
Relation rel; Relation rel;
overwrite = upd_pg_class_inplace = deactivate_needed = false;
overwrite = upd_pg_class_inplace = deactivate_needed = false;
/* /*
* avoid heap_update() pg_class tuples while processing * avoid heap_update() pg_class tuples while processing reindex for
* reindex for pg_class. * pg_class.
*/ */
if (IsIgnoringSystemIndexes()) if (IsIgnoringSystemIndexes())
upd_pg_class_inplace = true; upd_pg_class_inplace = true;
/* /*
* ignore the indexes of the target system relation while processing * ignore the indexes of the target system relation while processing
* reindex. * reindex.
*/ */
rel = RelationIdGetRelation(relid); rel = RelationIdGetRelation(relid);
if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname))) if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname)))
deactivate_needed = true; deactivate_needed = true;
#ifndef ENABLE_REINDEX_NAILED_RELATIONS #ifndef ENABLE_REINDEX_NAILED_RELATIONS
/*
* nailed relations are never updated. /*
* We couldn't keep the consistency between the relation * nailed relations are never updated. We couldn't keep the
* descriptors and pg_class tuples. * consistency between the relation descriptors and pg_class tuples.
*/ */
if (rel->rd_isnailed) if (rel->rd_isnailed)
{ {
if (IsIgnoringSystemIndexes()) if (IsIgnoringSystemIndexes())
@ -2199,10 +2209,11 @@ reindex_relation(Oid relid, bool force)
else else
elog(ERROR, "the target relation %u is nailed", relid); elog(ERROR, "the target relation %u is nailed", relid);
} }
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ #endif /* ENABLE_REINDEX_NAILED_RELATIONS */
/* /*
* Shared system indexes must be overwritten because it's * Shared system indexes must be overwritten because it's impossible
* impossible to update pg_class tuples of all databases. * to update pg_class tuples of all databases.
*/ */
if (IsSharedSystemRelationName(NameStr(rel->rd_rel->relname))) if (IsSharedSystemRelationName(NameStr(rel->rd_rel->relname)))
{ {
@ -2215,7 +2226,7 @@ reindex_relation(Oid relid, bool force)
elog(ERROR, "the target relation %u is shared", relid); elog(ERROR, "the target relation %u is shared", relid);
} }
RelationClose(rel); RelationClose(rel);
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
old = SetReindexProcessing(true); old = SetReindexProcessing(true);
if (deactivate_needed) if (deactivate_needed)
{ {
@ -2252,24 +2263,27 @@ reindex_relation(Oid relid, bool force)
heap_endscan(scan); heap_endscan(scan);
heap_close(indexRelation, AccessShareLock); heap_close(indexRelation, AccessShareLock);
if (reindexed) if (reindexed)
/*
* Ok,we could use the reindexed indexes of the target /*
* system relation now. * Ok,we could use the reindexed indexes of the target system
*/ * relation now.
{ */
{
if (deactivate_needed) if (deactivate_needed)
{ {
if (!overwrite && relid == RelOid_pg_class) if (!overwrite && relid == RelOid_pg_class)
{ {
/*
* For pg_class, relhasindex should be set /*
* to true here in place. * For pg_class, relhasindex should be set to true here in
* place.
*/ */
setRelhasindex(relid, true); setRelhasindex(relid, true);
CommandCounterIncrement(); CommandCounterIncrement();
/*
* However the following setRelhasindex() /*
* is needed to keep consistency with WAL. * However the following setRelhasindex() is needed to
* keep consistency with WAL.
*/ */
} }
setRelhasindex(relid, true); setRelhasindex(relid, true);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.76 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.77 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -124,7 +124,7 @@ CatalogCloseIndices(int nIndices, Relation *idescs)
* NOTE: since this routine looks up all the pg_index data on each call, * NOTE: since this routine looks up all the pg_index data on each call,
* it's relatively inefficient for inserting a large number of tuples into * it's relatively inefficient for inserting a large number of tuples into
* the same catalog. We use it only for inserting one or a few tuples * the same catalog. We use it only for inserting one or a few tuples
* in a given command. See ExecOpenIndices() and related routines if you * in a given command. See ExecOpenIndices() and related routines if you
* are inserting tuples in bulk. * are inserting tuples in bulk.
* *
* NOTE: we do not bother to handle partial indices. Nor do we try to * NOTE: we do not bother to handle partial indices. Nor do we try to

View File

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

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.7 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.8 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -51,7 +51,7 @@ LargeObjectCreate(Oid loid)
*/ */
for (i = 0; i < Natts_pg_largeobject; i++) for (i = 0; i < Natts_pg_largeobject; i++)
{ {
values[i] = (Datum)NULL; values[i] = (Datum) NULL;
nulls[i] = ' '; nulls[i] = ' ';
} }
@ -60,7 +60,7 @@ LargeObjectCreate(Oid loid)
values[i++] = Int32GetDatum(0); values[i++] = Int32GetDatum(0);
values[i++] = DirectFunctionCall1(byteain, values[i++] = DirectFunctionCall1(byteain,
CStringGetDatum("")); CStringGetDatum(""));
ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls); ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls);
/* /*
@ -77,7 +77,7 @@ LargeObjectCreate(Oid loid)
CatalogIndexInsert(idescs, Num_pg_largeobject_indices, pg_largeobject, ntup); CatalogIndexInsert(idescs, Num_pg_largeobject_indices, pg_largeobject, ntup);
CatalogCloseIndices(Num_pg_largeobject_indices, idescs); CatalogCloseIndices(Num_pg_largeobject_indices, idescs);
} }
heap_close(pg_largeobject, RowExclusiveLock); heap_close(pg_largeobject, RowExclusiveLock);
heap_freetuple(ntup); heap_freetuple(ntup);
@ -91,9 +91,9 @@ LargeObjectDrop(Oid loid)
bool found = false; bool found = false;
Relation pg_largeobject; Relation pg_largeobject;
Relation pg_lo_idx; Relation pg_lo_idx;
ScanKeyData skey[1]; ScanKeyData skey[1];
IndexScanDesc sd; IndexScanDesc sd;
RetrieveIndexResult indexRes; RetrieveIndexResult indexRes;
HeapTupleData tuple; HeapTupleData tuple;
Buffer buffer; Buffer buffer;
@ -139,9 +139,9 @@ LargeObjectExists(Oid loid)
bool retval = false; bool retval = false;
Relation pg_largeobject; Relation pg_largeobject;
Relation pg_lo_idx; Relation pg_lo_idx;
ScanKeyData skey[1]; ScanKeyData skey[1];
IndexScanDesc sd; IndexScanDesc sd;
RetrieveIndexResult indexRes; RetrieveIndexResult indexRes;
HeapTupleData tuple; HeapTupleData tuple;
Buffer buffer; Buffer buffer;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.55 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.56 2001/03/22 03:59:20 momjian Exp $
* *
* NOTES * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
@ -263,7 +263,7 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
values[i++] = NameGetDatum(&oname); values[i++] = NameGetDatum(&oname);
values[i++] = Int32GetDatum(GetUserId()); values[i++] = Int32GetDatum(GetUserId());
values[i++] = UInt16GetDatum(0); values[i++] = UInt16GetDatum(0);
values[i++] = CharGetDatum('b'); /* assume it's binary */ values[i++] = CharGetDatum('b'); /* assume it's binary */
values[i++] = BoolGetDatum(false); values[i++] = BoolGetDatum(false);
values[i++] = BoolGetDatum(false); values[i++] = BoolGetDatum(false);
values[i++] = ObjectIdGetDatum(leftObjectId); /* <-- left oid */ values[i++] = ObjectIdGetDatum(leftObjectId); /* <-- left oid */
@ -595,7 +595,7 @@ OperatorDef(char *operatorName,
*/ */
if (restrictionName) if (restrictionName)
{ /* optional */ { /* optional */
Oid restOid; Oid restOid;
MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid));
typeId[0] = OIDOID; /* operator OID */ typeId[0] = OIDOID; /* operator OID */
@ -623,7 +623,7 @@ OperatorDef(char *operatorName,
*/ */
if (joinName) if (joinName)
{ /* optional */ { /* optional */
Oid joinOid; Oid joinOid;
MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid));
typeId[0] = OIDOID; /* operator OID */ typeId[0] = OIDOID; /* operator OID */
@ -745,7 +745,7 @@ OperatorDef(char *operatorName,
otherRightTypeName); otherRightTypeName);
if (!OidIsValid(other_oid)) if (!OidIsValid(other_oid))
elog(ERROR, elog(ERROR,
"OperatorDef: can't create operator shell \"%s\"", "OperatorDef: can't create operator shell \"%s\"",
name[j]); name[j]);
values[i++] = ObjectIdGetDatum(other_oid); values[i++] = ObjectIdGetDatum(other_oid);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.53 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.54 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -156,7 +156,7 @@ ProcedureCreate(char *procedureName,
text *prosrctext; text *prosrctext;
prosrctext = DatumGetTextP(DirectFunctionCall1(textin, prosrctext = DatumGetTextP(DirectFunctionCall1(textin,
CStringGetDatum(prosrc))); CStringGetDatum(prosrc)));
retval = GetSysCacheOid(PROSRC, retval = GetSysCacheOid(PROSRC,
PointerGetDatum(prosrctext), PointerGetDatum(prosrctext),
0, 0, 0); 0, 0, 0);
@ -237,18 +237,18 @@ ProcedureCreate(char *procedureName,
prosrc = procedureName; prosrc = procedureName;
if (fmgr_internal_function(prosrc) == InvalidOid) if (fmgr_internal_function(prosrc) == InvalidOid)
elog(ERROR, elog(ERROR,
"ProcedureCreate: there is no builtin function named \"%s\"", "ProcedureCreate: there is no builtin function named \"%s\"",
prosrc); prosrc);
} }
/* /*
* If this is a dynamically loadable procedure, make sure that the * If this is a dynamically loadable procedure, make sure that the
* library file exists, is loadable, and contains the specified link * library file exists, is loadable, and contains the specified link
* symbol. Also check for a valid function information record. * symbol. Also check for a valid function information record.
* *
* We used to perform these checks only when the function was first * We used to perform these checks only when the function was first
* called, but it seems friendlier to verify the library's validity * called, but it seems friendlier to verify the library's validity at
* at CREATE FUNCTION time. * CREATE FUNCTION time.
*/ */
if (languageObjectId == ClanguageId) if (languageObjectId == ClanguageId)
@ -355,7 +355,8 @@ checkretval(Oid rettype, List *queryTreeList)
tlist = parse->targetList; tlist = parse->targetList;
/* /*
* The last query must be a SELECT if and only if there is a return type. * The last query must be a SELECT if and only if there is a return
* type.
*/ */
if (rettype == InvalidOid) if (rettype == InvalidOid)
{ {
@ -375,8 +376,8 @@ checkretval(Oid rettype, List *queryTreeList)
tlistlen = ExecCleanTargetListLength(tlist); tlistlen = ExecCleanTargetListLength(tlist);
/* /*
* For base-type returns, the target list should have exactly one entry, * For base-type returns, the target list should have exactly one
* and its type should agree with what the user declared. * entry, and its type should agree with what the user declared.
*/ */
typerelid = typeidTypeRelid(rettype); typerelid = typeidTypeRelid(rettype);
if (typerelid == InvalidOid) if (typerelid == InvalidOid)
@ -388,7 +389,7 @@ checkretval(Oid rettype, List *queryTreeList)
resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom; resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
if (resnode->restype != rettype) if (resnode->restype != rettype)
elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", elog(ERROR, "return type mismatch in function: declared to return %s, returns %s",
typeidTypeName(rettype), typeidTypeName(resnode->restype)); typeidTypeName(rettype), typeidTypeName(resnode->restype));
return; return;
} }
@ -397,8 +398,8 @@ checkretval(Oid rettype, List *queryTreeList)
* If the target list is of length 1, and the type of the varnode in * If the target list is of length 1, and the type of the varnode in
* the target list is the same as the declared return type, this is * the target list is the same as the declared return type, this is
* okay. This can happen, for example, where the body of the function * okay. This can happen, for example, where the body of the function
* is 'SELECT (x = func2())', where func2 has the same return type * is 'SELECT (x = func2())', where func2 has the same return type as
* as the function that's calling it. * the function that's calling it.
*/ */
if (tlistlen == 1) if (tlistlen == 1)
{ {
@ -408,10 +409,10 @@ checkretval(Oid rettype, List *queryTreeList)
} }
/* /*
* By here, the procedure returns a tuple or set of tuples. This part of * By here, the procedure returns a tuple or set of tuples. This part
* the typechecking is a hack. We look up the relation that is the * of the typechecking is a hack. We look up the relation that is the
* declared return type, and be sure that attributes 1 .. n in the target * declared return type, and be sure that attributes 1 .. n in the
* list match the declared types. * target list match the declared types.
*/ */
reln = heap_open(typerelid, AccessShareLock); reln = heap_open(typerelid, AccessShareLock);
relid = reln->rd_id; relid = reln->rd_id;
@ -436,7 +437,7 @@ checkretval(Oid rettype, List *queryTreeList)
typeidTypeName(rettype), typeidTypeName(rettype),
typeidTypeName(tletype), typeidTypeName(tletype),
typeidTypeName(reln->rd_att->attrs[i]->atttypid), typeidTypeName(reln->rd_att->attrs[i]->atttypid),
i+1); i + 1);
i++; i++;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.60 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -171,24 +171,24 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
*/ */
i = 0; i = 0;
namestrcpy(&name, typeName); namestrcpy(&name, typeName);
values[i++] = NameGetDatum(&name); /* 1 */ values[i++] = NameGetDatum(&name); /* 1 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 2 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 2 */
values[i++] = Int16GetDatum(0); /* 3 */ values[i++] = Int16GetDatum(0); /* 3 */
values[i++] = Int16GetDatum(0); /* 4 */ values[i++] = Int16GetDatum(0); /* 4 */
values[i++] = BoolGetDatum(false); /* 5 */ values[i++] = BoolGetDatum(false); /* 5 */
values[i++] = CharGetDatum(0); /* 6 */ values[i++] = CharGetDatum(0); /* 6 */
values[i++] = BoolGetDatum(false); /* 7 */ values[i++] = BoolGetDatum(false); /* 7 */
values[i++] = CharGetDatum(0); /* 8 */ values[i++] = CharGetDatum(0); /* 8 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 9 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 9 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 10 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 10 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 11 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 11 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
values[i++] = CharGetDatum('i'); /* 15 */ values[i++] = CharGetDatum('i'); /* 15 */
values[i++] = CharGetDatum('p'); /* 16 */ values[i++] = CharGetDatum('p'); /* 16 */
values[i++] = DirectFunctionCall1(textin, values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(typeName)); /* 17 */ CStringGetDatum(typeName)); /* 17 */
/* ---------------- /* ----------------
* create a new type tuple with FormHeapTuple * create a new type tuple with FormHeapTuple
@ -368,16 +368,16 @@ TypeCreate(char *typeName,
*/ */
i = 0; i = 0;
namestrcpy(&name, typeName); namestrcpy(&name, typeName);
values[i++] = NameGetDatum(&name); /* 1 */ values[i++] = NameGetDatum(&name); /* 1 */
values[i++] = Int32GetDatum(GetUserId()); /* 2 */ values[i++] = Int32GetDatum(GetUserId()); /* 2 */
values[i++] = Int16GetDatum(internalSize); /* 3 */ values[i++] = Int16GetDatum(internalSize); /* 3 */
values[i++] = Int16GetDatum(externalSize); /* 4 */ values[i++] = Int16GetDatum(externalSize); /* 4 */
values[i++] = BoolGetDatum(passedByValue); /* 5 */ values[i++] = BoolGetDatum(passedByValue); /* 5 */
values[i++] = CharGetDatum(typeType); /* 6 */ values[i++] = CharGetDatum(typeType); /* 6 */
values[i++] = BoolGetDatum(true); /* 7 */ values[i++] = BoolGetDatum(true); /* 7 */
values[i++] = CharGetDatum(typDelim); /* 8 */ values[i++] = CharGetDatum(typDelim); /* 8 */
values[i++] = ObjectIdGetDatum(typeType == 'c' ? relationOid : InvalidOid); /* 9 */ values[i++] = ObjectIdGetDatum(typeType == 'c' ? relationOid : InvalidOid); /* 9 */
values[i++] = ObjectIdGetDatum(elementObjectId); /* 10 */ values[i++] = ObjectIdGetDatum(elementObjectId); /* 10 */
procs[0] = inputProcedure; procs[0] = inputProcedure;
procs[1] = outputProcedure; procs[1] = outputProcedure;
@ -386,7 +386,7 @@ TypeCreate(char *typeName,
for (j = 0; j < 4; ++j) for (j = 0; j < 4; ++j)
{ {
Oid procOid; Oid procOid;
procname = procs[j]; procname = procs[j];
@ -438,27 +438,27 @@ TypeCreate(char *typeName,
func_error("TypeCreate", procname, 1, argList, NULL); func_error("TypeCreate", procname, 1, argList, NULL);
} }
values[i++] = ObjectIdGetDatum(procOid); /* 11 - 14 */ values[i++] = ObjectIdGetDatum(procOid); /* 11 - 14 */
} }
/* ---------------- /* ----------------
* set default alignment * set default alignment
* ---------------- * ----------------
*/ */
values[i++] = CharGetDatum(alignment); /* 15 */ values[i++] = CharGetDatum(alignment); /* 15 */
/* ---------------- /* ----------------
* set default storage for TOAST * set default storage for TOAST
* ---------------- * ----------------
*/ */
values[i++] = CharGetDatum(storage); /* 16 */ values[i++] = CharGetDatum(storage); /* 16 */
/* ---------------- /* ----------------
* initialize the default value for this type. * initialize the default value for this type.
* ---------------- * ----------------
*/ */
values[i] = DirectFunctionCall1(textin, /* 17 */ values[i] = DirectFunctionCall1(textin, /* 17 */
CStringGetDatum(defaultTypeValue ? defaultTypeValue : "-")); CStringGetDatum(defaultTypeValue ? defaultTypeValue : "-"));
/* ---------------- /* ----------------
* open pg_type and begin a scan for the type name. * open pg_type and begin a scan for the type name.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.14 2001/02/16 03:16:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.15 2001/03/22 03:59:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -86,9 +86,10 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
CommitTransactionCommand(); CommitTransactionCommand();
return; return;
} }
/* /*
* We can VACUUM ANALYZE any table except pg_statistic. * We can VACUUM ANALYZE any table except pg_statistic. see
* see update_relstats * update_relstats
*/ */
if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname), if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname),
StatisticRelationName) == 0) StatisticRelationName) == 0)
@ -104,10 +105,12 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel), if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
RELNAME)) RELNAME))
{ {
/* we already did an elog during vacuum
elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it", /*
RelationGetRelationName(onerel)); * we already did an elog during vacuum elog(NOTICE, "Skipping
*/ * \"%s\" --- only table owner can VACUUM it",
* RelationGetRelationName(onerel));
*/
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
CommitTransactionCommand(); CommitTransactionCommand();
return; return;
@ -136,7 +139,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
if (namestrcmp(&(attr[i]->attname), col) == 0) if (namestrcmp(&(attr[i]->attname), col) == 0)
break; break;
} }
if (i < attr_cnt) /* found */ if (i < attr_cnt) /* found */
attnums[tcnt++] = i; attnums[tcnt++] = i;
else else
{ {
@ -295,15 +298,16 @@ attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple
stats->nonnull_cnt++; stats->nonnull_cnt++;
/* /*
* If the value is toasted, detoast it to avoid repeated detoastings * If the value is toasted, detoast it to avoid repeated
* and resultant memory leakage inside the comparison routines. * detoastings and resultant memory leakage inside the comparison
* routines.
*/ */
if (!stats->attr->attbyval && stats->attr->attlen == -1) if (!stats->attr->attbyval && stats->attr->attlen == -1)
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue)); value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
else else
value = origvalue; value = origvalue;
if (! stats->initialized) if (!stats->initialized)
{ {
bucketcpy(stats->attr, value, &stats->best, &stats->best_len); bucketcpy(stats->attr, value, &stats->best, &stats->best_len);
/* best_cnt gets incremented below */ /* best_cnt gets incremented below */
@ -433,7 +437,7 @@ bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len)
* Of course, this only works for fixed-size never-null columns, but * Of course, this only works for fixed-size never-null columns, but
* dispersion is. * dispersion is.
* *
* pg_statistic rows are just added normally. This means that * pg_statistic rows are just added normally. This means that
* pg_statistic will probably contain some deleted rows at the * pg_statistic will probably contain some deleted rows at the
* completion of a vacuum cycle, unless it happens to get vacuumed last. * completion of a vacuum cycle, unless it happens to get vacuumed last.
* *
@ -467,7 +471,7 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
VacAttrStats *stats; VacAttrStats *stats;
attp = (Form_pg_attribute) GETSTRUCT(atup); attp = (Form_pg_attribute) GETSTRUCT(atup);
if (attp->attnum <= 0) /* skip system attributes for now */ if (attp->attnum <= 0) /* skip system attributes for now */
continue; continue;
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
@ -476,47 +480,45 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
break; break;
} }
if (i >= natts) if (i >= natts)
continue; /* skip attr if no stats collected */ continue; /* skip attr if no stats collected */
stats = &(vacattrstats[i]); stats = &(vacattrstats[i]);
if (VacAttrStatsEqValid(stats)) if (VacAttrStatsEqValid(stats))
{ {
float4 selratio; /* average ratio of rows selected float4 selratio; /* average ratio of rows selected
* for a random constant */ * for a random constant */
/* Compute dispersion */ /* Compute dispersion */
if (stats->nonnull_cnt == 0 && stats->null_cnt == 0) if (stats->nonnull_cnt == 0 && stats->null_cnt == 0)
{ {
/* /*
* empty relation, so put a dummy value in * empty relation, so put a dummy value in attdispersion
* attdispersion
*/ */
selratio = 0; selratio = 0;
} }
else if (stats->null_cnt <= 1 && stats->best_cnt == 1) else if (stats->null_cnt <= 1 && stats->best_cnt == 1)
{ {
/* /*
* looks like we have a unique-key attribute --- flag * looks like we have a unique-key attribute --- flag this
* this with special -1.0 flag value. * with special -1.0 flag value.
* *
* The correct dispersion is 1.0/numberOfRows, but since * The correct dispersion is 1.0/numberOfRows, but since the
* the relation row count can get updated without * relation row count can get updated without recomputing
* recomputing dispersion, we want to store a * dispersion, we want to store a "symbolic" value and
* "symbolic" value and figure 1.0/numberOfRows on the * figure 1.0/numberOfRows on the fly.
* fly.
*/ */
selratio = -1; selratio = -1;
} }
else else
{ {
if (VacAttrStatsLtGtValid(stats) && if (VacAttrStatsLtGtValid(stats) &&
stats->min_cnt + stats->max_cnt == stats->nonnull_cnt) stats->min_cnt + stats->max_cnt == stats->nonnull_cnt)
{ {
/* /*
* exact result when there are just 1 or 2 * exact result when there are just 1 or 2 values...
* values...
*/ */
double min_cnt_d = stats->min_cnt, double min_cnt_d = stats->min_cnt,
max_cnt_d = stats->max_cnt, max_cnt_d = stats->max_cnt,
@ -552,12 +554,12 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
/* /*
* Create pg_statistic tuples for the relation, if we have * Create pg_statistic tuples for the relation, if we have
* gathered the right data. del_stats() previously * gathered the right data. del_stats() previously deleted
* deleted all the pg_statistic tuples for the rel, so we * all the pg_statistic tuples for the rel, so we just have to
* just have to insert new ones here. * insert new ones here.
* *
* Note analyze_rel() has seen to it that we won't come here * Note analyze_rel() has seen to it that we won't come here when
* when vacuuming pg_statistic itself. * vacuuming pg_statistic itself.
*/ */
if (VacAttrStatsLtGtValid(stats) && stats->initialized) if (VacAttrStatsLtGtValid(stats) && stats->initialized)
{ {
@ -567,7 +569,7 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
char *out_string; char *out_string;
double best_cnt_d = stats->best_cnt, double best_cnt_d = stats->best_cnt,
null_cnt_d = stats->null_cnt, null_cnt_d = stats->null_cnt,
nonnull_cnt_d = stats->nonnull_cnt; /* prevent overflow */ nonnull_cnt_d = stats->nonnull_cnt; /* prevent overflow */
Datum values[Natts_pg_statistic]; Datum values[Natts_pg_statistic];
char nulls[Natts_pg_statistic]; char nulls[Natts_pg_statistic];
Relation irelations[Num_pg_statistic_indices]; Relation irelations[Num_pg_statistic_indices];
@ -585,31 +587,31 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
* ---------------- * ----------------
*/ */
i = 0; i = 0;
values[i++] = ObjectIdGetDatum(relid); /* starelid */ values[i++] = ObjectIdGetDatum(relid); /* starelid */
values[i++] = Int16GetDatum(attp->attnum); /* staattnum */ values[i++] = Int16GetDatum(attp->attnum); /* staattnum */
values[i++] = ObjectIdGetDatum(stats->op_cmplt); /* staop */ values[i++] = ObjectIdGetDatum(stats->op_cmplt); /* staop */
values[i++] = Float4GetDatum(nullratio); /* stanullfrac */ values[i++] = Float4GetDatum(nullratio); /* stanullfrac */
values[i++] = Float4GetDatum(bestratio); /* stacommonfrac */ values[i++] = Float4GetDatum(bestratio); /* stacommonfrac */
out_string = DatumGetCString(FunctionCall3(&out_function, out_string = DatumGetCString(FunctionCall3(&out_function,
stats->best, stats->best,
ObjectIdGetDatum(stats->typelem), ObjectIdGetDatum(stats->typelem),
Int32GetDatum(stats->attr->atttypmod))); Int32GetDatum(stats->attr->atttypmod)));
values[i++] = DirectFunctionCall1(textin, /* stacommonval */ values[i++] = DirectFunctionCall1(textin, /* stacommonval */
CStringGetDatum(out_string)); CStringGetDatum(out_string));
pfree(out_string); pfree(out_string);
out_string = DatumGetCString(FunctionCall3(&out_function, out_string = DatumGetCString(FunctionCall3(&out_function,
stats->min, stats->min,
ObjectIdGetDatum(stats->typelem), ObjectIdGetDatum(stats->typelem),
Int32GetDatum(stats->attr->atttypmod))); Int32GetDatum(stats->attr->atttypmod)));
values[i++] = DirectFunctionCall1(textin, /* staloval */ values[i++] = DirectFunctionCall1(textin, /* staloval */
CStringGetDatum(out_string)); CStringGetDatum(out_string));
pfree(out_string); pfree(out_string);
out_string = DatumGetCString(FunctionCall3(&out_function, out_string = DatumGetCString(FunctionCall3(&out_function,
stats->max, stats->max,
ObjectIdGetDatum(stats->typelem), ObjectIdGetDatum(stats->typelem),
Int32GetDatum(stats->attr->atttypmod))); Int32GetDatum(stats->attr->atttypmod)));
values[i++] = DirectFunctionCall1(textin, /* stahival */ values[i++] = DirectFunctionCall1(textin, /* stahival */
CStringGetDatum(out_string)); CStringGetDatum(out_string));
pfree(out_string); pfree(out_string);
stup = heap_formtuple(sd->rd_att, values, nulls); stup = heap_formtuple(sd->rd_att, values, nulls);
@ -682,6 +684,3 @@ del_stats(Oid relid, int attcnt, int *attnums)
*/ */
heap_close(pgstatistic, NoLock); heap_close(pgstatistic, NoLock);
} }

View File

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

View File

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

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.122 2001/02/27 22:07:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.123 2001/03/22 03:59:21 momjian Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
@ -173,29 +173,29 @@ PerformPortalFetch(char *name,
* at the end of the available tuples in that direction. If so, do * at the end of the available tuples in that direction. If so, do
* nothing. (This check exists because not all plan node types are * nothing. (This check exists because not all plan node types are
* robust about being called again if they've already returned NULL * robust about being called again if they've already returned NULL
* once.) If it's OK to do the fetch, call the executor. Then, * once.) If it's OK to do the fetch, call the executor. Then,
* update the atStart/atEnd state depending on the number of tuples * update the atStart/atEnd state depending on the number of tuples
* that were retrieved. * that were retrieved.
* ---------------- * ----------------
*/ */
if (forward) if (forward)
{ {
if (! portal->atEnd) if (!portal->atEnd)
{ {
ExecutorRun(queryDesc, estate, EXEC_FOR, (long) count); ExecutorRun(queryDesc, estate, EXEC_FOR, (long) count);
if (estate->es_processed > 0) if (estate->es_processed > 0)
portal->atStart = false; /* OK to back up now */ portal->atStart = false; /* OK to back up now */
if (count <= 0 || (int) estate->es_processed < count) if (count <= 0 || (int) estate->es_processed < count)
portal->atEnd = true; /* we retrieved 'em all */ portal->atEnd = true; /* we retrieved 'em all */
} }
} }
else else
{ {
if (! portal->atStart) if (!portal->atStart)
{ {
ExecutorRun(queryDesc, estate, EXEC_BACK, (long) count); ExecutorRun(queryDesc, estate, EXEC_BACK, (long) count);
if (estate->es_processed > 0) if (estate->es_processed > 0)
portal->atEnd = false; /* OK to go forward now */ portal->atEnd = false; /* OK to go forward now */
if (count <= 0 || (int) estate->es_processed < count) if (count <= 0 || (int) estate->es_processed < count)
portal->atStart = true; /* we retrieved 'em all */ portal->atStart = true; /* we retrieved 'em all */
} }
@ -502,8 +502,8 @@ AlterTableAddColumn(const char *relationName,
heap_close(rel, NoLock); heap_close(rel, NoLock);
/* /*
* Automatically create the secondary relation for TOAST * Automatically create the secondary relation for TOAST if it
* if it formerly had no such but now has toastable attributes. * formerly had no such but now has toastable attributes.
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
AlterTableCreateToastTable(relationName, true); AlterTableCreateToastTable(relationName, true);
@ -842,7 +842,7 @@ RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup)
relcheck = (Form_pg_relcheck) GETSTRUCT(htup); relcheck = (Form_pg_relcheck) GETSTRUCT(htup);
ccbin = DatumGetCString(DirectFunctionCall1(textout, ccbin = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(&relcheck->rcbin))); PointerGetDatum(&relcheck->rcbin)));
node = stringToNode(ccbin); node = stringToNode(ccbin);
pfree(ccbin); pfree(ccbin);
if (find_attribute_in_node(node, attnum)) if (find_attribute_in_node(node, attnum))
@ -890,7 +890,7 @@ RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup)
else else
{ {
htup = SearchSysCache(RELOID, htup = SearchSysCache(RELOID,
ObjectIdGetDatum(index->indexrelid), ObjectIdGetDatum(index->indexrelid),
0, 0, 0); 0, 0, 0);
RemoveIndex(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname)); RemoveIndex(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname));
ReleaseSysCache(htup); ReleaseSysCache(htup);
@ -1106,339 +1106,361 @@ AlterTableAddConstraint(char *relationName,
#endif #endif
/* Disallow ADD CONSTRAINT on views, indexes, sequences, etc */ /* Disallow ADD CONSTRAINT on views, indexes, sequences, etc */
if (! is_relation(relationName)) if (!is_relation(relationName))
elog(ERROR, "ALTER TABLE ADD CONSTRAINT: %s is not a table", elog(ERROR, "ALTER TABLE ADD CONSTRAINT: %s is not a table",
relationName); relationName);
switch (nodeTag(newConstraint)) switch (nodeTag(newConstraint))
{ {
case T_Constraint: case T_Constraint:
{
Constraint *constr = (Constraint *) newConstraint;
switch (constr->contype)
{ {
case CONSTR_CHECK: Constraint *constr = (Constraint *) newConstraint;
switch (constr->contype)
{ {
ParseState *pstate; case CONSTR_CHECK:
bool successful = true;
HeapScanDesc scan;
ExprContext *econtext;
TupleTableSlot *slot;
HeapTuple tuple;
RangeTblEntry *rte;
List *qual;
List *constlist;
Relation rel;
Node *expr;
char *name;
if (constr->name)
name = constr->name;
else
name = "<unnamed>";
constlist = makeList1(constr);
rel = heap_openr(relationName, AccessExclusiveLock);
/* make sure it is not a view */
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "ALTER TABLE: cannot add constraint to a view");
/*
* Scan all of the rows, looking for a false match
*/
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
AssertState(scan != NULL);
/*
* We need to make a parse state and range table to allow
* us to transformExpr and fix_opids to get a version of
* the expression we can pass to ExecQual
*/
pstate = make_parsestate(NULL);
rte = addRangeTableEntry(pstate, relationName, NULL,
false, true);
addRTEtoQuery(pstate, rte, true, true);
/* Convert the A_EXPR in raw_expr into an EXPR */
expr = transformExpr(pstate, constr->raw_expr,
EXPR_COLUMN_FIRST);
/*
* Make sure it yields a boolean result.
*/
if (exprType(expr) != BOOLOID)
elog(ERROR, "CHECK '%s' does not yield boolean result",
name);
/*
* Make sure no outside relations are referred to.
*/
if (length(pstate->p_rtable) != 1)
elog(ERROR, "Only relation '%s' can be referenced in CHECK",
relationName);
/*
* Might as well try to reduce any constant expressions.
*/
expr = eval_const_expressions(expr);
/* And fix the opids */
fix_opids(expr);
qual = makeList1(expr);
/* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
/* Make an expression context for ExecQual */
econtext = MakeExprContext(slot, CurrentMemoryContext);
/*
* Scan through the rows now, checking the expression
* at each row.
*/
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
if (!ExecQual(qual, econtext, true))
{ {
successful=false; ParseState *pstate;
bool successful = true;
HeapScanDesc scan;
ExprContext *econtext;
TupleTableSlot *slot;
HeapTuple tuple;
RangeTblEntry *rte;
List *qual;
List *constlist;
Relation rel;
Node *expr;
char *name;
if (constr->name)
name = constr->name;
else
name = "<unnamed>";
constlist = makeList1(constr);
rel = heap_openr(relationName, AccessExclusiveLock);
/* make sure it is not a view */
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "ALTER TABLE: cannot add constraint to a view");
/*
* Scan all of the rows, looking for a false
* match
*/
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
AssertState(scan != NULL);
/*
* We need to make a parse state and range
* table to allow us to transformExpr and
* fix_opids to get a version of the
* expression we can pass to ExecQual
*/
pstate = make_parsestate(NULL);
rte = addRangeTableEntry(pstate, relationName, NULL,
false, true);
addRTEtoQuery(pstate, rte, true, true);
/* Convert the A_EXPR in raw_expr into an EXPR */
expr = transformExpr(pstate, constr->raw_expr,
EXPR_COLUMN_FIRST);
/*
* Make sure it yields a boolean result.
*/
if (exprType(expr) != BOOLOID)
elog(ERROR, "CHECK '%s' does not yield boolean result",
name);
/*
* Make sure no outside relations are referred
* to.
*/
if (length(pstate->p_rtable) != 1)
elog(ERROR, "Only relation '%s' can be referenced in CHECK",
relationName);
/*
* Might as well try to reduce any constant
* expressions.
*/
expr = eval_const_expressions(expr);
/* And fix the opids */
fix_opids(expr);
qual = makeList1(expr);
/* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
/* Make an expression context for ExecQual */
econtext = MakeExprContext(slot, CurrentMemoryContext);
/*
* Scan through the rows now, checking the
* expression at each row.
*/
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
if (!ExecQual(qual, econtext, true))
{
successful = false;
break;
}
ResetExprContext(econtext);
}
FreeExprContext(econtext);
pfree(slot);
heap_endscan(scan);
if (!successful)
{
heap_close(rel, NoLock);
elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s", name);
}
/*
* Call AddRelationRawConstraints to do the
* real adding -- It duplicates some of the
* above, but does not check the validity of
* the constraint against tuples already in
* the table.
*/
AddRelationRawConstraints(rel, NIL, constlist);
heap_close(rel, NoLock);
pfree(constlist);
break; break;
} }
ResetExprContext(econtext); default:
} elog(ERROR, "ALTER TABLE / ADD CONSTRAINT is not implemented for that constraint type.");
FreeExprContext(econtext);
pfree(slot);
heap_endscan(scan);
if (!successful)
{
heap_close(rel, NoLock);
elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s", name);
}
/*
* Call AddRelationRawConstraints to do the real adding --
* It duplicates some of the above, but does not check the
* validity of the constraint against tuples already in
* the table.
*/
AddRelationRawConstraints(rel, NIL, constlist);
heap_close(rel, NoLock);
pfree(constlist);
break;
} }
default: break;
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT is not implemented for that constraint type.");
} }
break;
}
case T_FkConstraint: case T_FkConstraint:
{
FkConstraint *fkconstraint = (FkConstraint *) newConstraint;
Relation rel, pkrel;
HeapScanDesc scan;
HeapTuple tuple;
Trigger trig;
List *list;
int count;
List *indexoidlist,
*indexoidscan;
Form_pg_attribute *rel_attrs = NULL;
int i;
bool found = false;
if (is_temp_rel_name(fkconstraint->pktable_name) &&
!is_temp_rel_name(relationName))
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
/*
* Grab an exclusive lock on the pk table, so that someone
* doesn't delete rows out from under us.
*/
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referenced table \"%s\" not a relation",
fkconstraint->pktable_name);
/*
* Grab an exclusive lock on the fk table, and then scan
* through each tuple, calling the RI_FKey_Match_Ins
* (insert trigger) as if that tuple had just been
* inserted. If any of those fail, it should elog(ERROR)
* and that's that.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referencing table \"%s\" not a relation",
relationName);
/* First we check for limited correctness of the constraint */
rel_attrs = pkrel->rd_att->attrs;
indexoidlist = RelationGetIndexList(pkrel);
foreach(indexoidscan, indexoidlist)
{ {
Oid indexoid = lfirsti(indexoidscan); FkConstraint *fkconstraint = (FkConstraint *) newConstraint;
HeapTuple indexTuple; Relation rel,
Form_pg_index indexStruct; pkrel;
HeapScanDesc scan;
HeapTuple tuple;
Trigger trig;
List *list;
int count;
List *indexoidlist,
*indexoidscan;
Form_pg_attribute *rel_attrs = NULL;
int i;
bool found = false;
indexTuple = SearchSysCache(INDEXRELID, if (is_temp_rel_name(fkconstraint->pktable_name) &&
ObjectIdGetDatum(indexoid), !is_temp_rel_name(relationName))
0, 0, 0); elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
if (!HeapTupleIsValid(indexTuple))
elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
indexoid);
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
if (indexStruct->indisunique) /*
* Grab an exclusive lock on the pk table, so that someone
* doesn't delete rows out from under us.
*/
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referenced table \"%s\" not a relation",
fkconstraint->pktable_name);
/*
* Grab an exclusive lock on the fk table, and then scan
* through each tuple, calling the RI_FKey_Match_Ins
* (insert trigger) as if that tuple had just been
* inserted. If any of those fail, it should elog(ERROR)
* and that's that.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referencing table \"%s\" not a relation",
relationName);
/*
* First we check for limited correctness of the
* constraint
*/
rel_attrs = pkrel->rd_att->attrs;
indexoidlist = RelationGetIndexList(pkrel);
foreach(indexoidscan, indexoidlist)
{ {
List *attrl; Oid indexoid = lfirsti(indexoidscan);
HeapTuple indexTuple;
Form_pg_index indexStruct;
/* Make sure this index has the same number of keys -- It obviously indexTuple = SearchSysCache(INDEXRELID,
* won't match otherwise. */ ObjectIdGetDatum(indexoid),
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++); 0, 0, 0);
if (i!=length(fkconstraint->pk_attrs)) if (!HeapTupleIsValid(indexTuple))
found=false; elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
else { indexoid);
/* go through the fkconstraint->pk_attrs list */ indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
foreach(attrl, fkconstraint->pk_attrs)
{ if (indexStruct->indisunique)
Ident *attr=lfirst(attrl); {
List *attrl;
/*
* Make sure this index has the same number of
* keys -- It obviously won't match otherwise.
*/
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
if (i != length(fkconstraint->pk_attrs))
found = false; found = false;
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) else
{
/* go through the fkconstraint->pk_attrs list */
foreach(attrl, fkconstraint->pk_attrs)
{ {
int pkattno = indexStruct->indkey[i]; Ident *attr = lfirst(attrl);
if (pkattno>0)
found = false;
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
{ {
char *name = NameStr(rel_attrs[pkattno-1]->attname); int pkattno = indexStruct->indkey[i];
if (strcmp(name, attr->name)==0)
if (pkattno > 0)
{ {
found = true; char *name = NameStr(rel_attrs[pkattno - 1]->attname);
break;
if (strcmp(name, attr->name) == 0)
{
found = true;
break;
}
} }
} }
if (!found)
break;
} }
if (!found)
break;
} }
} }
} ReleaseSysCache(indexTuple);
ReleaseSysCache(indexTuple); if (found)
if (found)
break;
}
if (!found)
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
fkconstraint->pktable_name);
freeList(indexoidlist);
heap_close(pkrel, NoLock);
rel_attrs = rel->rd_att->attrs;
if (fkconstraint->fk_attrs!=NIL) {
List *fkattrs;
Ident *fkattr;
found = false;
foreach(fkattrs, fkconstraint->fk_attrs) {
int count;
found = false;
fkattr=lfirst(fkattrs);
for (count = 0; count < rel->rd_att->natts; count++) {
char *name = NameStr(rel->rd_att->attrs[count]->attname);
if (strcmp(name, fkattr->name)==0) {
found = true;
break;
}
}
if (!found)
break; break;
} }
if (!found) if (!found)
elog(ERROR, "columns referenced in foreign key constraint not found."); elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
} fkconstraint->pktable_name);
trig.tgoid = 0; freeList(indexoidlist);
if (fkconstraint->constr_name) heap_close(pkrel, NoLock);
trig.tgname = fkconstraint->constr_name;
else
trig.tgname = "<unknown>";
trig.tgfoid = 0;
trig.tgtype = 0;
trig.tgenabled = TRUE;
trig.tgisconstraint = TRUE;
trig.tginitdeferred = FALSE;
trig.tgdeferrable = FALSE;
trig.tgargs = (char **) palloc( rel_attrs = rel->rd_att->attrs;
sizeof(char *) * (4 + length(fkconstraint->fk_attrs) if (fkconstraint->fk_attrs != NIL)
+ length(fkconstraint->pk_attrs))); {
List *fkattrs;
Ident *fkattr;
if (fkconstraint->constr_name) found = false;
trig.tgargs[0] = fkconstraint->constr_name; foreach(fkattrs, fkconstraint->fk_attrs)
else {
trig.tgargs[0] = "<unknown>"; int count;
trig.tgargs[1] = (char *) relationName;
trig.tgargs[2] = fkconstraint->pktable_name; found = false;
trig.tgargs[3] = fkconstraint->match_type; fkattr = lfirst(fkattrs);
count = 4; for (count = 0; count < rel->rd_att->natts; count++)
foreach(list, fkconstraint->fk_attrs) {
char *name = NameStr(rel->rd_att->attrs[count]->attname);
if (strcmp(name, fkattr->name) == 0)
{
found = true;
break;
}
}
if (!found)
break;
}
if (!found)
elog(ERROR, "columns referenced in foreign key constraint not found.");
}
trig.tgoid = 0;
if (fkconstraint->constr_name)
trig.tgname = fkconstraint->constr_name;
else
trig.tgname = "<unknown>";
trig.tgfoid = 0;
trig.tgtype = 0;
trig.tgenabled = TRUE;
trig.tgisconstraint = TRUE;
trig.tginitdeferred = FALSE;
trig.tgdeferrable = FALSE;
trig.tgargs = (char **) palloc(
sizeof(char *) * (4 + length(fkconstraint->fk_attrs)
+ length(fkconstraint->pk_attrs)));
if (fkconstraint->constr_name)
trig.tgargs[0] = fkconstraint->constr_name;
else
trig.tgargs[0] = "<unknown>";
trig.tgargs[1] = (char *) relationName;
trig.tgargs[2] = fkconstraint->pktable_name;
trig.tgargs[3] = fkconstraint->match_type;
count = 4;
foreach(list, fkconstraint->fk_attrs)
{ {
Ident *fk_at = lfirst(list); Ident *fk_at = lfirst(list);
trig.tgargs[count] = fk_at->name; trig.tgargs[count] = fk_at->name;
count+=2; count += 2;
} }
count = 5; count = 5;
foreach(list, fkconstraint->pk_attrs) foreach(list, fkconstraint->pk_attrs)
{ {
Ident *pk_at = lfirst(list); Ident *pk_at = lfirst(list);
trig.tgargs[count] = pk_at->name; trig.tgargs[count] = pk_at->name;
count+=2; count += 2;
} }
trig.tgnargs = count-1; trig.tgnargs = count - 1;
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL); scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
AssertState(scan != NULL); AssertState(scan != NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{ {
/* Make a call to the check function */ /* Make a call to the check function */
/* No parameters are passed, but we do set a context */ /* No parameters are passed, but we do set a context */
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
TriggerData trigdata; TriggerData trigdata;
MemSet(&fcinfo, 0, sizeof(fcinfo)); MemSet(&fcinfo, 0, sizeof(fcinfo));
/* We assume RI_FKey_check_ins won't look at flinfo... */ /* We assume RI_FKey_check_ins won't look at flinfo... */
trigdata.type = T_TriggerData; trigdata.type = T_TriggerData;
trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW; trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
trigdata.tg_relation = rel; trigdata.tg_relation = rel;
trigdata.tg_trigtuple = tuple; trigdata.tg_trigtuple = tuple;
trigdata.tg_newtuple = NULL; trigdata.tg_newtuple = NULL;
trigdata.tg_trigger = &trig; trigdata.tg_trigger = &trig;
fcinfo.context = (Node *) &trigdata; fcinfo.context = (Node *) &trigdata;
RI_FKey_check_ins(&fcinfo); RI_FKey_check_ins(&fcinfo);
}
heap_endscan(scan);
heap_close(rel, NoLock); /* close rel but keep
* lock! */
pfree(trig.tgargs);
break;
} }
heap_endscan(scan);
heap_close(rel, NoLock); /* close rel but keep
* lock! */
pfree(trig.tgargs);
break;
}
default: default:
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT unable to determine type of constraint passed"); elog(ERROR, "ALTER TABLE / ADD CONSTRAINT unable to determine type of constraint passed");
} }
@ -1464,15 +1486,15 @@ AlterTableDropConstraint(const char *relationName,
void void
AlterTableOwner(const char *relationName, const char *newOwnerName) AlterTableOwner(const char *relationName, const char *newOwnerName)
{ {
Relation class_rel; Relation class_rel;
HeapTuple tuple; HeapTuple tuple;
int32 newOwnerSysid; int32 newOwnerSysid;
Relation idescs[Num_pg_class_indices]; Relation idescs[Num_pg_class_indices];
/* /*
* first check that we are a superuser * first check that we are a superuser
*/ */
if (! superuser()) if (!superuser())
elog(ERROR, "ALTER TABLE: permission denied"); elog(ERROR, "ALTER TABLE: permission denied");
/* /*
@ -1537,21 +1559,21 @@ AlterTableOwner(const char *relationName, const char *newOwnerName)
void void
AlterTableCreateToastTable(const char *relationName, bool silent) AlterTableCreateToastTable(const char *relationName, bool silent)
{ {
Relation rel; Relation rel;
Oid myrelid; Oid myrelid;
HeapTuple reltup; HeapTuple reltup;
HeapTupleData classtuple; HeapTupleData classtuple;
TupleDesc tupdesc; TupleDesc tupdesc;
Relation class_rel; Relation class_rel;
Buffer buffer; Buffer buffer;
Relation ridescs[Num_pg_class_indices]; Relation ridescs[Num_pg_class_indices];
Oid toast_relid; Oid toast_relid;
Oid toast_idxid; Oid toast_idxid;
char toast_relname[NAMEDATALEN + 1]; char toast_relname[NAMEDATALEN + 1];
char toast_idxname[NAMEDATALEN + 1]; char toast_idxname[NAMEDATALEN + 1];
Relation toast_idxrel; Relation toast_idxrel;
IndexInfo *indexInfo; IndexInfo *indexInfo;
Oid classObjectId[1]; Oid classObjectId[1];
/* /*
* permissions checking. XXX exactly what is appropriate here? * permissions checking. XXX exactly what is appropriate here?
@ -1618,7 +1640,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
/* /*
* Check to see whether the table actually needs a TOAST table. * Check to see whether the table actually needs a TOAST table.
*/ */
if (! needs_toast_table(rel)) if (!needs_toast_table(rel))
{ {
if (silent) if (silent)
{ {
@ -1652,10 +1674,11 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
"chunk_data", "chunk_data",
BYTEAOID, BYTEAOID,
-1, 0, false); -1, 0, false);
/* /*
* Ensure that the toast table doesn't itself get toasted, * Ensure that the toast table doesn't itself get toasted, or we'll be
* or we'll be toast :-(. This is essential for chunk_data because * toast :-(. This is essential for chunk_data because type bytea is
* type bytea is toastable; hit the other two just to be sure. * toastable; hit the other two just to be sure.
*/ */
tupdesc->attrs[0]->attstorage = 'p'; tupdesc->attrs[0]->attstorage = 'p';
tupdesc->attrs[1]->attstorage = 'p'; tupdesc->attrs[1]->attstorage = 'p';
@ -1733,7 +1756,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
} }
/* /*
* Check to see whether the table needs a TOAST table. It does only if * Check to see whether the table needs a TOAST table. It does only if
* (1) there are any toastable attributes, and (2) the maximum length * (1) there are any toastable attributes, and (2) the maximum length
* of a tuple could exceed TOAST_TUPLE_THRESHOLD. (We don't want to * of a tuple could exceed TOAST_TUPLE_THRESHOLD. (We don't want to
* create a toast table for something like "f1 varchar(20)".) * create a toast table for something like "f1 varchar(20)".)
@ -1745,7 +1768,7 @@ needs_toast_table(Relation rel)
bool maxlength_unknown = false; bool maxlength_unknown = false;
bool has_toastable_attrs = false; bool has_toastable_attrs = false;
TupleDesc tupdesc; TupleDesc tupdesc;
Form_pg_attribute *att; Form_pg_attribute *att;
int32 tuple_length; int32 tuple_length;
int i; int i;
@ -1762,8 +1785,8 @@ needs_toast_table(Relation rel)
} }
else else
{ {
int32 maxlen = type_maximum_size(att[i]->atttypid, int32 maxlen = type_maximum_size(att[i]->atttypid,
att[i]->atttypmod); att[i]->atttypmod);
if (maxlen < 0) if (maxlen < 0)
maxlength_unknown = true; maxlength_unknown = true;
@ -1798,7 +1821,7 @@ LockTableCommand(LockStmt *lockstmt)
rel = heap_openr(lockstmt->relname, NoLock); rel = heap_openr(lockstmt->relname, NoLock);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname); elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname);
if (lockstmt->mode == AccessShareLock) if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_RD); aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_RD);
@ -1817,9 +1840,9 @@ LockTableCommand(LockStmt *lockstmt)
static bool static bool
is_relation(char *name) is_relation(char *name)
{ {
Relation rel = heap_openr(name, NoLock); Relation rel = heap_openr(name, NoLock);
bool retval = (rel->rd_rel->relkind == RELKIND_RELATION); bool retval = (rel->rd_rel->relkind == RELKIND_RELATION);
heap_close(rel, NoLock); heap_close(rel, NoLock);

View File

@ -7,7 +7,7 @@
* Copyright (c) 1999, PostgreSQL Global Development Group * Copyright (c) 1999, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.26 2001/01/23 04:32:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.27 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -55,7 +55,7 @@ static void CommentAggregate(char *aggregate, List *arguments, char *comment);
static void CommentProc(char *function, List *arguments, char *comment); static void CommentProc(char *function, List *arguments, char *comment);
static void CommentOperator(char *opname, List *arguments, char *comment); static void CommentOperator(char *opname, List *arguments, char *comment);
static void CommentTrigger(char *trigger, char *relation, char *comments); static void CommentTrigger(char *trigger, char *relation, char *comments);
static void CreateComments(Oid oid, char *comment); static void CreateComments(Oid oid, char *comment);
/*------------------------------------------------------------------ /*------------------------------------------------------------------
* CommentObject -- * CommentObject --

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.134 2001/03/14 21:47:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.135 2001/03/22 03:59:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -76,6 +76,7 @@ static StringInfoData attribute_buf;
#ifdef MULTIBYTE #ifdef MULTIBYTE
static int client_encoding; static int client_encoding;
static int server_encoding; static int server_encoding;
#endif #endif
@ -285,6 +286,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
elog(ERROR, "You must have Postgres superuser privilege to do a COPY " elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or " "directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone."); "from stdin. Psql's \\copy command also works for anyone.");
/* /*
* This restriction is unfortunate, but necessary until the frontend * This restriction is unfortunate, but necessary until the frontend
* COPY protocol is redesigned to be binary-safe... * COPY protocol is redesigned to be binary-safe...
@ -344,8 +346,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
mode_t oumask; /* Pre-existing umask value */ mode_t oumask; /* Pre-existing umask value */
/* /*
* Prevent write to relative path ... too easy to shoot oneself * Prevent write to relative path ... too easy to shoot
* in the foot by overwriting a database file ... * oneself in the foot by overwriting a database file ...
*/ */
if (filename[0] != '/') if (filename[0] != '/')
elog(ERROR, "Relative path not allowed for server side" elog(ERROR, "Relative path not allowed for server side"
@ -408,7 +410,10 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
attr_count = rel->rd_att->natts; attr_count = rel->rd_att->natts;
attr = rel->rd_att->attrs; attr = rel->rd_att->attrs;
/* For binary copy we really only need isvarlena, but compute it all... */ /*
* For binary copy we really only need isvarlena, but compute it
* all...
*/
out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo)); out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
elements = (Oid *) palloc(attr_count * sizeof(Oid)); elements = (Oid *) palloc(attr_count * sizeof(Oid));
isvarlena = (bool *) palloc(attr_count * sizeof(bool)); isvarlena = (bool *) palloc(attr_count * sizeof(bool));
@ -417,7 +422,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
Oid out_func_oid; Oid out_func_oid;
if (!getTypeOutputInfo(attr[i]->atttypid, if (!getTypeOutputInfo(attr[i]->atttypid,
&out_func_oid, &elements[i], &isvarlena[i])) &out_func_oid, &elements[i], &isvarlena[i]))
elog(ERROR, "COPY: couldn't lookup info for type %u", elog(ERROR, "COPY: couldn't lookup info for type %u",
attr[i]->atttypid); attr[i]->atttypid);
fmgr_info(out_func_oid, &out_functions[i]); fmgr_info(out_func_oid, &out_functions[i]);
@ -454,7 +459,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
if (binary) if (binary)
{ {
/* Binary per-tuple header */ /* Binary per-tuple header */
int16 fld_count = attr_count; int16 fld_count = attr_count;
CopySendData(&fld_count, sizeof(int16), fp); CopySendData(&fld_count, sizeof(int16), fp);
/* Send OID if wanted --- note fld_count doesn't include it */ /* Send OID if wanted --- note fld_count doesn't include it */
@ -471,7 +476,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
if (oids) if (oids)
{ {
string = DatumGetCString(DirectFunctionCall1(oidout, string = DatumGetCString(DirectFunctionCall1(oidout,
ObjectIdGetDatum(tuple->t_data->t_oid))); ObjectIdGetDatum(tuple->t_data->t_oid)));
CopySendString(string, fp); CopySendString(string, fp);
pfree(string); pfree(string);
need_delim = true; need_delim = true;
@ -497,20 +502,22 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
{ {
if (!binary) if (!binary)
{ {
CopySendString(null_print, fp); /* null indicator */ CopySendString(null_print, fp); /* null indicator */
} }
else else
{ {
fld_size = 0; /* null marker */ fld_size = 0; /* null marker */
CopySendData(&fld_size, sizeof(int16), fp); CopySendData(&fld_size, sizeof(int16), fp);
} }
} }
else else
{ {
/* /*
* If we have a toasted datum, forcibly detoast it to avoid * If we have a toasted datum, forcibly detoast it to
* memory leakage inside the type's output routine (or * avoid memory leakage inside the type's output routine
* for binary case, becase we must output untoasted value). * (or for binary case, becase we must output untoasted
* value).
*/ */
if (isvarlena[i]) if (isvarlena[i])
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue)); value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
@ -520,9 +527,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
if (!binary) if (!binary)
{ {
string = DatumGetCString(FunctionCall3(&out_functions[i], string = DatumGetCString(FunctionCall3(&out_functions[i],
value, value,
ObjectIdGetDatum(elements[i]), ObjectIdGetDatum(elements[i]),
Int32GetDatum(attr[i]->atttypmod))); Int32GetDatum(attr[i]->atttypmod)));
CopyAttributeOut(fp, string, delim); CopyAttributeOut(fp, string, delim);
pfree(string); pfree(string);
} }
@ -552,8 +559,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
Datum datumBuf; Datum datumBuf;
/* /*
* We need this horsing around because we don't know * We need this horsing around because we don't
* how shorter data values are aligned within a Datum. * know how shorter data values are aligned within
* a Datum.
*/ */
store_att_byval(&datumBuf, value, fld_size); store_att_byval(&datumBuf, value, fld_size);
CopySendData(&datumBuf, CopySendData(&datumBuf,
@ -577,7 +585,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
if (binary) if (binary)
{ {
/* Generate trailer for a binary copy */ /* Generate trailer for a binary copy */
int16 fld_count = -1; int16 fld_count = -1;
CopySendData(&fld_count, sizeof(int16), fp); CopySendData(&fld_count, sizeof(int16), fp);
} }
@ -609,7 +617,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
int done = 0; int done = 0;
char *string; char *string;
ResultRelInfo *resultRelInfo; ResultRelInfo *resultRelInfo;
EState *estate = CreateExecutorState(); /* for ExecConstraints() */ EState *estate = CreateExecutorState(); /* for ExecConstraints() */
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
Oid loaded_oid = InvalidOid; Oid loaded_oid = InvalidOid;
@ -622,11 +630,11 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
/* /*
* We need a ResultRelInfo so we can use the regular executor's * We need a ResultRelInfo so we can use the regular executor's
* index-entry-making machinery. (There used to be a huge amount * index-entry-making machinery. (There used to be a huge amount of
* of code here that basically duplicated execUtils.c ...) * code here that basically duplicated execUtils.c ...)
*/ */
resultRelInfo = makeNode(ResultRelInfo); resultRelInfo = makeNode(ResultRelInfo);
resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
resultRelInfo->ri_RelationDesc = rel; resultRelInfo->ri_RelationDesc = rel;
ExecOpenIndices(resultRelInfo); ExecOpenIndices(resultRelInfo);
@ -673,7 +681,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
if (CopyGetEof(fp)) if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: bogus file header (missing flags)"); elog(ERROR, "COPY BINARY: bogus file header (missing flags)");
file_has_oids = (tmp & (1 << 16)) != 0; file_has_oids = (tmp & (1 << 16)) != 0;
tmp &= ~ (1 << 16); tmp &= ~(1 << 16);
if ((tmp >> 16) != 0) if ((tmp >> 16) != 0)
elog(ERROR, "COPY BINARY: unrecognized critical flags in header"); elog(ERROR, "COPY BINARY: unrecognized critical flags in header");
/* Header extension length */ /* Header extension length */
@ -727,7 +735,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
else else
{ {
loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin, loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(string))); CStringGetDatum(string)));
if (loaded_oid == InvalidOid) if (loaded_oid == InvalidOid)
elog(ERROR, "COPY TEXT: Invalid Oid"); elog(ERROR, "COPY TEXT: Invalid Oid");
} }
@ -747,8 +755,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
{ {
values[i] = FunctionCall3(&in_functions[i], values[i] = FunctionCall3(&in_functions[i],
CStringGetDatum(string), CStringGetDatum(string),
ObjectIdGetDatum(elements[i]), ObjectIdGetDatum(elements[i]),
Int32GetDatum(attr[i]->atttypmod)); Int32GetDatum(attr[i]->atttypmod));
nulls[i] = ' '; nulls[i] = ' ';
} }
} }
@ -757,8 +765,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
} }
else else
{ /* binary */ { /* binary */
int16 fld_count, int16 fld_count,
fld_size; fld_size;
CopyGetData(&fld_count, sizeof(int16), fp); CopyGetData(&fld_count, sizeof(int16), fp);
if (CopyGetEof(fp) || if (CopyGetEof(fp) ||
@ -791,15 +799,15 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
if (CopyGetEof(fp)) if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: unexpected EOF"); elog(ERROR, "COPY BINARY: unexpected EOF");
if (fld_size == 0) if (fld_size == 0)
continue; /* it's NULL; nulls[i] already set */ continue; /* it's NULL; nulls[i] already set */
if (fld_size != attr[i]->attlen) if (fld_size != attr[i]->attlen)
elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d", elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
i+1, (int) fld_size, (int) attr[i]->attlen); i + 1, (int) fld_size, (int) attr[i]->attlen);
if (fld_size == -1) if (fld_size == -1)
{ {
/* varlena field */ /* varlena field */
int32 varlena_size; int32 varlena_size;
Pointer varlena_ptr; Pointer varlena_ptr;
CopyGetData(&varlena_size, sizeof(int32), fp); CopyGetData(&varlena_size, sizeof(int32), fp);
if (CopyGetEof(fp)) if (CopyGetEof(fp))
@ -818,7 +826,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
else if (!attr[i]->attbyval) else if (!attr[i]->attbyval)
{ {
/* fixed-length pass-by-reference */ /* fixed-length pass-by-reference */
Pointer refval_ptr; Pointer refval_ptr;
Assert(fld_size > 0); Assert(fld_size > 0);
refval_ptr = (Pointer) palloc(fld_size); refval_ptr = (Pointer) palloc(fld_size);
@ -833,8 +841,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
Datum datumBuf; Datum datumBuf;
/* /*
* We need this horsing around because we don't know * We need this horsing around because we don't
* how shorter data values are aligned within a Datum. * know how shorter data values are aligned within
* a Datum.
*/ */
Assert(fld_size > 0 && fld_size <= sizeof(Datum)); Assert(fld_size > 0 && fld_size <= sizeof(Datum));
CopyGetData(&datumBuf, fld_size, fp); CopyGetData(&datumBuf, fld_size, fp);
@ -1163,6 +1172,7 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
char *string_start; char *string_start;
int mblen; int mblen;
int i; int i;
#endif #endif
#ifdef MULTIBYTE #ifdef MULTIBYTE
@ -1182,7 +1192,7 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
#endif #endif
#ifdef MULTIBYTE #ifdef MULTIBYTE
for (; (mblen = (server_encoding == client_encoding? 1 : pg_encoding_mblen(client_encoding, string))) && for (; (mblen = (server_encoding == client_encoding ? 1 : pg_encoding_mblen(client_encoding, string))) &&
((c = *string) != '\0'); string += mblen) ((c = *string) != '\0'); string += mblen)
#else #else
for (; (c = *string) != '\0'; string++) for (; (c = *string) != '\0'; string++)
@ -1199,7 +1209,7 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
} }
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (client_encoding != server_encoding) if (client_encoding != server_encoding)
pfree(string_start); /* pfree pg_server_to_client result */ pfree(string_start); /* pfree pg_server_to_client result */
#endif #endif
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.72 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.73 2001/03/22 03:59:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,7 +37,7 @@
static int checkAttrExists(const char *attributeName, static int checkAttrExists(const char *attributeName,
const char *attributeType, List *schema); const char *attributeType, List *schema);
static List *MergeAttributes(List *schema, List *supers, bool istemp, static List *MergeAttributes(List *schema, List *supers, bool istemp,
List **supOids, List **supconstr); List **supOids, List **supconstr);
static void StoreCatalogInheritance(Oid relationId, List *supers); static void StoreCatalogInheritance(Oid relationId, List *supers);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
@ -150,10 +150,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
CommandCounterIncrement(); CommandCounterIncrement();
/* /*
* Open the new relation and acquire exclusive lock on it. This isn't * Open the new relation and acquire exclusive lock on it. This isn't
* really necessary for locking out other backends (since they can't * really necessary for locking out other backends (since they can't
* see the new rel anyway until we commit), but it keeps the lock manager * see the new rel anyway until we commit), but it keeps the lock
* from complaining about deadlock risks. * manager from complaining about deadlock risks.
*/ */
rel = heap_openr(relname, AccessExclusiveLock); rel = heap_openr(relname, AccessExclusiveLock);
@ -242,7 +242,7 @@ TruncateRelation(char *name)
* Varattnos of pg_relcheck.rcbin should be rewritten when * Varattnos of pg_relcheck.rcbin should be rewritten when
* subclasses inherit the constraints from the super class. * subclasses inherit the constraints from the super class.
* Note that these functions rewrite varattnos while walking * Note that these functions rewrite varattnos while walking
* through a node tree. * through a node tree.
*/ */
static bool static bool
change_varattnos_walker(Node *node, const AttrNumber *newattno) change_varattnos_walker(Node *node, const AttrNumber *newattno)
@ -251,15 +251,15 @@ change_varattnos_walker(Node *node, const AttrNumber *newattno)
return false; return false;
if (IsA(node, Var)) if (IsA(node, Var))
{ {
Var *var = (Var *) node; Var *var = (Var *) node;
if (var->varlevelsup == 0 && var->varno == 1) if (var->varlevelsup == 0 && var->varno == 1)
{ {
/* /*
* ??? the following may be a problem when the * ??? the following may be a problem when the node is
* node is multiply referenced though * multiply referenced though stringToNode() doesn't create
* stringToNode() doesn't create such a node * such a node currently.
* currently.
*/ */
Assert(newattno[var->varattno - 1] > 0); Assert(newattno[var->varattno - 1] > 0);
var->varattno = newattno[var->varattno - 1]; var->varattno = newattno[var->varattno - 1];
@ -373,9 +373,12 @@ MergeAttributes(List *schema, List *supers, bool istemp,
AttrNumber attrno; AttrNumber attrno;
TupleDesc tupleDesc; TupleDesc tupleDesc;
TupleConstr *constr; TupleConstr *constr;
AttrNumber *newattno, *partialAttidx; AttrNumber *newattno,
Node *expr; *partialAttidx;
int i, attidx, attno_exist; Node *expr;
int i,
attidx,
attno_exist;
relation = heap_openr(name, AccessShareLock); relation = heap_openr(name, AccessShareLock);
@ -385,7 +388,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
if (!istemp && is_temp_rel_name(name)) if (!istemp && is_temp_rel_name(name))
elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name); elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name);
/* We should have an UNDER permission flag for this, but for now, /*
* We should have an UNDER permission flag for this, but for now,
* demand that creator of a child table own the parent. * demand that creator of a child table own the parent.
*/ */
if (!pg_ownercheck(GetUserId(), name, RELNAME)) if (!pg_ownercheck(GetUserId(), name, RELNAME))
@ -397,14 +401,15 @@ MergeAttributes(List *schema, List *supers, bool istemp,
/* allocate a new attribute number table and initialize */ /* allocate a new attribute number table and initialize */
newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber)); newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
for (i = 0; i < tupleDesc->natts; i++) for (i = 0; i < tupleDesc->natts; i++)
newattno [i] = 0; newattno[i] = 0;
/* /*
* searching and storing order are different. * searching and storing order are different. another table is
* another table is needed. * needed.
*/ */
partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber)); partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
for (i = 0; i < tupleDesc->natts; i++) for (i = 0; i < tupleDesc->natts; i++)
partialAttidx [i] = 0; partialAttidx[i] = 0;
constr = tupleDesc->constr; constr = tupleDesc->constr;
attidx = 0; attidx = 0;
@ -577,9 +582,9 @@ StoreCatalogInheritance(Oid relationId, List *supers)
Datum datum[Natts_pg_inherits]; Datum datum[Natts_pg_inherits];
char nullarr[Natts_pg_inherits]; char nullarr[Natts_pg_inherits];
datum[0] = ObjectIdGetDatum(relationId); /* inhrel */ datum[0] = ObjectIdGetDatum(relationId); /* inhrel */
datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */ datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */ datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
nullarr[0] = ' '; nullarr[0] = ' ';
nullarr[1] = ' '; nullarr[1] = ' ';
@ -730,7 +735,7 @@ checkAttrExists(const char *attributeName, const char *attributeType,
List *schema) List *schema)
{ {
List *s; List *s;
int i = 0; int i = 0;
foreach(s, schema) foreach(s, schema)
{ {
@ -756,9 +761,9 @@ checkAttrExists(const char *attributeName, const char *attributeType,
static void static void
setRelhassubclassInRelation(Oid relationId, bool relhassubclass) setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
{ {
Relation relationRelation; Relation relationRelation;
HeapTuple tuple; HeapTuple tuple;
Relation idescs[Num_pg_class_indices]; Relation idescs[Num_pg_class_indices];
/* /*
* Fetch a modifiable copy of the tuple, modify it, update pg_class. * Fetch a modifiable copy of the tuple, modify it, update pg_class.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.73 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.74 2001/03/22 03:59:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -36,8 +36,8 @@
/* non-export function prototypes */ /* non-export function prototypes */
static bool get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, static bool get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
int *encodingP, bool *dbIsTemplateP, int *encodingP, bool *dbIsTemplateP,
Oid *dbLastSysOidP, char *dbpath); Oid *dbLastSysOidP, char *dbpath);
static bool get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb); static bool get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb);
static char *resolve_alt_dbpath(const char *dbpath, Oid dboid); static char *resolve_alt_dbpath(const char *dbpath, Oid dboid);
static bool remove_dbdirs(const char *real_loc, const char *altloc); static bool remove_dbdirs(const char *real_loc, const char *altloc);
@ -82,12 +82,12 @@ createdb(const char *dbname, const char *dbpath,
elog(ERROR, "CREATE DATABASE: may not be called in a transaction block"); elog(ERROR, "CREATE DATABASE: may not be called in a transaction block");
/* /*
* Check for db name conflict. There is a race condition here, since * Check for db name conflict. There is a race condition here, since
* another backend could create the same DB name before we commit. * another backend could create the same DB name before we commit.
* However, holding an exclusive lock on pg_database for the whole time * However, holding an exclusive lock on pg_database for the whole
* we are copying the source database doesn't seem like a good idea, * time we are copying the source database doesn't seem like a good
* so accept possibility of race to create. We will check again after * idea, so accept possibility of race to create. We will check again
* we grab the exclusive lock. * after we grab the exclusive lock.
*/ */
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL)) if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL))
elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname); elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname);
@ -96,15 +96,16 @@ createdb(const char *dbname, const char *dbpath,
* Lookup database (template) to be cloned. * Lookup database (template) to be cloned.
*/ */
if (!dbtemplate) if (!dbtemplate)
dbtemplate = "template1"; /* Default template database name */ dbtemplate = "template1"; /* Default template database name */
if (!get_db_info(dbtemplate, &src_dboid, &src_owner, &src_encoding, if (!get_db_info(dbtemplate, &src_dboid, &src_owner, &src_encoding,
&src_istemplate, &src_lastsysoid, src_dbpath)) &src_istemplate, &src_lastsysoid, src_dbpath))
elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist", elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist",
dbtemplate); dbtemplate);
/* /*
* Permission check: to copy a DB that's not marked datistemplate, * Permission check: to copy a DB that's not marked datistemplate, you
* you must be superuser or the owner thereof. * must be superuser or the owner thereof.
*/ */
if (!src_istemplate) if (!src_istemplate)
{ {
@ -112,6 +113,7 @@ createdb(const char *dbname, const char *dbpath,
elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied", elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied",
dbtemplate); dbtemplate);
} }
/* /*
* Determine physical path of source database * Determine physical path of source database
*/ */
@ -133,14 +135,16 @@ createdb(const char *dbname, const char *dbpath,
if (encoding < 0) if (encoding < 0)
encoding = src_encoding; encoding = src_encoding;
/* /*
* Preassign OID for pg_database tuple, so that we can compute db path. * Preassign OID for pg_database tuple, so that we can compute db
* path.
*/ */
dboid = newoid(); dboid = newoid();
/* /*
* Compute nominal location (where we will try to access the database), * Compute nominal location (where we will try to access the
* and resolve alternate physical location if one is specified. * database), and resolve alternate physical location if one is
* specified.
*/ */
nominal_loc = GetDatabasePath(dboid); nominal_loc = GetDatabasePath(dboid);
alt_loc = resolve_alt_dbpath(dbpath, dboid); alt_loc = resolve_alt_dbpath(dbpath, dboid);
@ -155,8 +159,8 @@ createdb(const char *dbname, const char *dbpath,
/* /*
* Force dirty buffers out to disk, to ensure source database is * Force dirty buffers out to disk, to ensure source database is
* up-to-date for the copy. (We really only need to flush buffers * up-to-date for the copy. (We really only need to flush buffers for
* for the source database...) * the source database...)
*/ */
BufferSync(); BufferSync();
@ -231,7 +235,8 @@ createdb(const char *dbname, const char *dbpath,
tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls); tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
tuple->t_data->t_oid = dboid; /* override heap_insert's OID selection */ tuple->t_data->t_oid = dboid; /* override heap_insert's OID
* selection */
heap_insert(pg_database_rel, tuple); heap_insert(pg_database_rel, tuple);
@ -273,9 +278,9 @@ dropdb(const char *dbname)
bool db_istemplate; bool db_istemplate;
bool use_super; bool use_super;
Oid db_id; Oid db_id;
char *alt_loc; char *alt_loc;
char *nominal_loc; char *nominal_loc;
char dbpath[MAXPGPATH]; char dbpath[MAXPGPATH];
Relation pgdbrel; Relation pgdbrel;
HeapScanDesc pgdbscan; HeapScanDesc pgdbscan;
ScanKeyData key; ScanKeyData key;
@ -311,8 +316,8 @@ dropdb(const char *dbname)
elog(ERROR, "DROP DATABASE: permission denied"); elog(ERROR, "DROP DATABASE: permission denied");
/* /*
* Disallow dropping a DB that is marked istemplate. This is just * Disallow dropping a DB that is marked istemplate. This is just to
* to prevent people from accidentally dropping template0 or template1; * prevent people from accidentally dropping template0 or template1;
* they can do so if they're really determined ... * they can do so if they're really determined ...
*/ */
if (db_istemplate) if (db_istemplate)
@ -338,6 +343,7 @@ dropdb(const char *dbname)
tup = heap_getnext(pgdbscan, 0); tup = heap_getnext(pgdbscan, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
/* /*
* This error should never come up since the existence of the * This error should never come up since the existence of the
* database is checked earlier * database is checked earlier
@ -437,7 +443,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
{ {
tmptext = DatumGetTextP(heap_getattr(tuple, tmptext = DatumGetTextP(heap_getattr(tuple,
Anum_pg_database_datpath, Anum_pg_database_datpath,
RelationGetDescr(relation), RelationGetDescr(relation),
&isnull)); &isnull));
if (!isnull) if (!isnull)
{ {
@ -481,11 +487,11 @@ get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb)
static char * static char *
resolve_alt_dbpath(const char * dbpath, Oid dboid) resolve_alt_dbpath(const char *dbpath, Oid dboid)
{ {
const char * prefix; const char *prefix;
char * ret; char *ret;
size_t len; size_t len;
if (dbpath == NULL || dbpath[0] == '\0') if (dbpath == NULL || dbpath[0] == '\0')
return NULL; return NULL;
@ -502,7 +508,8 @@ resolve_alt_dbpath(const char * dbpath, Oid dboid)
else else
{ {
/* must be environment variable */ /* must be environment variable */
char * var = getenv(dbpath); char *var = getenv(dbpath);
if (!var) if (!var)
elog(ERROR, "Postmaster environment variable '%s' not set", dbpath); elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
if (var[0] != '/') if (var[0] != '/')
@ -519,11 +526,11 @@ resolve_alt_dbpath(const char * dbpath, Oid dboid)
static bool static bool
remove_dbdirs(const char * nominal_loc, const char * alt_loc) remove_dbdirs(const char *nominal_loc, const char *alt_loc)
{ {
const char *target_dir; const char *target_dir;
char buf[MAXPGPATH + 100]; char buf[MAXPGPATH + 100];
bool success = true; bool success = true;
target_dir = alt_loc ? alt_loc : nominal_loc; target_dir = alt_loc ? alt_loc : nominal_loc;

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.53 2001/03/22 03:59:22 momjian Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -70,7 +70,7 @@ case_translate_language_name(const char *input, char *output)
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
int i; int i;
for (i = 0; i < NAMEDATALEN-1 && input[i]; ++i) for (i = 0; i < NAMEDATALEN - 1 && input[i]; ++i)
output[i] = tolower((unsigned char) input[i]); output[i] = tolower((unsigned char) input[i]);
output[i] = '\0'; output[i] = '\0';
@ -110,12 +110,12 @@ compute_full_attributes(List *parameters,
Note: currently, only two of these parameters actually do anything: Note: currently, only two of these parameters actually do anything:
* canCache means the optimizer's constant-folder is allowed to * canCache means the optimizer's constant-folder is allowed to
pre-evaluate the function when all its inputs are constants. pre-evaluate the function when all its inputs are constants.
* isStrict means the function should not be called when any NULL * isStrict means the function should not be called when any NULL
inputs are present; instead a NULL result value should be assumed. inputs are present; instead a NULL result value should be assumed.
The other four parameters are not used anywhere. They used to be The other four parameters are not used anywhere. They used to be
used in the "expensive functions" optimizer, but that's been dead code used in the "expensive functions" optimizer, but that's been dead code
for a long time. for a long time.
@ -217,21 +217,26 @@ void
CreateFunction(ProcedureStmt *stmt, CommandDest dest) CreateFunction(ProcedureStmt *stmt, CommandDest dest)
{ {
char *probin_str; char *probin_str;
/* pathname of executable file that executes this function, if any */ /* pathname of executable file that executes this function, if any */
char *prosrc_str; char *prosrc_str;
/* SQL that executes this function, if any */ /* SQL that executes this function, if any */
char *prorettype; char *prorettype;
/* Type of return value (or member of set of values) from function */ /* Type of return value (or member of set of values) from function */
char languageName[NAMEDATALEN]; char languageName[NAMEDATALEN];
/* /*
* name of language of function, with case adjusted: "C", * name of language of function, with case adjusted: "C", "internal",
* "internal", "sql", etc. * "sql", etc.
*/ */
bool returnsSet; bool returnsSet;
/* The function returns a set of values, as opposed to a singleton. */ /* The function returns a set of values, as opposed to a singleton. */
/* /*
@ -257,7 +262,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
if (!superuser()) if (!superuser())
elog(ERROR, elog(ERROR,
"Only users with Postgres superuser privilege are " "Only users with Postgres superuser privilege are "
"permitted to create a function in the '%s' language.\n\t" "permitted to create a function in the '%s' language.\n\t"
"Others may use the 'sql' language " "Others may use the 'sql' language "
"or the created procedural languages.", "or the created procedural languages.",
languageName); languageName);
@ -380,14 +385,14 @@ DefineOperator(char *oprName,
{ {
typeName1 = defGetString(defel); typeName1 = defGetString(defel);
if (IsA(defel->arg, TypeName) if (IsA(defel->arg, TypeName)
&& ((TypeName *) defel->arg)->setof) &&((TypeName *) defel->arg)->setof)
elog(ERROR, "setof type not implemented for leftarg"); elog(ERROR, "setof type not implemented for leftarg");
} }
else if (strcasecmp(defel->defname, "rightarg") == 0) else if (strcasecmp(defel->defname, "rightarg") == 0)
{ {
typeName2 = defGetString(defel); typeName2 = defGetString(defel);
if (IsA(defel->arg, TypeName) if (IsA(defel->arg, TypeName)
&& ((TypeName *) defel->arg)->setof) &&((TypeName *) defel->arg)->setof)
elog(ERROR, "setof type not implemented for rightarg"); elog(ERROR, "setof type not implemented for rightarg");
} }
else if (strcasecmp(defel->defname, "procedure") == 0) else if (strcasecmp(defel->defname, "procedure") == 0)
@ -478,8 +483,8 @@ DefineAggregate(char *aggName, List *parameters)
DefElem *defel = (DefElem *) lfirst(pl); DefElem *defel = (DefElem *) lfirst(pl);
/* /*
* sfunc1, stype1, and initcond1 are accepted as obsolete spellings * sfunc1, stype1, and initcond1 are accepted as obsolete
* for sfunc, stype, initcond. * spellings for sfunc, stype, initcond.
*/ */
if (strcasecmp(defel->defname, "sfunc") == 0) if (strcasecmp(defel->defname, "sfunc") == 0)
transfuncName = defGetString(defel); transfuncName = defGetString(defel);
@ -515,12 +520,12 @@ DefineAggregate(char *aggName, List *parameters)
/* /*
* Most of the argument-checking is done inside of AggregateCreate * Most of the argument-checking is done inside of AggregateCreate
*/ */
AggregateCreate(aggName, /* aggregate name */ AggregateCreate(aggName, /* aggregate name */
transfuncName, /* step function name */ transfuncName, /* step function name */
finalfuncName, /* final function name */ finalfuncName, /* final function name */
baseType, /* type of data being aggregated */ baseType, /* type of data being aggregated */
transType, /* transition data type */ transType, /* transition data type */
initval); /* initial condition */ initval); /* initial condition */
} }
/* /*
@ -543,13 +548,13 @@ DefineType(char *typeName, List *parameters)
char delimiter = DEFAULT_TYPDELIM; char delimiter = DEFAULT_TYPDELIM;
char *shadow_type; char *shadow_type;
List *pl; List *pl;
char alignment = 'i'; /* default alignment */ char alignment = 'i';/* default alignment */
char storage = 'p'; /* default storage in TOAST */ char storage = 'p'; /* default storage in TOAST */
/* /*
* Type names must be one character shorter than other names, * Type names must be one character shorter than other names, allowing
* allowing room to create the corresponding array type name with * room to create the corresponding array type name with prepended
* prepended "_". * "_".
*/ */
if (strlen(typeName) > (NAMEDATALEN - 2)) if (strlen(typeName) > (NAMEDATALEN - 2))
{ {
@ -692,14 +697,16 @@ defGetString(DefElem *def)
switch (nodeTag(def->arg)) switch (nodeTag(def->arg))
{ {
case T_Integer: case T_Integer:
{ {
char *str = palloc(32); char *str = palloc(32);
snprintf(str, 32, "%ld", (long) intVal(def->arg)); snprintf(str, 32, "%ld", (long) intVal(def->arg));
return str; return str;
} }
case T_Float: case T_Float:
/* T_Float values are kept in string form, so this type cheat
/*
* T_Float values are kept in string form, so this type cheat
* works (and doesn't risk losing precision) * works (and doesn't risk losing precision)
*/ */
return strVal(def->arg); return strVal(def->arg);

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.64 2001/01/27 01:41:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.65 2001/03/22 03:59:22 momjian Exp $
* *
*/ */
@ -271,7 +271,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
stringStringInfo(rte->relname)); stringStringInfo(rte->relname));
if (strcmp(rte->eref->relname, rte->relname) != 0) if (strcmp(rte->eref->relname, rte->relname) != 0)
appendStringInfo(str, " %s", appendStringInfo(str, " %s",
stringStringInfo(rte->eref->relname)); stringStringInfo(rte->eref->relname));
} }
break; break;
case T_SubqueryScan: case T_SubqueryScan:

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.45 2001/02/23 09:26:14 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.46 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -49,15 +49,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid); static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP, static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP,
IndexElem *funcIndex, IndexElem *funcIndex,
Oid relId, Oid relId,
char *accessMethodName, Oid accessMethodId); char *accessMethodName, Oid accessMethodId);
static void NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP, static void NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP,
List *attList, List *attList,
Oid relId, Oid relId,
char *accessMethodName, Oid accessMethodId); char *accessMethodName, Oid accessMethodId);
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType, static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType,
char *accessMethodName, Oid accessMethodId); char *accessMethodName, Oid accessMethodId);
static char *GetDefaultOpClass(Oid atttypid); static char *GetDefaultOpClass(Oid atttypid);
/* /*
@ -118,9 +118,9 @@ DefineIndex(char *heapRelationName,
accessMethodName); accessMethodName);
/* /*
* XXX Hardwired hacks to check for limitations on supported index types. * XXX Hardwired hacks to check for limitations on supported index
* We really ought to be learning this info from entries in the pg_am * types. We really ought to be learning this info from entries in the
* table, instead of having it wired in here! * pg_am table, instead of having it wired in here!
*/ */
if (unique && accessMethodId != BTREE_AM_OID) if (unique && accessMethodId != BTREE_AM_OID)
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method"); elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
@ -161,7 +161,8 @@ DefineIndex(char *heapRelationName,
elog(ERROR, "Existing indexes are inactive. REINDEX first"); elog(ERROR, "Existing indexes are inactive. REINDEX first");
/* /*
* Prepare arguments for index_create, primarily an IndexInfo structure * Prepare arguments for index_create, primarily an IndexInfo
* structure
*/ */
indexInfo = makeNode(IndexInfo); indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = (Node *) cnfPred; indexInfo->ii_Predicate = (Node *) cnfPred;
@ -207,7 +208,7 @@ DefineIndex(char *heapRelationName,
/* /*
* We update the relation's pg_class tuple even if it already has * We update the relation's pg_class tuple even if it already has
* relhasindex = true. This is needed to cause a shared-cache-inval * relhasindex = true. This is needed to cause a shared-cache-inval
* message to be sent for the pg_class tuple, which will cause other * message to be sent for the pg_class tuple, which will cause other
* backends to flush their relcache entries and in particular their * backends to flush their relcache entries and in particular their
* cached lists of the indexes for this relation. * cached lists of the indexes for this relation.
@ -415,8 +416,8 @@ FuncIndexArgs(IndexInfo *indexInfo,
* has exact-match or binary-compatible input types. * has exact-match or binary-compatible input types.
* ---------------- * ----------------
*/ */
if (! func_get_detail(funcIndex->name, nargs, argTypes, if (!func_get_detail(funcIndex->name, nargs, argTypes,
&funcid, &rettype, &retset, &true_typeids)) &funcid, &rettype, &retset, &true_typeids))
func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL); func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
if (retset) if (retset)
@ -425,7 +426,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
if (argTypes[i] != true_typeids[i] && if (argTypes[i] != true_typeids[i] &&
! IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i])) !IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i]))
func_error("DefineIndex", funcIndex->name, nargs, argTypes, func_error("DefineIndex", funcIndex->name, nargs, argTypes,
"Index function must be binary-compatible with table datatype"); "Index function must be binary-compatible with table datatype");
} }
@ -439,7 +440,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
indexInfo->ii_FuncOid = funcid; indexInfo->ii_FuncOid = funcid;
/* Need to do the fmgr function lookup now, too */ /* Need to do the fmgr function lookup now, too */
fmgr_info(funcid, & indexInfo->ii_FuncInfo); fmgr_info(funcid, &indexInfo->ii_FuncInfo);
} }
static void static void
@ -477,7 +478,7 @@ NormIndexAttrs(IndexInfo *indexInfo,
indexInfo->ii_KeyAttrNumbers[attn] = attform->attnum; indexInfo->ii_KeyAttrNumbers[attn] = attform->attnum;
classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid, classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid,
accessMethodName, accessMethodId); accessMethodName, accessMethodId);
ReleaseSysCache(atttuple); ReleaseSysCache(atttuple);
attn++; attn++;
@ -515,8 +516,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
attribute->class); attribute->class);
/* /*
* Assume the opclass is supported by this index access method * Assume the opclass is supported by this index access method if we
* if we can find at least one relevant entry in pg_amop. * can find at least one relevant entry in pg_amop.
*/ */
ScanKeyEntryInitialize(&entry[0], 0, ScanKeyEntryInitialize(&entry[0], 0,
Anum_pg_amop_amopid, Anum_pg_amop_amopid,
@ -530,7 +531,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock); relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
scan = heap_beginscan(relation, false, SnapshotNow, 2, entry); scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
if (! HeapTupleIsValid(tuple = heap_getnext(scan, 0))) if (!HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"", elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"",
attribute->class, accessMethodName); attribute->class, accessMethodName);
@ -540,17 +541,18 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
heap_close(relation, AccessShareLock); heap_close(relation, AccessShareLock);
/* /*
* Make sure the operators associated with this opclass actually accept * Make sure the operators associated with this opclass actually
* the column data type. This prevents possible coredumps caused by * accept the column data type. This prevents possible coredumps
* user errors like applying text_ops to an int4 column. We will accept * caused by user errors like applying text_ops to an int4 column. We
* an opclass as OK if the operator's input datatype is binary-compatible * will accept an opclass as OK if the operator's input datatype is
* with the actual column datatype. Note we assume that all the operators * binary-compatible with the actual column datatype. Note we assume
* associated with an opclass accept the same datatypes, so checking the * that all the operators associated with an opclass accept the same
* first one we happened to find in the table is sufficient. * datatypes, so checking the first one we happened to find in the
* table is sufficient.
* *
* If the opclass was the default for the datatype, assume we can skip * If the opclass was the default for the datatype, assume we can skip
* this check --- that saves a few cycles in the most common case. * this check --- that saves a few cycles in the most common case. If
* If pg_opclass is wrong then we're probably screwed anyway... * pg_opclass is wrong then we're probably screwed anyway...
*/ */
if (doTypeCheck) if (doTypeCheck)
{ {
@ -560,11 +562,11 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
if (HeapTupleIsValid(tuple)) if (HeapTupleIsValid(tuple))
{ {
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tuple); Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tuple);
Oid opInputType = (optup->oprkind == 'l') ? Oid opInputType = (optup->oprkind == 'l') ?
optup->oprright : optup->oprleft; optup->oprright : optup->oprleft;
if (attrType != opInputType && if (attrType != opInputType &&
! IS_BINARY_COMPATIBLE(attrType, opInputType)) !IS_BINARY_COMPATIBLE(attrType, opInputType))
elog(ERROR, "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"", elog(ERROR, "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"",
attribute->class, typeidTypeName(attrType)); attribute->class, typeidTypeName(attrType));
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
@ -660,7 +662,7 @@ ReindexIndex(const char *name, bool force /* currently unused */ )
if (IsIgnoringSystemIndexes()) if (IsIgnoringSystemIndexes())
overwrite = true; overwrite = true;
if (!reindex_index(tuple->t_data->t_oid, force, overwrite)) if (!reindex_index(tuple->t_data->t_oid, force, overwrite))
#endif /* OLD_FILE_NAMING */ #endif /* OLD_FILE_NAMING */
elog(NOTICE, "index \"%s\" wasn't reindexed", name); elog(NOTICE, "index \"%s\" wasn't reindexed", name);
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
@ -752,18 +754,18 @@ ReindexDatabase(const char *dbname, bool force, bool all)
elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database."); elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
/* /*
* We cannot run inside a user transaction block; if we were * We cannot run inside a user transaction block; if we were inside a
* inside a transaction, then our commit- and * transaction, then our commit- and start-transaction-command calls
* start-transaction-command calls would not have the intended effect! * would not have the intended effect!
*/ */
if (IsTransactionBlock()) if (IsTransactionBlock())
elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block"); elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block");
/* /*
* Create a memory context that will survive forced transaction commits * Create a memory context that will survive forced transaction
* we do below. Since it is a child of QueryContext, it will go away * commits we do below. Since it is a child of QueryContext, it will
* eventually even if we suffer an error; there's no need for special * go away eventually even if we suffer an error; there's no need for
* abort cleanup logic. * special abort cleanup logic.
*/ */
private_context = AllocSetContextCreate(QueryContext, private_context = AllocSetContextCreate(QueryContext,
"ReindexDatabase", "ReindexDatabase",

View File

@ -111,7 +111,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
i = 0; i = 0;
values[i++] = PointerGetDatum(languageName); values[i++] = PointerGetDatum(languageName);
values[i++] = BoolGetDatum(true); /* lanispl */ values[i++] = BoolGetDatum(true); /* lanispl */
values[i++] = BoolGetDatum(stmt->pltrusted); values[i++] = BoolGetDatum(stmt->pltrusted);
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid); values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = DirectFunctionCall1(textin, values[i++] = DirectFunctionCall1(textin,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.59 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.60 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -40,8 +40,8 @@
*/ */
void void
RemoveOperator(char *operatorName, /* operator name */ RemoveOperator(char *operatorName, /* operator name */
char *typeName1, /* left argument type name */ char *typeName1, /* left argument type name */
char *typeName2) /* right argument type name */ char *typeName2) /* right argument type name */
{ {
Relation relation; Relation relation;
HeapTuple tup; HeapTuple tup;

View File

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

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.51 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.52 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -33,7 +33,7 @@
* so we pre-log a few fetches in advance. In the event of * so we pre-log a few fetches in advance. In the event of
* crash we can lose as much as we pre-logged. * crash we can lose as much as we pre-logged.
*/ */
#define SEQ_LOG_VALS 32 #define SEQ_LOG_VALS 32
typedef struct sequence_magic typedef struct sequence_magic
{ {
@ -140,7 +140,7 @@ DefineSequence(CreateSeqStmt *seq)
case SEQ_COL_LOG: case SEQ_COL_LOG:
typnam->name = "int4"; typnam->name = "int4";
coldef->colname = "log_cnt"; coldef->colname = "log_cnt";
value[i - 1] = Int32GetDatum((int32)1); value[i - 1] = Int32GetDatum((int32) 1);
break; break;
case SEQ_COL_CYCLE: case SEQ_COL_CYCLE:
typnam->name = "char"; typnam->name = "char";
@ -247,7 +247,7 @@ nextval(PG_FUNCTION_ARGS)
logit = true; logit = true;
} }
while (fetch) /* try to fetch cache [+ log ] numbers */ while (fetch) /* try to fetch cache [+ log ] numbers */
{ {
/* /*
@ -292,8 +292,8 @@ nextval(PG_FUNCTION_ARGS)
log--; log--;
rescnt++; rescnt++;
last = next; last = next;
if (rescnt == 1) /* if it's first result - */ if (rescnt == 1) /* if it's first result - */
result = next; /* it's what to return */ result = next; /* it's what to return */
} }
} }
@ -306,12 +306,12 @@ nextval(PG_FUNCTION_ARGS)
{ {
xl_seq_rec xlrec; xl_seq_rec xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
xlrec.node = elm->rel->rd_node; xlrec.node = elm->rel->rd_node;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = sizeof(xl_seq_rec); rdata[0].len = sizeof(xl_seq_rec);
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -319,17 +319,17 @@ nextval(PG_FUNCTION_ARGS)
seq->is_called = 't'; seq->is_called = 't';
seq->log_cnt = 0; seq->log_cnt = 0;
rdata[1].buffer = InvalidBuffer; rdata[1].buffer = InvalidBuffer;
rdata[1].data = (char*)page + ((PageHeader) page)->pd_upper; rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;
rdata[1].len = ((PageHeader)page)->pd_special - rdata[1].len = ((PageHeader) page)->pd_special -
((PageHeader)page)->pd_upper; ((PageHeader) page)->pd_upper;
rdata[1].next = NULL; rdata[1].next = NULL;
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG|XLOG_NO_TRAN, rdata); recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
if (fetch) /* not all numbers were fetched */ if (fetch) /* not all numbers were fetched */
log -= fetch; log -= fetch;
} }
@ -374,15 +374,15 @@ currval(PG_FUNCTION_ARGS)
PG_RETURN_INT32(result); PG_RETURN_INT32(result);
} }
/* /*
* Main internal procedure that handles 2 & 3 arg forms of SETVAL. * Main internal procedure that handles 2 & 3 arg forms of SETVAL.
* *
* Note that the 3 arg version (which sets the is_called flag) is * Note that the 3 arg version (which sets the is_called flag) is
* only for use in pg_dump, and setting the is_called flag may not * only for use in pg_dump, and setting the is_called flag may not
* work if multiple users are attached to the database and referencing * work if multiple users are attached to the database and referencing
* the sequence (unlikely if pg_dump is restoring it). * the sequence (unlikely if pg_dump is restoring it).
* *
* It is necessary to have the 3 arg version so that pg_dump can * It is necessary to have the 3 arg version so that pg_dump can
* restore the state of a sequence exactly during data-only restores - * restore the state of a sequence exactly during data-only restores -
* it is the only way to clear the is_called flag in an existing * it is the only way to clear the is_called flag in an existing
* sequence. * sequence.
@ -409,18 +409,19 @@ do_setval(char *seqname, int32 next, bool iscalled)
/* save info in local cache */ /* save info in local cache */
elm->last = next; /* last returned number */ elm->last = next; /* last returned number */
elm->cached = next; /* last cached number (forget cached values) */ elm->cached = next; /* last cached number (forget cached
* values) */
START_CRIT_SECTION(); START_CRIT_SECTION();
{ {
xl_seq_rec xlrec; xl_seq_rec xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
xlrec.node = elm->rel->rd_node; xlrec.node = elm->rel->rd_node;
rdata[0].buffer = InvalidBuffer; rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char*)&xlrec; rdata[0].data = (char *) &xlrec;
rdata[0].len = sizeof(xl_seq_rec); rdata[0].len = sizeof(xl_seq_rec);
rdata[0].next = &(rdata[1]); rdata[0].next = &(rdata[1]);
@ -428,12 +429,12 @@ do_setval(char *seqname, int32 next, bool iscalled)
seq->is_called = 't'; seq->is_called = 't';
seq->log_cnt = 0; seq->log_cnt = 0;
rdata[1].buffer = InvalidBuffer; rdata[1].buffer = InvalidBuffer;
rdata[1].data = (char*)page + ((PageHeader) page)->pd_upper; rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;
rdata[1].len = ((PageHeader)page)->pd_special - rdata[1].len = ((PageHeader) page)->pd_special -
((PageHeader)page)->pd_upper; ((PageHeader) page)->pd_upper;
rdata[1].next = NULL; rdata[1].next = NULL;
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG|XLOG_NO_TRAN, rdata); recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
@ -496,7 +497,7 @@ static char *
get_seq_name(text *seqin) get_seq_name(text *seqin)
{ {
char *rawname = DatumGetCString(DirectFunctionCall1(textout, char *rawname = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(seqin))); PointerGetDatum(seqin)));
int rawlen = strlen(rawname); int rawlen = strlen(rawname);
char *seqname; char *seqname;
@ -511,6 +512,7 @@ get_seq_name(text *seqin)
else else
{ {
seqname = rawname; seqname = rawname;
/* /*
* It's important that this match the identifier downcasing code * It's important that this match the identifier downcasing code
* used by backend/parser/scan.l. * used by backend/parser/scan.l.
@ -752,15 +754,16 @@ get_param(DefElem *def)
return -1; return -1;
} }
void seq_redo(XLogRecPtr lsn, XLogRecord *record) void
seq_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
Relation reln; Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
char *item; char *item;
Size itemsz; Size itemsz;
xl_seq_rec *xlrec = (xl_seq_rec*) XLogRecGetData(record); xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
sequence_magic *sm; sequence_magic *sm;
if (info != XLOG_SEQ_LOG) if (info != XLOG_SEQ_LOG)
@ -772,8 +775,8 @@ void seq_redo(XLogRecPtr lsn, XLogRecord *record)
buffer = XLogReadBuffer(true, reln, 0); buffer = XLogReadBuffer(true, reln, 0);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(STOP, "seq_redo: can't read block of %u/%u", elog(STOP, "seq_redo: can't read block of %u/%u",
xlrec->node.tblNode, xlrec->node.relNode); xlrec->node.tblNode, xlrec->node.relNode);
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
@ -781,10 +784,10 @@ void seq_redo(XLogRecPtr lsn, XLogRecord *record)
sm = (sequence_magic *) PageGetSpecialPointer(page); sm = (sequence_magic *) PageGetSpecialPointer(page);
sm->magic = SEQ_MAGIC; sm->magic = SEQ_MAGIC;
item = (char*)xlrec + sizeof(xl_seq_rec); item = (char *) xlrec + sizeof(xl_seq_rec);
itemsz = record->xl_len - sizeof(xl_seq_rec); itemsz = record->xl_len - sizeof(xl_seq_rec);
itemsz = MAXALIGN(itemsz); itemsz = MAXALIGN(itemsz);
if (PageAddItem(page, (Item)item, itemsz, if (PageAddItem(page, (Item) item, itemsz,
FirstOffsetNumber, LP_USED) == InvalidOffsetNumber) FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
elog(STOP, "seq_redo: failed to add item to page"); elog(STOP, "seq_redo: failed to add item to page");
@ -795,14 +798,16 @@ void seq_redo(XLogRecPtr lsn, XLogRecord *record)
return; return;
} }
void seq_undo(XLogRecPtr lsn, XLogRecord *record) void
seq_undo(XLogRecPtr lsn, XLogRecord *record)
{ {
} }
void seq_desc(char *buf, uint8 xl_info, char* rec) void
seq_desc(char *buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
xl_seq_rec *xlrec = (xl_seq_rec*) rec; xl_seq_rec *xlrec = (xl_seq_rec *) rec;
if (info == XLOG_SEQ_LOG) if (info == XLOG_SEQ_LOG)
strcat(buf, "log: "); strcat(buf, "log: ");
@ -813,5 +818,5 @@ void seq_desc(char *buf, uint8 xl_info, char* rec)
} }
sprintf(buf + strlen(buf), "node %u/%u", sprintf(buf + strlen(buf), "node %u/%u",
xlrec->node.tblNode, xlrec->node.relNode); xlrec->node.tblNode, xlrec->node.relNode);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.88 2001/03/14 21:50:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.89 2001/03/22 03:59:23 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -36,8 +36,8 @@ static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid, static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
TupleTableSlot **newSlot); TupleTableSlot **newSlot);
static HeapTuple ExecCallTriggerFunc(Trigger *trigger, static HeapTuple ExecCallTriggerFunc(Trigger *trigger,
TriggerData *trigdata, TriggerData *trigdata,
MemoryContext per_tuple_context); MemoryContext per_tuple_context);
static void DeferredTriggerSaveEvent(Relation rel, int event, static void DeferredTriggerSaveEvent(Relation rel, int event,
HeapTuple oldtup, HeapTuple newtup); HeapTuple oldtup, HeapTuple newtup);
@ -87,7 +87,9 @@ CreateTrigger(CreateTrigStmt *stmt)
constrrelid = InvalidOid; constrrelid = InvalidOid;
else else
{ {
/* NoLock is probably sufficient here, since we're only
/*
* NoLock is probably sufficient here, since we're only
* interested in getting the relation's OID... * interested in getting the relation's OID...
*/ */
rel = heap_openr(stmt->constrrelname, NoLock); rel = heap_openr(stmt->constrrelname, NoLock);
@ -192,7 +194,7 @@ CreateTrigger(CreateTrigStmt *stmt)
values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
CStringGetDatum(stmt->trigname)); CStringGetDatum(stmt->trigname));
values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype); values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
values[Anum_pg_trigger_tgenabled - 1] = BoolGetDatum(true); values[Anum_pg_trigger_tgenabled - 1] = BoolGetDatum(true);
@ -211,7 +213,7 @@ CreateTrigger(CreateTrigStmt *stmt)
foreach(le, stmt->args) foreach(le, stmt->args)
{ {
char *ar = ((Value*) lfirst(le))->val.str; char *ar = ((Value *) lfirst(le))->val.str;
len += strlen(ar) + 4; len += strlen(ar) + 4;
for (; *ar; ar++) for (; *ar; ar++)
@ -224,7 +226,7 @@ CreateTrigger(CreateTrigStmt *stmt)
args[0] = '\0'; args[0] = '\0';
foreach(le, stmt->args) foreach(le, stmt->args)
{ {
char *s = ((Value*) lfirst(le))->val.str; char *s = ((Value *) lfirst(le))->val.str;
char *d = args + strlen(args); char *d = args + strlen(args);
while (*s) while (*s)
@ -237,7 +239,7 @@ CreateTrigger(CreateTrigStmt *stmt)
} }
values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs); values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
CStringGetDatum(args)); CStringGetDatum(args));
} }
else else
{ {
@ -569,15 +571,16 @@ RelationBuildTriggers(Relation relation)
sizeof(Trigger)); sizeof(Trigger));
else else
triggers = (Trigger *) repalloc(triggers, triggers = (Trigger *) repalloc(triggers,
(found + 1) * sizeof(Trigger)); (found + 1) * sizeof(Trigger));
build = &(triggers[found]); build = &(triggers[found]);
build->tgoid = htup->t_data->t_oid; build->tgoid = htup->t_data->t_oid;
build->tgname = MemoryContextStrdup(CacheMemoryContext, build->tgname = MemoryContextStrdup(CacheMemoryContext,
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(&pg_trigger->tgname)))); NameGetDatum(&pg_trigger->tgname))));
build->tgfoid = pg_trigger->tgfoid; build->tgfoid = pg_trigger->tgfoid;
build->tgfunc.fn_oid = InvalidOid; /* mark FmgrInfo as uninitialized */ build->tgfunc.fn_oid = InvalidOid; /* mark FmgrInfo as
* uninitialized */
build->tgtype = pg_trigger->tgtype; build->tgtype = pg_trigger->tgtype;
build->tgenabled = pg_trigger->tgenabled; build->tgenabled = pg_trigger->tgenabled;
build->tgisconstraint = pg_trigger->tgisconstraint; build->tgisconstraint = pg_trigger->tgisconstraint;
@ -836,22 +839,22 @@ ExecCallTriggerFunc(Trigger *trigger,
TriggerData *trigdata, TriggerData *trigdata,
MemoryContext per_tuple_context) MemoryContext per_tuple_context)
{ {
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
Datum result; Datum result;
MemoryContext oldContext; MemoryContext oldContext;
/* /*
* Fmgr lookup info is cached in the Trigger structure, * Fmgr lookup info is cached in the Trigger structure, so that we
* so that we need not repeat the lookup on every call. * need not repeat the lookup on every call.
*/ */
if (trigger->tgfunc.fn_oid == InvalidOid) if (trigger->tgfunc.fn_oid == InvalidOid)
fmgr_info(trigger->tgfoid, &trigger->tgfunc); fmgr_info(trigger->tgfoid, &trigger->tgfunc);
/* /*
* Do the function evaluation in the per-tuple memory context, * Do the function evaluation in the per-tuple memory context, so that
* so that leaked memory will be reclaimed once per tuple. * leaked memory will be reclaimed once per tuple. Note in particular
* Note in particular that any new tuple created by the trigger function * that any new tuple created by the trigger function will live till
* will live till the end of the tuple cycle. * the end of the tuple cycle.
*/ */
oldContext = MemoryContextSwitchTo(per_tuple_context); oldContext = MemoryContextSwitchTo(per_tuple_context);
@ -868,8 +871,8 @@ ExecCallTriggerFunc(Trigger *trigger,
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
/* /*
* Trigger protocol allows function to return a null pointer, * Trigger protocol allows function to return a null pointer, but NOT
* but NOT to set the isnull result flag. * to set the isnull result flag.
*/ */
if (fcinfo.isnull) if (fcinfo.isnull)
elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL", elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL",
@ -885,7 +888,7 @@ ExecBRInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT]; Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
HeapTuple newtuple = trigtuple; HeapTuple newtuple = trigtuple;
HeapTuple oldtuple; HeapTuple oldtuple;
TriggerData LocTriggerData; TriggerData LocTriggerData;
int i; int i;
LocTriggerData.type = T_TriggerData; LocTriggerData.type = T_TriggerData;
@ -915,9 +918,7 @@ ExecARInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
if (rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 || if (rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 ||
rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 || rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 ||
rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0) rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
{
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple); DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple);
}
} }
bool bool
@ -1240,10 +1241,11 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate)
static void static void
deferredTriggerAddEvent(DeferredTriggerEvent event) deferredTriggerAddEvent(DeferredTriggerEvent event)
{ {
/* /*
* Since the event list could grow quite long, we keep track of the * Since the event list could grow quite long, we keep track of the
* list tail and append there, rather than just doing a stupid "lappend". * list tail and append there, rather than just doing a stupid
* This avoids O(N^2) behavior for large numbers of events. * "lappend". This avoids O(N^2) behavior for large numbers of events.
*/ */
event->dte_next = NULL; event->dte_next = NULL;
if (deftrig_event_tail == NULL) if (deftrig_event_tail == NULL)
@ -1291,7 +1293,7 @@ deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
if (previous == NULL) if (previous == NULL)
elog(ERROR, elog(ERROR,
"deferredTriggerGetPreviousEvent: event for tuple %s not found", "deferredTriggerGetPreviousEvent: event for tuple %s not found",
DatumGetCString(DirectFunctionCall1(tidout, DatumGetCString(DirectFunctionCall1(tidout,
PointerGetDatum(ctid)))); PointerGetDatum(ctid))));
return previous; return previous;
@ -1528,7 +1530,7 @@ DeferredTriggerBeginXact(void)
if (deftrig_cxt != NULL) if (deftrig_cxt != NULL)
elog(ERROR, elog(ERROR,
"DeferredTriggerBeginXact() called while inside transaction"); "DeferredTriggerBeginXact() called while inside transaction");
/* ---------- /* ----------
* Create the per transaction memory context and copy all states * Create the per transaction memory context and copy all states
@ -1671,7 +1673,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
l = deftrig_dfl_trigstates; l = deftrig_dfl_trigstates;
while (l != NIL) while (l != NIL)
{ {
List *next = lnext(l); List *next = lnext(l);
pfree(lfirst(l)); pfree(lfirst(l));
pfree(l); pfree(l);
@ -1700,7 +1702,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
l = deftrig_trigstates; l = deftrig_trigstates;
while (l != NIL) while (l != NIL)
{ {
List *next = lnext(l); List *next = lnext(l);
pfree(lfirst(l)); pfree(lfirst(l));
pfree(l); pfree(l);
@ -1912,7 +1914,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
* Called by ExecAR...Triggers() to add the event to the queue. * Called by ExecAR...Triggers() to add the event to the queue.
* *
* NOTE: should be called only if we've determined that an event must * NOTE: should be called only if we've determined that an event must
* be added to the queue. We must save *all* events if there is either * be added to the queue. We must save *all* events if there is either
* an UPDATE or a DELETE deferred trigger; see uses of * an UPDATE or a DELETE deferred trigger; see uses of
* deferredTriggerGetPreviousEvent. * deferredTriggerGetPreviousEvent.
* ---------- * ----------
@ -2099,15 +2101,15 @@ DeferredTriggerSaveEvent(Relation rel, int event,
TRIGGER_DEFERRED_ROW_INSERTED) TRIGGER_DEFERRED_ROW_INSERTED)
elog(ERROR, "triggered data change violation " elog(ERROR, "triggered data change violation "
"on relation \"%s\"", "on relation \"%s\"",
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(&(rel->rd_rel->relname))))); NameGetDatum(&(rel->rd_rel->relname)))));
if (prev_event->dte_item[i].dti_state & if (prev_event->dte_item[i].dti_state &
TRIGGER_DEFERRED_KEY_CHANGED) TRIGGER_DEFERRED_KEY_CHANGED)
elog(ERROR, "triggered data change violation " elog(ERROR, "triggered data change violation "
"on relation \"%s\"", "on relation \"%s\"",
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(&(rel->rd_rel->relname))))); NameGetDatum(&(rel->rd_rel->relname)))));
} }
/* ---------- /* ----------
@ -2142,7 +2144,7 @@ DeferredTriggerSaveEvent(Relation rel, int event,
elog(ERROR, "triggered data change violation " elog(ERROR, "triggered data change violation "
"on relation \"%s\"", "on relation \"%s\"",
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(&(rel->rd_rel->relname))))); NameGetDatum(&(rel->rd_rel->relname)))));
break; break;
} }

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.73 2001/01/24 19:42:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.74 2001/03/22 03:59:24 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -122,7 +122,7 @@ write_password_file(Relation rel)
CRYPT_PWD_FILE_SEPSTR CRYPT_PWD_FILE_SEPSTR
"%s\n", "%s\n",
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(DatumGetName(datum_n)))), NameGetDatum(DatumGetName(datum_n)))),
null_p ? "" : null_p ? "" :
DatumGetCString(DirectFunctionCall1(textout, datum_p)), DatumGetCString(DirectFunctionCall1(textout, datum_p)),
null_v ? "\\N" : null_v ? "\\N" :
@ -248,7 +248,7 @@ CreateUser(CreateUserStmt *stmt)
* Build a tuple to insert * Build a tuple to insert
*/ */
new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein, new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein,
CStringGetDatum(stmt->user)); CStringGetDatum(stmt->user));
new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1); new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1);
AssertState(BoolIsValid(stmt->createdb)); AssertState(BoolIsValid(stmt->createdb));
@ -312,7 +312,7 @@ CreateUser(CreateUserStmt *stmt)
* this in */ * this in */
ags.action = +1; ags.action = +1;
ags.listUsers = makeList1(makeInteger(havesysid ? ags.listUsers = makeList1(makeInteger(havesysid ?
stmt->sysid : max_id + 1)); stmt->sysid : max_id + 1));
AlterGroup(&ags, "CREATE USER"); AlterGroup(&ags, "CREATE USER");
} }
@ -377,7 +377,7 @@ AlterUser(AlterUserStmt *stmt)
* Build a tuple to update, perusing the information just obtained * Build a tuple to update, perusing the information just obtained
*/ */
new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein, new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein,
CStringGetDatum(stmt->user)); CStringGetDatum(stmt->user));
new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; new_record_nulls[Anum_pg_shadow_usename - 1] = ' ';
/* sysid - leave as is */ /* sysid - leave as is */
@ -561,7 +561,7 @@ DropUser(DropUserStmt *stmt)
elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s", elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
user, user,
DatumGetCString(DirectFunctionCall1(nameout, DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(DatumGetName(datum)))), NameGetDatum(DatumGetName(datum)))),
(length(stmt->users) > 1) ? " (no users removed)" : "" (length(stmt->users) > 1) ? " (no users removed)" : ""
); );
} }
@ -603,6 +603,7 @@ DropUser(DropUserStmt *stmt)
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(pg_rel, AccessExclusiveLock); heap_close(pg_rel, AccessExclusiveLock);
/* /*
* Advance command counter so that later iterations of this loop * Advance command counter so that later iterations of this loop
* will see the changes already made. This is essential if, for * will see the changes already made. This is essential if, for
@ -873,7 +874,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
{ {
/* Get the uid of the proposed user to add. */ /* Get the uid of the proposed user to add. */
tuple = SearchSysCache(SHADOWNAME, tuple = SearchSysCache(SHADOWNAME,
PointerGetDatum(strVal(lfirst(item))), PointerGetDatum(strVal(lfirst(item))),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "%s: user \"%s\" does not exist", elog(ERROR, "%s: user \"%s\" does not exist",
@ -995,7 +996,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
{ {
/* Get the uid of the proposed user to drop. */ /* Get the uid of the proposed user to drop. */
tuple = SearchSysCache(SHADOWNAME, tuple = SearchSysCache(SHADOWNAME,
PointerGetDatum(strVal(lfirst(item))), PointerGetDatum(strVal(lfirst(item))),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item))); elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item)));

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.187 2001/03/14 08:40:57 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.188 2001/03/22 03:59:24 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -47,11 +47,11 @@
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/temprel.h" #include "utils/temprel.h"
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer, extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
char *unused, int unlen); char *unused, int unlen);
extern XLogRecPtr log_heap_move(Relation reln, extern XLogRecPtr log_heap_move(Relation reln,
Buffer oldbuf, ItemPointerData from, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup); Buffer newbuf, HeapTuple newtup);
static MemoryContext vac_context = NULL; static MemoryContext vac_context = NULL;
@ -78,9 +78,9 @@ static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
static void get_indices(Relation relation, int *nindices, Relation **Irel); static void get_indices(Relation relation, int *nindices, Relation **Irel);
static void close_indices(int nindices, Relation *Irel); static void close_indices(int nindices, Relation *Irel);
static IndexInfo **get_index_desc(Relation onerel, int nindices, static IndexInfo **get_index_desc(Relation onerel, int nindices,
Relation *Irel); Relation *Irel);
static void *vac_find_eq(void *bot, int nelem, int size, void *elm, static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
int (*compar) (const void *, const void *)); int (*compar) (const void *, const void *));
static int vac_cmp_blk(const void *left, const void *right); static int vac_cmp_blk(const void *left, const void *right);
static int vac_cmp_offno(const void *left, const void *right); static int vac_cmp_offno(const void *left, const void *right);
static int vac_cmp_vtlinks(const void *left, const void *right); static int vac_cmp_vtlinks(const void *left, const void *right);
@ -120,9 +120,9 @@ vacuum(char *vacrel, bool verbose, bool analyze, List *anal_cols)
/* /*
* Create special memory context for cross-transaction storage. * Create special memory context for cross-transaction storage.
* *
* Since it is a child of QueryContext, it will go away eventually * Since it is a child of QueryContext, it will go away eventually even
* even if we suffer an error; there's no need for special abort * if we suffer an error; there's no need for special abort cleanup
* cleanup logic. * logic.
*/ */
vac_context = AllocSetContextCreate(QueryContext, vac_context = AllocSetContextCreate(QueryContext,
"Vacuum", "Vacuum",
@ -215,8 +215,8 @@ vacuum_shutdown()
/* /*
* Clean up working storage --- note we must do this after * Clean up working storage --- note we must do this after
* StartTransactionCommand, else we might be trying to delete * StartTransactionCommand, else we might be trying to delete the
* the active context! * active context!
*/ */
MemoryContextDelete(vac_context); MemoryContextDelete(vac_context);
vac_context = NULL; vac_context = NULL;
@ -360,10 +360,10 @@ vacuum_rel(Oid relid)
{ {
Relation onerel; Relation onerel;
LockRelId onerelid; LockRelId onerelid;
VacPageListData vacuum_pages; /* List of pages to vacuum and/or clean VacPageListData vacuum_pages; /* List of pages to vacuum and/or
* indices */ * clean indices */
VacPageListData fraged_pages; /* List of pages with space enough for VacPageListData fraged_pages; /* List of pages with space enough
* re-using */ * for re-using */
Relation *Irel; Relation *Irel;
int32 nindices, int32 nindices,
i; i;
@ -411,10 +411,10 @@ vacuum_rel(Oid relid)
} }
/* /*
* Get a session-level exclusive lock too. This will protect our * Get a session-level exclusive lock too. This will protect our
* exclusive access to the relation across multiple transactions, * exclusive access to the relation across multiple transactions, so
* so that we can vacuum the relation's TOAST table (if any) secure * that we can vacuum the relation's TOAST table (if any) secure in
* in the knowledge that no one is diddling the parent relation. * the knowledge that no one is diddling the parent relation.
* *
* NOTE: this cannot block, even if someone else is waiting for access, * NOTE: this cannot block, even if someone else is waiting for access,
* because the lock manager knows that both lock requests are from the * because the lock manager knows that both lock requests are from the
@ -458,10 +458,11 @@ vacuum_rel(Oid relid)
vacrelstats->hasindex = true; vacrelstats->hasindex = true;
else else
vacrelstats->hasindex = false; vacrelstats->hasindex = false;
#ifdef NOT_USED #ifdef NOT_USED
/* /*
* reindex in VACUUM is dangerous under WAL. * reindex in VACUUM is dangerous under WAL. ifdef out until it
* ifdef out until it becomes safe. * becomes safe.
*/ */
if (reindex) if (reindex)
{ {
@ -470,7 +471,7 @@ vacuum_rel(Oid relid)
Irel = (Relation *) NULL; Irel = (Relation *) NULL;
activate_indexes_of_a_table(relid, false); activate_indexes_of_a_table(relid, false);
} }
#endif /* NOT_USED */ #endif /* NOT_USED */
/* Clean/scan index relation(s) */ /* Clean/scan index relation(s) */
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
@ -506,6 +507,7 @@ vacuum_rel(Oid relid)
} }
else else
{ {
/* /*
* Flush dirty pages out to disk. We must do this even if we * Flush dirty pages out to disk. We must do this even if we
* didn't do anything else, because we want to ensure that all * didn't do anything else, because we want to ensure that all
@ -518,10 +520,10 @@ vacuum_rel(Oid relid)
i); i);
} }
} }
#ifdef NOT_USED #ifdef NOT_USED
if (reindex) if (reindex)
activate_indexes_of_a_table(relid, true); activate_indexes_of_a_table(relid, true);
#endif /* NOT_USED */ #endif /* NOT_USED */
/* all done with this class, but hold lock until commit */ /* all done with this class, but hold lock until commit */
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
@ -537,11 +539,11 @@ vacuum_rel(Oid relid)
CommitTransactionCommand(); CommitTransactionCommand();
/* /*
* If the relation has a secondary toast one, vacuum that too * If the relation has a secondary toast one, vacuum that too while we
* while we still hold the session lock on the master table. * still hold the session lock on the master table. We don't need to
* We don't need to propagate "analyze" to it, because the toaster * propagate "analyze" to it, because the toaster always uses
* always uses hardcoded index access and statistics are * hardcoded index access and statistics are totally unimportant for
* totally unimportant for toast relations * toast relations
*/ */
if (toast_relid != InvalidOid) if (toast_relid != InvalidOid)
vacuum_rel(toast_relid); vacuum_rel(toast_relid);
@ -563,7 +565,7 @@ vacuum_rel(Oid relid)
*/ */
static void static void
scan_heap(VRelStats *vacrelstats, Relation onerel, scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages) VacPageList vacuum_pages, VacPageList fraged_pages)
{ {
BlockNumber nblocks, BlockNumber nblocks,
blkno; blkno;
@ -845,7 +847,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
* dead tuples removed. Below we will apply * dead tuples removed. Below we will apply
* PageRepairFragmentation to the copy, so that we can * PageRepairFragmentation to the copy, so that we can
* determine how much space will be available after * determine how much space will be available after
* removal of dead tuples. But note we are NOT changing * removal of dead tuples. But note we are NOT changing
* the real page yet... * the real page yet...
*/ */
if (tempPage == (Page) NULL) if (tempPage == (Page) NULL)
@ -964,8 +966,8 @@ Re-using: Free/Avail. Space %lu/%lu; EndEmpty/Avail. Pages %u/%u. %s",
nblocks, changed_pages, vacuum_pages->num_pages, empty_pages, nblocks, changed_pages, vacuum_pages->num_pages, empty_pages,
new_pages, num_tuples, tups_vacuumed, new_pages, num_tuples, tups_vacuumed,
nkeep, vacrelstats->num_vtlinks, ncrash, nkeep, vacrelstats->num_vtlinks, ncrash,
nunused, (unsigned long)min_tlen, (unsigned long)max_tlen, nunused, (unsigned long) min_tlen, (unsigned long) max_tlen,
(unsigned long)free_size, (unsigned long)usable_free_size, (unsigned long) free_size, (unsigned long) usable_free_size,
empty_end_pages, fraged_pages->num_pages, empty_end_pages, fraged_pages->num_pages,
show_rusage(&ru0)); show_rusage(&ru0));
@ -984,8 +986,8 @@ Re-using: Free/Avail. Space %lu/%lu; EndEmpty/Avail. Pages %u/%u. %s",
*/ */
static void static void
repair_frag(VRelStats *vacrelstats, Relation onerel, repair_frag(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages, VacPageList vacuum_pages, VacPageList fraged_pages,
int nindices, Relation *Irel) int nindices, Relation *Irel)
{ {
TransactionId myXID; TransactionId myXID;
CommandId myCID; CommandId myCID;
@ -1077,7 +1079,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
dowrite = false; dowrite = false;
if (blkno == last_vacuum_block) /* it's reaped page */ if (blkno == last_vacuum_block) /* it's reaped page */
{ {
if (last_vacuum_page->offsets_free > 0) /* there are dead tuples */ if (last_vacuum_page->offsets_free > 0) /* there are dead tuples */
{ /* on this page - clean */ { /* on this page - clean */
Assert(!isempty); Assert(!isempty);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
@ -1100,7 +1102,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
last_vacuum_block = -1; last_vacuum_block = -1;
} }
if (num_fraged_pages > 0 && if (num_fraged_pages > 0 &&
fraged_pages->pagedesc[num_fraged_pages - 1]->blkno == fraged_pages->pagedesc[num_fraged_pages - 1]->blkno ==
(BlockNumber) blkno) (BlockNumber) blkno)
{ {
/* page is in fraged_pages too; remove it */ /* page is in fraged_pages too; remove it */
@ -1142,8 +1144,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* If this (chain) tuple is moved by me already then I * If this (chain) tuple is moved by me already then I
* have to check is it in vacpage or not - i.e. is it moved * have to check is it in vacpage or not - i.e. is it
* while cleaning this page or some previous one. * moved while cleaning this page or some previous one.
*/ */
if (tuple.t_data->t_infomask & HEAP_MOVED_OFF) if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
{ {
@ -1232,8 +1234,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* xaction and this tuple is already deleted by * xaction and this tuple is already deleted by
* me. Actually, upper part of chain should be * me. Actually, upper part of chain should be
* removed and seems that this should be handled * removed and seems that this should be handled
* in scan_heap(), but it's not implemented at * in scan_heap(), but it's not implemented at the
* the moment and so we just stop shrinking here. * moment and so we just stop shrinking here.
*/ */
ReleaseBuffer(Cbuf); ReleaseBuffer(Cbuf);
pfree(vtmove); pfree(vtmove);
@ -1256,15 +1258,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
{ {
/* /*
* if to_vacpage no longer has enough free space to be * if to_vacpage no longer has enough free space
* useful, remove it from fraged_pages list * to be useful, remove it from fraged_pages list
*/ */
if (to_vacpage != NULL && if (to_vacpage != NULL &&
!enough_space(to_vacpage, vacrelstats->min_tlen)) !enough_space(to_vacpage, vacrelstats->min_tlen))
{ {
Assert(num_fraged_pages > to_item); Assert(num_fraged_pages > to_item);
memmove(fraged_pages->pagedesc + to_item, memmove(fraged_pages->pagedesc + to_item,
fraged_pages->pagedesc + to_item + 1, fraged_pages->pagedesc + to_item + 1,
sizeof(VacPage) * (num_fraged_pages - to_item - 1)); sizeof(VacPage) * (num_fraged_pages - to_item - 1));
num_fraged_pages--; num_fraged_pages--;
} }
@ -1326,10 +1328,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
vtld.new_tid = tp.t_self; vtld.new_tid = tp.t_self;
vtlp = (VTupleLink) vtlp = (VTupleLink)
vac_find_eq((void *) (vacrelstats->vtlinks), vac_find_eq((void *) (vacrelstats->vtlinks),
vacrelstats->num_vtlinks, vacrelstats->num_vtlinks,
sizeof(VTupleLinkData), sizeof(VTupleLinkData),
(void *) &vtld, (void *) &vtld,
vac_cmp_vtlinks); vac_cmp_vtlinks);
if (vtlp == NULL) if (vtlp == NULL)
elog(ERROR, "Parent tuple was not found"); elog(ERROR, "Parent tuple was not found");
tp.t_self = vtlp->this_tid; tp.t_self = vtlp->this_tid;
@ -1416,7 +1418,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ItemPointerSetInvalid(&Ctid); ItemPointerSetInvalid(&Ctid);
for (ti = 0; ti < num_vtmove; ti++) for (ti = 0; ti < num_vtmove; ti++)
{ {
VacPage destvacpage = vtmove[ti].vacpage; VacPage destvacpage = vtmove[ti].vacpage;
/* Get page to move from */ /* Get page to move from */
tuple.t_self = vtmove[ti].tid; tuple.t_self = vtmove[ti].tid;
@ -1460,21 +1462,22 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* *
* NOTE: a nasty bug used to lurk here. It is possible * NOTE: a nasty bug used to lurk here. It is possible
* for the source and destination pages to be the same * for the source and destination pages to be the same
* (since this tuple-chain member can be on a page lower * (since this tuple-chain member can be on a page
* than the one we're currently processing in the outer * lower than the one we're currently processing in
* loop). If that's true, then after vacuum_page() the * the outer loop). If that's true, then after
* source tuple will have been moved, and tuple.t_data * vacuum_page() the source tuple will have been
* will be pointing at garbage. Therefore we must do * moved, and tuple.t_data will be pointing at
* everything that uses tuple.t_data BEFORE this step!! * garbage. Therefore we must do everything that uses
* tuple.t_data BEFORE this step!!
* *
* This path is different from the other callers of * This path is different from the other callers of
* vacuum_page, because we have already incremented the * vacuum_page, because we have already incremented
* vacpage's offsets_used field to account for the * the vacpage's offsets_used field to account for the
* tuple(s) we expect to move onto the page. Therefore * tuple(s) we expect to move onto the page. Therefore
* vacuum_page's check for offsets_used == 0 is * vacuum_page's check for offsets_used == 0 is wrong.
* wrong. But since that's a good debugging check for * But since that's a good debugging check for all
* all other callers, we work around it here rather * other callers, we work around it here rather than
* than remove it. * remove it.
*/ */
if (!PageIsEmpty(ToPage) && vtmove[ti].cleanVpd) if (!PageIsEmpty(ToPage) && vtmove[ti].cleanVpd)
{ {
@ -1498,7 +1501,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (newoff == InvalidOffsetNumber) if (newoff == InvalidOffsetNumber)
{ {
elog(STOP, "moving chain: failed to add item with len = %lu to page %u", elog(STOP, "moving chain: failed to add item with len = %lu to page %u",
(unsigned long)tuple_len, destvacpage->blkno); (unsigned long) tuple_len, destvacpage->blkno);
} }
newitemid = PageGetItemId(ToPage, newoff); newitemid = PageGetItemId(ToPage, newoff);
pfree(newtup.t_data); pfree(newtup.t_data);
@ -1507,9 +1510,9 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ItemPointerSet(&(newtup.t_self), destvacpage->blkno, newoff); ItemPointerSet(&(newtup.t_self), destvacpage->blkno, newoff);
{ {
XLogRecPtr recptr = XLogRecPtr recptr =
log_heap_move(onerel, Cbuf, tuple.t_self, log_heap_move(onerel, Cbuf, tuple.t_self,
cur_buffer, &newtup); cur_buffer, &newtup);
if (Cbuf != cur_buffer) if (Cbuf != cur_buffer)
{ {
@ -1526,7 +1529,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* Set new tuple's t_ctid pointing to itself for last * Set new tuple's t_ctid pointing to itself for last
* tuple in chain, and to next tuple in chain otherwise. * tuple in chain, and to next tuple in chain
* otherwise.
*/ */
if (!ItemPointerIsValid(&Ctid)) if (!ItemPointerIsValid(&Ctid))
newtup.t_data->t_ctid = newtup.t_self; newtup.t_data->t_ctid = newtup.t_self;
@ -1552,13 +1556,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
{ {
/* /*
* XXX using CurrentMemoryContext here means * XXX using CurrentMemoryContext here means
* intra-vacuum memory leak for functional indexes. * intra-vacuum memory leak for functional
* Should fix someday. * indexes. Should fix someday.
* *
* XXX This code fails to handle partial indexes! * XXX This code fails to handle partial indexes!
* Probably should change it to use ExecOpenIndices. * Probably should change it to use
* ExecOpenIndices.
*/ */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
{ {
@ -1653,8 +1659,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
{ {
elog(STOP, "\ elog(STOP, "\
failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)", failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)",
(unsigned long)tuple_len, cur_page->blkno, (unsigned long)cur_page->free, (unsigned long) tuple_len, cur_page->blkno, (unsigned long) cur_page->free,
cur_page->offsets_used, cur_page->offsets_free); cur_page->offsets_used, cur_page->offsets_free);
} }
newitemid = PageGetItemId(ToPage, newoff); newitemid = PageGetItemId(ToPage, newoff);
pfree(newtup.t_data); pfree(newtup.t_data);
@ -1673,9 +1679,9 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
tuple.t_data->t_infomask |= HEAP_MOVED_OFF; tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
{ {
XLogRecPtr recptr = XLogRecPtr recptr =
log_heap_move(onerel, buf, tuple.t_self, log_heap_move(onerel, buf, tuple.t_self,
cur_buffer, &newtup); cur_buffer, &newtup);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
@ -1698,13 +1704,13 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
/* insert index' tuples if needed */ /* insert index' tuples if needed */
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
{ {
/* /*
* XXX using CurrentMemoryContext here means * XXX using CurrentMemoryContext here means intra-vacuum
* intra-vacuum memory leak for functional indexes. * memory leak for functional indexes. Should fix someday.
* Should fix someday.
* *
* XXX This code fails to handle partial indexes! * XXX This code fails to handle partial indexes! Probably
* Probably should change it to use ExecOpenIndices. * should change it to use ExecOpenIndices.
*/ */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
{ {
@ -1803,14 +1809,15 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
if (num_moved > 0) if (num_moved > 0)
{ {
/* /*
* We have to commit our tuple movings before we truncate the * We have to commit our tuple movings before we truncate the
* relation. Ideally we should do Commit/StartTransactionCommand * relation. Ideally we should do Commit/StartTransactionCommand
* here, relying on the session-level table lock to protect our * here, relying on the session-level table lock to protect our
* exclusive access to the relation. However, that would require * exclusive access to the relation. However, that would require
* a lot of extra code to close and re-open the relation, indices, * a lot of extra code to close and re-open the relation, indices,
* etc. For now, a quick hack: record status of current transaction * etc. For now, a quick hack: record status of current
* as committed, and continue. * transaction as committed, and continue.
*/ */
RecordTransactionCommit(); RecordTransactionCommit();
} }
@ -1873,7 +1880,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
nblocks, blkno, num_moved, nblocks, blkno, num_moved,
show_rusage(&ru0)); show_rusage(&ru0));
/* /*
* Reflect the motion of system tuples to catalog cache here. * Reflect the motion of system tuples to catalog cache here.
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
@ -1883,13 +1890,13 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
/* vacuum indices again if needed */ /* vacuum indices again if needed */
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
{ {
VacPage *vpleft, VacPage *vpleft,
*vpright, *vpright,
vpsave; vpsave;
/* re-sort Nvacpagelist.pagedesc */ /* re-sort Nvacpagelist.pagedesc */
for (vpleft = Nvacpagelist.pagedesc, for (vpleft = Nvacpagelist.pagedesc,
vpright = Nvacpagelist.pagedesc + Nvacpagelist.num_pages - 1; vpright = Nvacpagelist.pagedesc + Nvacpagelist.num_pages - 1;
vpleft < vpright; vpleft++, vpright--) vpleft < vpright; vpleft++, vpright--)
{ {
vpsave = *vpleft; vpsave = *vpleft;
@ -1906,9 +1913,9 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
if (vacpage->blkno == (BlockNumber) (blkno - 1) && if (vacpage->blkno == (BlockNumber) (blkno - 1) &&
vacpage->offsets_free > 0) vacpage->offsets_free > 0)
{ {
char unbuf[BLCKSZ]; char unbuf[BLCKSZ];
OffsetNumber *unused = (OffsetNumber*)unbuf; OffsetNumber *unused = (OffsetNumber *) unbuf;
int uncnt; int uncnt;
buf = ReadBuffer(onerel, vacpage->blkno); buf = ReadBuffer(onerel, vacpage->blkno);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
@ -1943,8 +1950,9 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
uncnt = PageRepairFragmentation(page, unused); uncnt = PageRepairFragmentation(page, unused);
{ {
XLogRecPtr recptr; XLogRecPtr recptr;
recptr = log_heap_clean(onerel, buf, (char*)unused,
(char*)(&(unused[uncnt])) - (char*)unused); recptr = log_heap_clean(onerel, buf, (char *) unused,
(char *) (&(unused[uncnt])) - (char *) unused);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
} }
@ -1962,9 +1970,9 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
/* /*
* Flush dirty pages out to disk. We do this unconditionally, even if * Flush dirty pages out to disk. We do this unconditionally, even if
* we don't need to truncate, because we want to ensure that all tuples * we don't need to truncate, because we want to ensure that all
* have correct on-row commit status on disk (see bufmgr.c's comments * tuples have correct on-row commit status on disk (see bufmgr.c's
* for FlushRelationBuffers()). * comments for FlushRelationBuffers()).
*/ */
i = FlushRelationBuffers(onerel, blkno); i = FlushRelationBuffers(onerel, blkno);
if (i < 0) if (i < 0)
@ -2005,8 +2013,7 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
int i; int i;
nblocks = vacuum_pages->num_pages; nblocks = vacuum_pages->num_pages;
nblocks -= vacuum_pages->empty_end_pages; /* nothing to do with nblocks -= vacuum_pages->empty_end_pages; /* nothing to do with them */
* them */
for (i = 0, vacpage = vacuum_pages->pagedesc; i < nblocks; i++, vacpage++) for (i = 0, vacpage = vacuum_pages->pagedesc; i < nblocks; i++, vacpage++)
{ {
@ -2022,9 +2029,9 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
/* /*
* Flush dirty pages out to disk. We do this unconditionally, even if * Flush dirty pages out to disk. We do this unconditionally, even if
* we don't need to truncate, because we want to ensure that all tuples * we don't need to truncate, because we want to ensure that all
* have correct on-row commit status on disk (see bufmgr.c's comments * tuples have correct on-row commit status on disk (see bufmgr.c's
* for FlushRelationBuffers()). * comments for FlushRelationBuffers()).
*/ */
Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages); Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages);
nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages; nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages;
@ -2042,7 +2049,8 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
vacrelstats->num_pages, nblocks); vacrelstats->num_pages, nblocks);
nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks); nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks);
Assert(nblocks >= 0); Assert(nblocks >= 0);
vacrelstats->num_pages = nblocks; /* set new number of blocks */ vacrelstats->num_pages = nblocks; /* set new number of
* blocks */
} }
} }
@ -2053,12 +2061,12 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
static void static void
vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage) vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
{ {
char unbuf[BLCKSZ]; char unbuf[BLCKSZ];
OffsetNumber *unused = (OffsetNumber*)unbuf; OffsetNumber *unused = (OffsetNumber *) unbuf;
int uncnt; int uncnt;
Page page = BufferGetPage(buffer); Page page = BufferGetPage(buffer);
ItemId itemid; ItemId itemid;
int i; int i;
/* There shouldn't be any tuples moved onto the page yet! */ /* There shouldn't be any tuples moved onto the page yet! */
Assert(vacpage->offsets_used == 0); Assert(vacpage->offsets_used == 0);
@ -2072,8 +2080,9 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
uncnt = PageRepairFragmentation(page, unused); uncnt = PageRepairFragmentation(page, unused);
{ {
XLogRecPtr recptr; XLogRecPtr recptr;
recptr = log_heap_clean(onerel, buffer, (char*)unused,
(char*)(&(unused[uncnt])) - (char*)unused); recptr = log_heap_clean(onerel, buffer, (char *) unused,
(char *) (&(unused[uncnt])) - (char *) unused);
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
} }
@ -2220,8 +2229,8 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
vp = &vacpage; vp = &vacpage;
vpp = (VacPage *) vac_find_eq((void *) (vacpagelist->pagedesc), vpp = (VacPage *) vac_find_eq((void *) (vacpagelist->pagedesc),
vacpagelist->num_pages, sizeof(VacPage), (void *) &vp, vacpagelist->num_pages, sizeof(VacPage), (void *) &vp,
vac_cmp_blk); vac_cmp_blk);
if (vpp == (VacPage *) NULL) if (vpp == (VacPage *) NULL)
return (VacPage) NULL; return (VacPage) NULL;
@ -2235,8 +2244,8 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
} }
voff = (OffsetNumber *) vac_find_eq((void *) (vp->offsets), voff = (OffsetNumber *) vac_find_eq((void *) (vp->offsets),
vp->offsets_free, sizeof(OffsetNumber), (void *) &ioffno, vp->offsets_free, sizeof(OffsetNumber), (void *) &ioffno,
vac_cmp_offno); vac_cmp_offno);
if (voff == (OffsetNumber *) NULL) if (voff == (OffsetNumber *) NULL)
return (VacPage) NULL; return (VacPage) NULL;
@ -2265,7 +2274,7 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
*/ */
static void static void
update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex, update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex,
VRelStats *vacrelstats) VRelStats *vacrelstats)
{ {
Relation rd; Relation rd;
HeapTupleData rtup; HeapTupleData rtup;
@ -2313,7 +2322,7 @@ update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex,
static void static void
reap_page(VacPageList vacpagelist, VacPage vacpage) reap_page(VacPageList vacpagelist, VacPage vacpage)
{ {
VacPage newvacpage; VacPage newvacpage;
/* allocate a VacPageData entry */ /* allocate a VacPageData entry */
newvacpage = (VacPage) palloc(sizeof(VacPageData) + vacpage->offsets_free * sizeof(OffsetNumber)); newvacpage = (VacPage) palloc(sizeof(VacPageData) + vacpage->offsets_free * sizeof(OffsetNumber));
@ -2354,7 +2363,7 @@ vpage_insert(VacPageList vacpagelist, VacPage vpnew)
static void * static void *
vac_find_eq(void *bot, int nelem, int size, void *elm, vac_find_eq(void *bot, int nelem, int size, void *elm,
int (*compar) (const void *, const void *)) int (*compar) (const void *, const void *))
{ {
int res; int res;
int last = nelem - 1; int last = nelem - 1;

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.45 2001/01/24 19:42:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.46 2001/03/22 03:59:25 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -453,6 +453,7 @@ parse_DefaultXactIsoLevel(char *value)
{ {
#if 0 #if 0
TransactionState s = CurrentTransactionState; TransactionState s = CurrentTransactionState;
#endif #endif
if (value == NULL) if (value == NULL)
@ -632,7 +633,7 @@ parse_client_encoding(char *value)
} }
#else #else
if (value && if (value &&
strcasecmp(value, pg_encoding_to_char(pg_get_client_encoding())) != 0) strcasecmp(value, pg_encoding_to_char(pg_get_client_encoding())) != 0)
elog(ERROR, "Client encoding %s is not supported", value); elog(ERROR, "Client encoding %s is not supported", value);
#endif #endif
return TRUE; return TRUE;
@ -701,28 +702,27 @@ reset_server_encoding(void)
void void
SetPGVariable(const char *name, const char *value) SetPGVariable(const char *name, const char *value)
{ {
char *mvalue = value ? pstrdup(value) : ((char*) NULL); char *mvalue = value ? pstrdup(value) : ((char *) NULL);
/* /*
* Special cases ought to be removed and handled separately * Special cases ought to be removed and handled separately by TCOP
* by TCOP */
*/ if (strcasecmp(name, "datestyle") == 0)
if (strcasecmp(name, "datestyle")==0) parse_date(mvalue);
parse_date(mvalue); else if (strcasecmp(name, "timezone") == 0)
else if (strcasecmp(name, "timezone")==0) parse_timezone(mvalue);
parse_timezone(mvalue); else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
else if (strcasecmp(name, "DefaultXactIsoLevel")==0) parse_DefaultXactIsoLevel(mvalue);
parse_DefaultXactIsoLevel(mvalue); else if (strcasecmp(name, "XactIsoLevel") == 0)
else if (strcasecmp(name, "XactIsoLevel")==0) parse_XactIsoLevel(mvalue);
parse_XactIsoLevel(mvalue); else if (strcasecmp(name, "client_encoding") == 0)
else if (strcasecmp(name, "client_encoding")==0) parse_client_encoding(mvalue);
parse_client_encoding(mvalue); else if (strcasecmp(name, "server_encoding") == 0)
else if (strcasecmp(name, "server_encoding")==0) parse_server_encoding(mvalue);
parse_server_encoding(mvalue); else if (strcasecmp(name, "random_seed") == 0)
else if (strcasecmp(name, "random_seed")==0) parse_random_seed(mvalue);
parse_random_seed(mvalue); else
else SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET);
SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET);
if (mvalue) if (mvalue)
pfree(mvalue); pfree(mvalue);
@ -732,44 +732,45 @@ SetPGVariable(const char *name, const char *value)
void void
GetPGVariable(const char *name) GetPGVariable(const char *name)
{ {
if (strcasecmp(name, "datestyle")==0) if (strcasecmp(name, "datestyle") == 0)
show_date(); show_date();
else if (strcasecmp(name, "timezone")==0) else if (strcasecmp(name, "timezone") == 0)
show_timezone(); show_timezone();
else if (strcasecmp(name, "DefaultXactIsoLevel")==0) else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
show_DefaultXactIsoLevel(); show_DefaultXactIsoLevel();
else if (strcasecmp(name, "XactIsoLevel")==0) else if (strcasecmp(name, "XactIsoLevel") == 0)
show_XactIsoLevel(); show_XactIsoLevel();
else if (strcasecmp(name, "client_encoding")==0) else if (strcasecmp(name, "client_encoding") == 0)
show_client_encoding(); show_client_encoding();
else if (strcasecmp(name, "server_encoding")==0) else if (strcasecmp(name, "server_encoding") == 0)
show_server_encoding(); show_server_encoding();
else if (strcasecmp(name, "random_seed")==0) else if (strcasecmp(name, "random_seed") == 0)
show_random_seed(); show_random_seed();
else else
{ {
const char * val = GetConfigOption(name); const char *val = GetConfigOption(name);
elog(NOTICE, "%s is %s", name, val);
} elog(NOTICE, "%s is %s", name, val);
} }
}
void void
ResetPGVariable(const char *name) ResetPGVariable(const char *name)
{ {
if (strcasecmp(name, "datestyle")==0) if (strcasecmp(name, "datestyle") == 0)
reset_date(); reset_date();
else if (strcasecmp(name, "timezone")==0) else if (strcasecmp(name, "timezone") == 0)
reset_timezone(); reset_timezone();
else if (strcasecmp(name, "DefaultXactIsoLevel")==0) else if (strcasecmp(name, "DefaultXactIsoLevel") == 0)
reset_DefaultXactIsoLevel(); reset_DefaultXactIsoLevel();
else if (strcasecmp(name, "XactIsoLevel")==0) else if (strcasecmp(name, "XactIsoLevel") == 0)
reset_XactIsoLevel(); reset_XactIsoLevel();
else if (strcasecmp(name, "client_encoding")==0) else if (strcasecmp(name, "client_encoding") == 0)
reset_client_encoding(); reset_client_encoding();
else if (strcasecmp(name, "server_encoding")==0) else if (strcasecmp(name, "server_encoding") == 0)
reset_server_encoding(); reset_server_encoding();
else if (strcasecmp(name, "random_seed")==0) else if (strcasecmp(name, "random_seed") == 0)
reset_random_seed(); reset_random_seed();
else else
SetConfigOption(name, NULL, superuser() ? PGC_SUSET : PGC_USERSET); SetConfigOption(name, NULL, superuser() ? PGC_SUSET : PGC_USERSET);
} }

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