mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
pgindent run. Make it all clean.
This commit is contained in:
parent
6cf8707b82
commit
9e1552607a
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
1646
contrib/cube/cube.c
1646
contrib/cube/cube.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
|
@ -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]);
|
||||||
|
@ -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!!!! */
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() */
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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_ */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
1367
contrib/seg/seg.c
1367
contrib/seg/seg.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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++);
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
@ -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]);
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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}
|
||||||
};
|
};
|
||||||
|
@ -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())
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 --
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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:
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)));
|
||||||
|
@ -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;
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user