mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
pgindent run over code.
This commit is contained in:
@ -43,8 +43,8 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
|
||||
int ndim,
|
||||
*dim;
|
||||
char *p;
|
||||
FmgrInfo finf; /*Tobias Gabele Jan 18 1999*/
|
||||
|
||||
FmgrInfo finf; /* Tobias Gabele Jan 18 1999 */
|
||||
|
||||
|
||||
/* Sanity checks */
|
||||
if ((array == (ArrayType *) NULL)
|
||||
@ -75,9 +75,9 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
|
||||
|
||||
/* Lookup the function entry point */
|
||||
proc_fn = (func_ptr) NULL;
|
||||
fmgr_info(proc,&finf); /*Tobias Gabele Jan 18 1999*/
|
||||
proc_fn=finf.fn_addr; /*Tobias Gabele Jan 18 1999*/
|
||||
pronargs=finf.fn_nargs; /*Tobias Gabele Jan 18 1999*/
|
||||
fmgr_info(proc, &finf); /* Tobias Gabele Jan 18 1999 */
|
||||
proc_fn = finf.fn_addr; /* Tobias Gabele Jan 18 1999 */
|
||||
pronargs = finf.fn_nargs; /* Tobias Gabele Jan 18 1999 */
|
||||
if ((proc_fn == NULL) || (pronargs != 2))
|
||||
{
|
||||
elog(ERROR, "array_iterator: fmgr_info lookup failed for oid %d", proc);
|
||||
@ -110,38 +110,26 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
|
||||
{
|
||||
result = (int) (*proc_fn) (p, value);
|
||||
if (typlen > 0)
|
||||
{
|
||||
p += typlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
p += INTALIGN(*(int32 *) p);
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (!and)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (and)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (and && result)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -344,7 +332,7 @@ int32
|
||||
array_oideq(ArrayType *array, Oid value)
|
||||
{
|
||||
return array_iterator((Oid) 26, /* oid */
|
||||
(Oid) 184, /* oideq */
|
||||
(Oid) 184, /* oideq */
|
||||
0, /* logical or */
|
||||
array, (Datum) value);
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
#ifndef ARRAY_ITERATOR_H
|
||||
#define ARRAY_ITERATOR_H
|
||||
|
||||
static int32
|
||||
array_iterator(Oid elemtype, Oid proc, int and,
|
||||
static int32 array_iterator(Oid elemtype, Oid proc, int and,
|
||||
ArrayType *array, Datum value);
|
||||
int32 array_texteq(ArrayType *array, char *value);
|
||||
int32 array_all_texteq(ArrayType *array, char *value);
|
||||
@ -24,6 +23,7 @@ int32 array_int4lt(ArrayType *array, int4 value);
|
||||
int32 array_all_int4lt(ArrayType *array, int4 value);
|
||||
int32 array_int4le(ArrayType *array, int4 value);
|
||||
int32 array_all_int4le(ArrayType *array, int4 value);
|
||||
int32 array_oideq(ArrayType *array, Oid value);
|
||||
int32 array_all_oidne(ArrayType *array, Oid value);
|
||||
int32 array_oideq(ArrayType *array, Oid value);
|
||||
int32 array_all_oidne(ArrayType *array, Oid value);
|
||||
|
||||
#endif
|
||||
|
@ -225,8 +225,8 @@ currentdate()
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -4,23 +4,24 @@
|
||||
|
||||
#include <postgres.h>
|
||||
#include <utils/geo_decls.h> /* for Pt */
|
||||
#include <utils/palloc.h> /* for palloc */
|
||||
#include <utils/palloc.h> /* for palloc */
|
||||
|
||||
/* Earth's radius is in statute miles. */
|
||||
const EARTH_RADIUS = 3958.747716;
|
||||
const TWO_PI = 2.0 * M_PI;
|
||||
const EARTH_RADIUS = 3958.747716;
|
||||
const TWO_PI = 2.0 * M_PI;
|
||||
|
||||
/******************************************************
|
||||
*
|
||||
* degtorad - convert degrees to radians
|
||||
*
|
||||
* arg: double, angle in degrees
|
||||
* arg: double, angle in degrees
|
||||
*
|
||||
* returns: double, same angle in radians
|
||||
* returns: double, same angle in radians
|
||||
******************************************************/
|
||||
|
||||
static double
|
||||
degtorad (double degrees) {
|
||||
degtorad(double degrees)
|
||||
{
|
||||
return (degrees / 360.0) * TWO_PI;
|
||||
}
|
||||
|
||||
@ -30,36 +31,40 @@ degtorad (double degrees) {
|
||||
* geo_distance - distance between points
|
||||
*
|
||||
* args:
|
||||
* a pair of points - for each point,
|
||||
* x-coordinate is longitude in degrees west of Greenwich
|
||||
* y-coordinate is latitude in degrees above equator
|
||||
* a pair of points - for each point,
|
||||
* x-coordinate is longitude in degrees west of Greenwich
|
||||
* y-coordinate is latitude in degrees above equator
|
||||
*
|
||||
* returns: double
|
||||
* distance between the points in miles on earth's surface
|
||||
* returns: double
|
||||
* distance between the points in miles on earth's surface
|
||||
******************************************************/
|
||||
|
||||
double *
|
||||
geo_distance (Point *pt1, Point *pt2) {
|
||||
geo_distance(Point *pt1, Point *pt2)
|
||||
{
|
||||
|
||||
double long1, lat1, long2, lat2;
|
||||
double longdiff;
|
||||
double * resultp = palloc (sizeof(double));
|
||||
double long1,
|
||||
lat1,
|
||||
long2,
|
||||
lat2;
|
||||
double longdiff;
|
||||
double *resultp = palloc(sizeof(double));
|
||||
|
||||
/* convert degrees to radians */
|
||||
|
||||
long1 = degtorad (pt1->x);
|
||||
lat1 = degtorad (pt1->y);
|
||||
long1 = degtorad(pt1->x);
|
||||
lat1 = degtorad(pt1->y);
|
||||
|
||||
long2 = degtorad (pt2->x);
|
||||
lat2 = degtorad (pt2->y);
|
||||
long2 = degtorad(pt2->x);
|
||||
lat2 = degtorad(pt2->y);
|
||||
|
||||
/* compute difference in longitudes - want < 180 degrees */
|
||||
longdiff = fabs (long1 - long2);
|
||||
longdiff = fabs(long1 - long2);
|
||||
if (longdiff > M_PI)
|
||||
longdiff = TWO_PI - longdiff;
|
||||
|
||||
* resultp = EARTH_RADIUS * acos
|
||||
(sin (lat1) * sin (lat2) + cos (lat1) * cos (lat2) * cos (longdiff));
|
||||
*resultp = EARTH_RADIUS * acos
|
||||
(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(longdiff));
|
||||
|
||||
return resultp;
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include <libpq-fe.h>
|
||||
#include "pginterface.h"
|
||||
|
||||
PGresult *attres, *relres;
|
||||
PGresult *attres,
|
||||
*relres;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
@ -55,7 +56,7 @@ main(int argc, char **argv)
|
||||
");
|
||||
doquery("FETCH ALL IN c_relations");
|
||||
relres = get_result();
|
||||
|
||||
|
||||
set_result(attres);
|
||||
while (fetch(typname, relname, attname) != END_OF_TUPLES)
|
||||
{
|
||||
@ -65,17 +66,17 @@ main(int argc, char **argv)
|
||||
{
|
||||
unset_result(relres);
|
||||
if (strcmp(typname, "oid") == 0)
|
||||
sprintf(query,"\
|
||||
sprintf(query, "\
|
||||
DECLARE c_matches BINARY CURSOR FOR \
|
||||
SELECT count(*)
|
||||
FROM %s t1, %s t2 \
|
||||
WHERE t1.%s = t2.oid", relname, relname2, attname);
|
||||
SELECT count(*) \
|
||||
FROM % s t1, %s t2 \
|
||||
WHERE t1.% s = t2.oid ", relname, relname2, attname);
|
||||
else
|
||||
sprintf(query,"\
|
||||
sprintf(query, "\
|
||||
DECLARE c_matches BINARY CURSOR FOR \
|
||||
SELECT count(*)
|
||||
FROM %s t1, %s t2 \
|
||||
WHERE RegprocToOid(t1.%s) = t2.oid", relname, relname2, attname);
|
||||
SELECT count(*) \
|
||||
FROM % s t1, %s t2 \
|
||||
WHERE RegprocToOid(t1.% s) = t2.oid ", relname, relname2, attname);
|
||||
|
||||
doquery(query);
|
||||
doquery("FETCH ALL IN c_matches");
|
||||
@ -96,7 +97,7 @@ main(int argc, char **argv)
|
||||
doquery("CLOSE c_attributes");
|
||||
PQclear(attres);
|
||||
unset_result(attres);
|
||||
|
||||
|
||||
doquery("COMMIT WORK");
|
||||
|
||||
disconnectdb();
|
||||
|
@ -1,18 +1,18 @@
|
||||
#include "postgres.h"
|
||||
#include "executor/spi.h"
|
||||
#include "commands/trigger.h"
|
||||
#include <ctype.h> /* tolower */
|
||||
#include <stdio.h> /* debugging */
|
||||
#include <ctype.h> /* tolower */
|
||||
#include <stdio.h> /* debugging */
|
||||
|
||||
/*
|
||||
* Trigger function takes 2 arguments:
|
||||
1. relation in which to store the substrings
|
||||
2. field to extract substrings from
|
||||
1. relation in which to store the substrings
|
||||
2. field to extract substrings from
|
||||
|
||||
The relation in which to insert *must* have the following layout:
|
||||
|
||||
string varchar(#)
|
||||
id oid
|
||||
string varchar(#)
|
||||
id oid
|
||||
|
||||
Example:
|
||||
|
||||
@ -24,9 +24,9 @@ create index title_fti_idx on title_fti (string);
|
||||
|
||||
create trigger title_fti_trigger after update or insert or delete on product
|
||||
for each row execute procedure fti(title_fti, title);
|
||||
^^^^^^^^^
|
||||
^^^^^^^^^
|
||||
where to store index in
|
||||
^^^^^
|
||||
^^^^^
|
||||
which column to index
|
||||
|
||||
ofcourse don't forget to create an index on title_idx, column string, else
|
||||
@ -39,8 +39,8 @@ select p.* from product p, title_fti f1, title_fti f2 where
|
||||
*/
|
||||
|
||||
/*
|
||||
march 4 1998 Changed breakup() to return less substrings. Only breakup
|
||||
in word parts which are in turn shortened from the start
|
||||
march 4 1998 Changed breakup() to return less substrings. Only breakup
|
||||
in word parts which are in turn shortened from the start
|
||||
of the word (ie. word, ord, rd)
|
||||
Did allocation of substring buffer outside of breakup()
|
||||
oct. 5 1997, fixed a bug in string breakup (where there are more nonalpha
|
||||
@ -62,14 +62,14 @@ select p.* from product p, title_fti f1, title_fti f2 where
|
||||
*/
|
||||
|
||||
HeapTuple fti(void);
|
||||
char *breakup(char*, char*);
|
||||
bool is_stopword(char*);
|
||||
char *breakup(char *, char *);
|
||||
bool is_stopword(char *);
|
||||
|
||||
bool new_tuple = false;
|
||||
bool new_tuple = false;
|
||||
|
||||
|
||||
/* THIS LIST MUST BE IN SORTED ORDER, A BINARY SEARCH IS USED!!!! */
|
||||
char *StopWords[] = { /* list of words to skip in indexing */
|
||||
char *StopWords[] = { /* list of words to skip in indexing */
|
||||
#ifdef SAMPLE_STOP_WORDS
|
||||
"no"
|
||||
"the",
|
||||
@ -88,7 +88,7 @@ typedef struct
|
||||
static EPlan *InsertPlans = NULL;
|
||||
static EPlan *DeletePlans = NULL;
|
||||
static int nInsertPlans = 0;
|
||||
static int nDeletePlans = 0;
|
||||
static int nDeletePlans = 0;
|
||||
|
||||
static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
|
||||
|
||||
@ -96,28 +96,28 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
|
||||
HeapTuple
|
||||
fti()
|
||||
{
|
||||
Trigger *trigger; /* to get trigger name */
|
||||
int nargs; /* # of arguments */
|
||||
char **args; /* arguments */
|
||||
char *relname; /* triggered relation name */
|
||||
Relation rel; /* triggered relation */
|
||||
char *indexname; /* name of table for substrings */
|
||||
Trigger *trigger; /* to get trigger name */
|
||||
int nargs; /* # of arguments */
|
||||
char **args; /* arguments */
|
||||
char *relname; /* triggered relation name */
|
||||
Relation rel; /* triggered relation */
|
||||
char *indexname; /* name of table for substrings */
|
||||
HeapTuple rettuple = NULL;
|
||||
TupleDesc tupdesc; /* tuple description */
|
||||
bool isinsert=false;
|
||||
bool isdelete=false;
|
||||
TupleDesc tupdesc; /* tuple description */
|
||||
bool isinsert = false;
|
||||
bool isdelete = false;
|
||||
int ret;
|
||||
char query[8192];
|
||||
Oid oid;
|
||||
/*
|
||||
FILE *debug;
|
||||
*/
|
||||
|
||||
/*
|
||||
debug = fopen("/dev/xconsole", "w");
|
||||
fprintf(debug, "FTI: entered function\n");
|
||||
fflush(debug);
|
||||
*/
|
||||
* FILE *debug;
|
||||
*/
|
||||
|
||||
/*
|
||||
* debug = fopen("/dev/xconsole", "w"); fprintf(debug, "FTI: entered
|
||||
* function\n"); fflush(debug);
|
||||
*/
|
||||
|
||||
if (!CurrentTriggerData)
|
||||
elog(ERROR, "Full Text Indexing: triggers are not initialized");
|
||||
@ -127,47 +127,53 @@ fti()
|
||||
elog(ERROR, "Full Text Indexing: must be fired AFTER event");
|
||||
|
||||
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
|
||||
isinsert=true;
|
||||
isinsert = true;
|
||||
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
|
||||
{ isdelete=true;isinsert=true;}
|
||||
{
|
||||
isdelete = true;
|
||||
isinsert = true;
|
||||
}
|
||||
if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
|
||||
isdelete=true;
|
||||
isdelete = true;
|
||||
|
||||
trigger = CurrentTriggerData->tg_trigger;
|
||||
rel = CurrentTriggerData->tg_relation;
|
||||
relname = SPI_getrelname(rel);
|
||||
rettuple=CurrentTriggerData->tg_trigtuple;
|
||||
if (isdelete&&isinsert) /* is an UPDATE */
|
||||
rettuple=CurrentTriggerData->tg_newtuple;
|
||||
rettuple = CurrentTriggerData->tg_trigtuple;
|
||||
if (isdelete && isinsert) /* is an UPDATE */
|
||||
rettuple = CurrentTriggerData->tg_newtuple;
|
||||
|
||||
CurrentTriggerData = NULL; /* invalidate 'normal' calls to this function */
|
||||
CurrentTriggerData = NULL; /* invalidate 'normal' calls to this
|
||||
* function */
|
||||
|
||||
if ((ret = SPI_connect()) < 0)
|
||||
elog(ERROR, "Full Text Indexing: SPI_connect failed, returned %d\n", ret);
|
||||
|
||||
if ((ret = SPI_connect()) <0)
|
||||
elog(ERROR,"Full Text Indexing: SPI_connect failed, returned %d\n",ret);
|
||||
|
||||
nargs = trigger->tgnargs;
|
||||
if (nargs != 2)
|
||||
elog(ERROR, "Full Text Indexing: trigger can only have 2 arguments");
|
||||
|
||||
|
||||
args = trigger->tgargs;
|
||||
indexname = args[0];
|
||||
tupdesc = rel->rd_att; /* what the tuple looks like (?) */
|
||||
tupdesc = rel->rd_att; /* what the tuple looks like (?) */
|
||||
|
||||
/* get oid of current tuple, needed by all, so place here */
|
||||
oid = rettuple->t_data->t_oid;
|
||||
if (!OidIsValid(oid))
|
||||
elog(ERROR,"Full Text Indexing: oid of current tuple is NULL");
|
||||
elog(ERROR, "Full Text Indexing: oid of current tuple is NULL");
|
||||
|
||||
if (isdelete) {
|
||||
void *pplan;
|
||||
Oid *argtypes;
|
||||
Datum values[1];
|
||||
EPlan *plan;
|
||||
if (isdelete)
|
||||
{
|
||||
void *pplan;
|
||||
Oid *argtypes;
|
||||
Datum values[1];
|
||||
EPlan *plan;
|
||||
|
||||
sprintf(query, "D%s$%s", args[0], args[1]);
|
||||
plan = find_plan(query, &DeletePlans, &nDeletePlans);
|
||||
if (plan->nplans <= 0) {
|
||||
argtypes = (Oid *)palloc(sizeof(Oid));
|
||||
if (plan->nplans <= 0)
|
||||
{
|
||||
argtypes = (Oid *) palloc(sizeof(Oid));
|
||||
|
||||
argtypes[0] = OIDOID;
|
||||
|
||||
@ -181,7 +187,7 @@ fti()
|
||||
elog(ERROR, "Full Text Indexing: SPI_saveplan returned NULL "
|
||||
"in delete");
|
||||
|
||||
plan->splan = (void **)malloc(sizeof(void*));
|
||||
plan->splan = (void **) malloc(sizeof(void *));
|
||||
*(plan->splan) = pplan;
|
||||
plan->nplans = 1;
|
||||
}
|
||||
@ -192,26 +198,29 @@ fti()
|
||||
if (ret != SPI_OK_DELETE)
|
||||
elog(ERROR, "Full Text Indexing: error executing plan in delete");
|
||||
}
|
||||
|
||||
if (isinsert) {
|
||||
char *substring, *column;
|
||||
void *pplan;
|
||||
Oid *argtypes;
|
||||
Datum values[2];
|
||||
int colnum;
|
||||
|
||||
if (isinsert)
|
||||
{
|
||||
char *substring,
|
||||
*column;
|
||||
void *pplan;
|
||||
Oid *argtypes;
|
||||
Datum values[2];
|
||||
int colnum;
|
||||
struct varlena *data;
|
||||
EPlan *plan;
|
||||
EPlan *plan;
|
||||
|
||||
sprintf(query, "I%s$%s", args[0], args[1]);
|
||||
plan = find_plan(query, &InsertPlans, &nInsertPlans);
|
||||
|
||||
/* no plan yet, so allocate mem for argtypes */
|
||||
if (plan->nplans <= 0) {
|
||||
argtypes = (Oid *)palloc(2*sizeof(Oid));
|
||||
if (plan->nplans <= 0)
|
||||
{
|
||||
argtypes = (Oid *) palloc(2 * sizeof(Oid));
|
||||
|
||||
argtypes[0] = VARCHAROID; /*create table t_name
|
||||
(string varchar, */
|
||||
argtypes[1] = OIDOID; /* id oid); */
|
||||
argtypes[0] = VARCHAROID; /* create table t_name (string
|
||||
* varchar, */
|
||||
argtypes[1] = OIDOID; /* id oid); */
|
||||
|
||||
/* prepare plan to gain speed */
|
||||
sprintf(query, "INSERT INTO %s (string, id) VALUES ($1, $2)",
|
||||
@ -226,45 +235,49 @@ fti()
|
||||
elog(ERROR, "Full Text Indexing: SPI_saveplan returned NULL"
|
||||
" in insert");
|
||||
|
||||
plan->splan = (void **)malloc(sizeof(void*));
|
||||
plan->splan = (void **) malloc(sizeof(void *));
|
||||
*(plan->splan) = pplan;
|
||||
plan->nplans = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* prepare plan for query */
|
||||
colnum=SPI_fnumber(tupdesc, args[1]);
|
||||
colnum = SPI_fnumber(tupdesc, args[1]);
|
||||
if (colnum == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "Full Text Indexing: column '%s' of '%s' not found",
|
||||
args[1], args[0]);
|
||||
|
||||
|
||||
/* Get the char* representation of the column with name args[1] */
|
||||
column = SPI_getvalue(rettuple, tupdesc, colnum);
|
||||
|
||||
if (column) { /* make sure we don't try to index NULL's */
|
||||
char *buff;
|
||||
char *string = column;
|
||||
|
||||
while(*string != '\0') { /* placed 'really' inline. */
|
||||
*string = tolower(*string); /* some compilers will choke */
|
||||
string++; /* on 'inline' keyword */
|
||||
|
||||
if (column)
|
||||
{ /* make sure we don't try to index NULL's */
|
||||
char *buff;
|
||||
char *string = column;
|
||||
|
||||
while (*string != '\0')
|
||||
{ /* placed 'really' inline. */
|
||||
*string = tolower(*string); /* some compilers will
|
||||
* choke */
|
||||
string++; /* on 'inline' keyword */
|
||||
}
|
||||
|
||||
data = (struct varlena*)palloc(sizeof(int32)+strlen(column)+1);
|
||||
data = (struct varlena *) palloc(sizeof(int32) + strlen(column) +1);
|
||||
buff = palloc(strlen(column) + 1);
|
||||
/* saves lots of calls in while-loop and in breakup()*/
|
||||
/* saves lots of calls in while-loop and in breakup() */
|
||||
|
||||
new_tuple=true;
|
||||
while ((substring = breakup(column, buff))) {
|
||||
int l;
|
||||
new_tuple = true;
|
||||
while ((substring = breakup(column, buff)))
|
||||
{
|
||||
int l;
|
||||
|
||||
l = strlen(substring);
|
||||
|
||||
data->vl_len = l+sizeof(int32);
|
||||
data->vl_len = l + sizeof(int32);
|
||||
memcpy(VARDATA(data), substring, l);
|
||||
values[0] = PointerGetDatum(data);
|
||||
values[1] = oid;
|
||||
|
||||
|
||||
ret = SPI_execp(*(plan->splan), values, NULL, 0);
|
||||
if (ret != SPI_OK_INSERT)
|
||||
elog(ERROR, "Full Text Indexing: error executing plan "
|
||||
@ -279,76 +292,83 @@ fti()
|
||||
return (rettuple);
|
||||
}
|
||||
|
||||
char *breakup(char *string, char *substring)
|
||||
char *
|
||||
breakup(char *string, char *substring)
|
||||
{
|
||||
static char *last_start;
|
||||
static char *cur_pos;
|
||||
|
||||
if (new_tuple)
|
||||
{
|
||||
cur_pos=last_start=&string[strlen(string)-1];
|
||||
new_tuple=false; /* don't initialize this next time */
|
||||
cur_pos = last_start = &string[strlen(string) - 1];
|
||||
new_tuple = false; /* don't initialize this next time */
|
||||
}
|
||||
|
||||
while (cur_pos > string) /* don't read before start of 'string' */
|
||||
while (cur_pos > string) /* don't read before start of 'string' */
|
||||
{
|
||||
/* skip pieces at the end of a string that are not
|
||||
alfa-numeric (ie. 'string$%^&', last_start first points to
|
||||
'&', and after this to 'g' */
|
||||
if (!isalnum((int)*last_start)) {
|
||||
while (!isalnum((int)*last_start) &&
|
||||
|
||||
/*
|
||||
* skip pieces at the end of a string that are not alfa-numeric
|
||||
* (ie. 'string$%^&', last_start first points to '&', and after
|
||||
* this to 'g'
|
||||
*/
|
||||
if (!isalnum((int) *last_start))
|
||||
{
|
||||
while (!isalnum((int) *last_start) &&
|
||||
last_start > string)
|
||||
last_start--;
|
||||
cur_pos=last_start;
|
||||
cur_pos = last_start;
|
||||
}
|
||||
|
||||
cur_pos--; /* substrings are at minimum 2 characters long */
|
||||
cur_pos--; /* substrings are at minimum 2 characters
|
||||
* long */
|
||||
|
||||
if (isalnum((int)*cur_pos))
|
||||
if (isalnum((int) *cur_pos))
|
||||
{
|
||||
/* Houston, we have a substring! :) */
|
||||
memcpy(substring, cur_pos, last_start - cur_pos + 1);
|
||||
substring[last_start-cur_pos+1]='\0';
|
||||
if (!is_stopword(substring)) return substring;
|
||||
substring[last_start - cur_pos + 1] = '\0';
|
||||
if (!is_stopword(substring))
|
||||
return substring;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_start=cur_pos-1;
|
||||
last_start = cur_pos - 1;
|
||||
cur_pos = last_start;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* we've processed all of 'string' */
|
||||
return NULL; /* we've processed all of 'string' */
|
||||
}
|
||||
|
||||
/* copied from src/backend/parser/keywords.c and adjusted for our situation*/
|
||||
bool
|
||||
is_stopword(char *text)
|
||||
{
|
||||
char **StopLow; /* for list of stop-words */
|
||||
char **StopHigh;
|
||||
char **StopMiddle;
|
||||
unsigned int difference;
|
||||
char **StopLow; /* for list of stop-words */
|
||||
char **StopHigh;
|
||||
char **StopMiddle;
|
||||
unsigned int difference;
|
||||
|
||||
StopLow = &StopWords[0]; /* initialize stuff for binary search */
|
||||
StopLow = &StopWords[0]; /* initialize stuff for binary search */
|
||||
StopHigh = endof(StopWords);
|
||||
|
||||
if (lengthof(StopWords) == 0)
|
||||
return false;
|
||||
|
||||
while (StopLow <= StopHigh)
|
||||
{
|
||||
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
|
||||
difference = strcmp(*StopMiddle, text);
|
||||
if (difference == 0)
|
||||
return (true);
|
||||
else if (difference < 0)
|
||||
StopLow = StopMiddle + 1;
|
||||
else
|
||||
StopHigh = StopMiddle - 1;
|
||||
}
|
||||
|
||||
return (false);
|
||||
while (StopLow <= StopHigh)
|
||||
{
|
||||
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
|
||||
difference = strcmp(*StopMiddle, text);
|
||||
if (difference == 0)
|
||||
return (true);
|
||||
else if (difference < 0)
|
||||
StopLow = StopMiddle + 1;
|
||||
else
|
||||
StopHigh = StopMiddle - 1;
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* for caching of query plans, stolen from contrib/spi/\*.c */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for ISBNs.
|
||||
*
|
||||
* $Id: isbn.c,v 1.1 1998/08/17 03:35:04 scrappy Exp $
|
||||
* $Id: isbn.c,v 1.2 1999/05/25 16:05:40 momjian Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -16,8 +16,8 @@
|
||||
|
||||
typedef struct isbn
|
||||
{
|
||||
char num[13];
|
||||
char pad[3];
|
||||
char num[13];
|
||||
char pad[3];
|
||||
} isbn;
|
||||
|
||||
/*
|
||||
@ -50,13 +50,15 @@ isbn_in(char *str)
|
||||
char *cp;
|
||||
int count;
|
||||
|
||||
if (strlen(str) != 13) {
|
||||
if (strlen(str) != 13)
|
||||
{
|
||||
elog(ERROR, "isbn_in: invalid ISBN \"%s\"", str);
|
||||
return (NULL);
|
||||
}
|
||||
if (isbn_sum(str) != 0) {
|
||||
if (isbn_sum(str) != 0)
|
||||
{
|
||||
elog(ERROR, "isbn_in: purported ISBN \"%s\" failed checksum",
|
||||
str);
|
||||
str);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -84,28 +86,40 @@ isbn_in(char *str)
|
||||
int4
|
||||
isbn_sum(char *str)
|
||||
{
|
||||
int4 sum = 0, dashes = 0, val;
|
||||
int i;
|
||||
int4 sum = 0,
|
||||
dashes = 0,
|
||||
val;
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i] && i < 13; i++) {
|
||||
switch(str[i]) {
|
||||
case '-':
|
||||
if (++dashes > 3)
|
||||
for (i = 0; str[i] && i < 13; i++)
|
||||
{
|
||||
switch (str[i])
|
||||
{
|
||||
case '-':
|
||||
if (++dashes > 3)
|
||||
return 12;
|
||||
continue;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
val = str[i] - '0';
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
case 'x':
|
||||
val = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 12;
|
||||
continue;
|
||||
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
val = str[i] - '0';
|
||||
break;
|
||||
|
||||
case 'X': case 'x':
|
||||
val = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 12;
|
||||
}
|
||||
|
||||
sum += val * (i + 1 - dashes);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for ISSNs.
|
||||
*
|
||||
* $Id: issn.c,v 1.1 1998/08/17 03:35:05 scrappy Exp $
|
||||
* $Id: issn.c,v 1.2 1999/05/25 16:05:42 momjian Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -16,8 +16,8 @@
|
||||
|
||||
typedef struct issn
|
||||
{
|
||||
char num[9];
|
||||
char pad[7];
|
||||
char num[9];
|
||||
char pad[7];
|
||||
} issn;
|
||||
|
||||
/*
|
||||
@ -50,13 +50,15 @@ issn_in(char *str)
|
||||
char *cp;
|
||||
int count;
|
||||
|
||||
if (strlen(str) != 9) {
|
||||
if (strlen(str) != 9)
|
||||
{
|
||||
elog(ERROR, "issn_in: invalid ISSN \"%s\"", str);
|
||||
return (NULL);
|
||||
}
|
||||
if (issn_sum(str) != 0) {
|
||||
if (issn_sum(str) != 0)
|
||||
{
|
||||
elog(ERROR, "issn_in: purported ISSN \"%s\" failed checksum",
|
||||
str);
|
||||
str);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -75,28 +77,40 @@ issn_in(char *str)
|
||||
int4
|
||||
issn_sum(char *str)
|
||||
{
|
||||
int4 sum = 0, dashes = 0, val;
|
||||
int i;
|
||||
int4 sum = 0,
|
||||
dashes = 0,
|
||||
val;
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i] && i < 9; i++) {
|
||||
switch(str[i]) {
|
||||
case '-':
|
||||
if (++dashes > 1)
|
||||
for (i = 0; str[i] && i < 9; i++)
|
||||
{
|
||||
switch (str[i])
|
||||
{
|
||||
case '-':
|
||||
if (++dashes > 1)
|
||||
return 12;
|
||||
continue;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
val = str[i] - '0';
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
case 'x':
|
||||
val = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 12;
|
||||
continue;
|
||||
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
val = str[i] - '0';
|
||||
break;
|
||||
|
||||
case 'X': case 'x':
|
||||
val = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 12;
|
||||
}
|
||||
|
||||
sum += val * (8 - (i - dashes));
|
||||
|
245
contrib/lo/lo.c
245
contrib/lo/lo.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for managed LargeObjects.
|
||||
*
|
||||
* $Id: lo.c,v 1.1 1998/06/16 07:07:11 momjian Exp $
|
||||
* $Id: lo.c,v 1.2 1999/05/25 16:05:45 momjian Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,11 +33,11 @@ typedef Oid Blob;
|
||||
* Various forward declarations:
|
||||
*/
|
||||
|
||||
Blob *lo_in(char *str); /* Create from String */
|
||||
char *lo_out(Blob * addr); /* Output oid as String */
|
||||
Oid lo_oid(Blob * addr); /* Return oid as an oid */
|
||||
Blob *lo(Oid oid); /* Return Blob based on oid */
|
||||
HeapTuple lo_manage(void); /* Trigger handler */
|
||||
Blob *lo_in(char *str); /* Create from String */
|
||||
char *lo_out(Blob * addr);/* Output oid as String */
|
||||
Oid lo_oid(Blob * addr);/* Return oid as an oid */
|
||||
Blob *lo(Oid oid); /* Return Blob based on oid */
|
||||
HeapTuple lo_manage(void); /* Trigger handler */
|
||||
|
||||
/*
|
||||
* This creates a large object, and set's its OID to the value in the
|
||||
@ -49,45 +49,46 @@ HeapTuple lo_manage(void); /* Trigger handler */
|
||||
Blob *
|
||||
lo_in(char *str)
|
||||
{
|
||||
Blob *result;
|
||||
Oid oid;
|
||||
int count;
|
||||
|
||||
if (strlen(str) > 0)
|
||||
Blob *result;
|
||||
Oid oid;
|
||||
int count;
|
||||
|
||||
if (strlen(str) > 0)
|
||||
{
|
||||
|
||||
count = sscanf(str, "%d", &oid);
|
||||
|
||||
if (count < 1)
|
||||
|
||||
count = sscanf(str, "%d", &oid);
|
||||
|
||||
if (count < 1)
|
||||
{
|
||||
elog(ERROR, "lo_in: error in parsing \"%s\"", str);
|
||||
return (NULL);
|
||||
elog(ERROR, "lo_in: error in parsing \"%s\"", str);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if(oid < 0)
|
||||
|
||||
if (oid < 0)
|
||||
{
|
||||
elog(ERROR, "lo_in: illegal oid \"%s\"", str);
|
||||
return (NULL);
|
||||
elog(ERROR, "lo_in: illegal oid \"%s\"", str);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
/*
|
||||
* There is no Oid passed, so create a new one
|
||||
*/
|
||||
oid = lo_creat(INV_READ|INV_WRITE);
|
||||
if(oid == InvalidOid)
|
||||
|
||||
/*
|
||||
* There is no Oid passed, so create a new one
|
||||
*/
|
||||
oid = lo_creat(INV_READ | INV_WRITE);
|
||||
if (oid == InvalidOid)
|
||||
{
|
||||
elog(ERROR,"lo_in: InvalidOid returned from lo_creat");
|
||||
return (NULL);
|
||||
elog(ERROR, "lo_in: InvalidOid returned from lo_creat");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
result = (Blob *) palloc(sizeof(Blob));
|
||||
|
||||
*result = oid;
|
||||
|
||||
return (result);
|
||||
|
||||
result = (Blob *) palloc(sizeof(Blob));
|
||||
|
||||
*result = oid;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -96,42 +97,43 @@ lo_in(char *str)
|
||||
char *
|
||||
lo_out(Blob * addr)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (addr == NULL)
|
||||
return (NULL);
|
||||
|
||||
result = (char *) palloc(32);
|
||||
sprintf(result,"%d",*addr);
|
||||
return (result);
|
||||
char *result;
|
||||
|
||||
if (addr == NULL)
|
||||
return (NULL);
|
||||
|
||||
result = (char *) palloc(32);
|
||||
sprintf(result, "%d", *addr);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function converts Blob to oid.
|
||||
*
|
||||
* eg: select lo_export(raster::oid,'/path/file') from table;
|
||||
*
|
||||
*
|
||||
*/
|
||||
Oid
|
||||
lo_oid(Blob * addr)
|
||||
{
|
||||
if(addr == NULL)
|
||||
return InvalidOid;
|
||||
return (Oid)(*addr);
|
||||
if (addr == NULL)
|
||||
return InvalidOid;
|
||||
return (Oid) (*addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used so we can convert oid's to lo's
|
||||
*
|
||||
* ie: insert into table values(lo_import('/path/file')::lo);
|
||||
* ie: insert into table values(lo_import('/path/file')::lo);
|
||||
*
|
||||
*/
|
||||
Blob *
|
||||
lo(Oid oid)
|
||||
{
|
||||
Blob *result = (Blob *) palloc(sizeof(Blob));
|
||||
*result = oid;
|
||||
return (result);
|
||||
Blob *result = (Blob *) palloc(sizeof(Blob));
|
||||
|
||||
*result = oid;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -140,74 +142,77 @@ lo(Oid oid)
|
||||
HeapTuple
|
||||
lo_manage(void)
|
||||
{
|
||||
int attnum; /* attribute number to monitor */
|
||||
char **args; /* Args containing attr name */
|
||||
TupleDesc tupdesc; /* Tuple Descriptor */
|
||||
HeapTuple rettuple; /* Tuple to be returned */
|
||||
bool isdelete; /* are we deleting? */
|
||||
HeapTuple newtuple=NULL; /* The new value for tuple */
|
||||
HeapTuple trigtuple; /* The original value of tuple */
|
||||
|
||||
if (!CurrentTriggerData)
|
||||
elog(ERROR, "lo: triggers are not initialized");
|
||||
|
||||
/*
|
||||
* Fetch some values from CurrentTriggerData
|
||||
*/
|
||||
newtuple = CurrentTriggerData->tg_newtuple;
|
||||
trigtuple = CurrentTriggerData->tg_trigtuple;
|
||||
tupdesc = CurrentTriggerData->tg_relation->rd_att;
|
||||
args = CurrentTriggerData->tg_trigger->tgargs;
|
||||
|
||||
/* tuple to return to Executor */
|
||||
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
|
||||
rettuple = newtuple;
|
||||
else
|
||||
rettuple = trigtuple;
|
||||
|
||||
/* Are we deleting the row? */
|
||||
isdelete = TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event);
|
||||
|
||||
/* Were done with it */
|
||||
CurrentTriggerData = NULL;
|
||||
|
||||
/* Get the column were interested in */
|
||||
attnum = SPI_fnumber(tupdesc,args[0]);
|
||||
|
||||
/*
|
||||
* Handle updates
|
||||
*
|
||||
* Here, if the value of the monitored attribute changes, then the
|
||||
* large object associated with the original value is unlinked.
|
||||
*/
|
||||
if(newtuple!=NULL) {
|
||||
char *orig = SPI_getvalue(trigtuple,tupdesc,attnum);
|
||||
char *newv = SPI_getvalue(newtuple,tupdesc,attnum);
|
||||
|
||||
if((orig != newv && (orig==NULL || newv==NULL)) || (orig!=NULL && newv!=NULL && strcmp(orig,newv)))
|
||||
lo_unlink(atoi(orig));
|
||||
|
||||
if(newv)
|
||||
pfree(newv);
|
||||
if(orig)
|
||||
pfree(orig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle deleting of rows
|
||||
*
|
||||
* Here, we unlink the large object associated with the managed attribute
|
||||
*
|
||||
*/
|
||||
if(isdelete) {
|
||||
char *orig = SPI_getvalue(trigtuple,tupdesc,attnum);
|
||||
|
||||
if(orig != NULL) {
|
||||
lo_unlink(atoi(orig));
|
||||
|
||||
pfree(orig);
|
||||
int attnum; /* attribute number to monitor */
|
||||
char **args; /* Args containing attr name */
|
||||
TupleDesc tupdesc; /* Tuple Descriptor */
|
||||
HeapTuple rettuple; /* Tuple to be returned */
|
||||
bool isdelete; /* are we deleting? */
|
||||
HeapTuple newtuple = NULL;/* The new value for tuple */
|
||||
HeapTuple trigtuple; /* The original value of tuple */
|
||||
|
||||
if (!CurrentTriggerData)
|
||||
elog(ERROR, "lo: triggers are not initialized");
|
||||
|
||||
/*
|
||||
* Fetch some values from CurrentTriggerData
|
||||
*/
|
||||
newtuple = CurrentTriggerData->tg_newtuple;
|
||||
trigtuple = CurrentTriggerData->tg_trigtuple;
|
||||
tupdesc = CurrentTriggerData->tg_relation->rd_att;
|
||||
args = CurrentTriggerData->tg_trigger->tgargs;
|
||||
|
||||
/* tuple to return to Executor */
|
||||
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
|
||||
rettuple = newtuple;
|
||||
else
|
||||
rettuple = trigtuple;
|
||||
|
||||
/* Are we deleting the row? */
|
||||
isdelete = TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event);
|
||||
|
||||
/* Were done with it */
|
||||
CurrentTriggerData = NULL;
|
||||
|
||||
/* Get the column were interested in */
|
||||
attnum = SPI_fnumber(tupdesc, args[0]);
|
||||
|
||||
/*
|
||||
* Handle updates
|
||||
*
|
||||
* Here, if the value of the monitored attribute changes, then the large
|
||||
* object associated with the original value is unlinked.
|
||||
*/
|
||||
if (newtuple != NULL)
|
||||
{
|
||||
char *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
|
||||
char *newv = SPI_getvalue(newtuple, tupdesc, attnum);
|
||||
|
||||
if ((orig != newv && (orig == NULL || newv == NULL)) || (orig != NULL && newv != NULL && strcmp(orig, newv)))
|
||||
lo_unlink(atoi(orig));
|
||||
|
||||
if (newv)
|
||||
pfree(newv);
|
||||
if (orig)
|
||||
pfree(orig);
|
||||
}
|
||||
}
|
||||
|
||||
return (rettuple);
|
||||
|
||||
/*
|
||||
* Handle deleting of rows
|
||||
*
|
||||
* Here, we unlink the large object associated with the managed attribute
|
||||
*
|
||||
*/
|
||||
if (isdelete)
|
||||
{
|
||||
char *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
|
||||
|
||||
if (orig != NULL)
|
||||
{
|
||||
lo_unlink(atoi(orig));
|
||||
|
||||
pfree(orig);
|
||||
}
|
||||
}
|
||||
|
||||
return (rettuple);
|
||||
}
|
||||
|
@ -6,270 +6,360 @@
|
||||
|
||||
#define HNDMAX 10
|
||||
|
||||
PGconn *PGh[HNDMAX] = {
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
PGconn *PGh[HNDMAX] = {
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
#define E_NOHANDLERS 0
|
||||
|
||||
char *msqlErrors[] = {
|
||||
"Out of database handlers."
|
||||
char *msqlErrors[] = {
|
||||
"Out of database handlers."
|
||||
};
|
||||
|
||||
char msqlErrMsg[BUFSIZ], *tfrom = "dunno";
|
||||
PGresult *queryres = NULL;
|
||||
char msqlErrMsg[BUFSIZ],
|
||||
*tfrom = "dunno";
|
||||
PGresult *queryres = NULL;
|
||||
|
||||
int msqlConnect (char *host) {
|
||||
int count;
|
||||
|
||||
for (count = 0; count < HNDMAX; count++)
|
||||
if (PGh[count] == NULL) break;
|
||||
|
||||
if (count == HNDMAX) {
|
||||
strncpy(msqlErrMsg, msqlErrors[E_NOHANDLERS], BUFSIZ);
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
msqlConnect(char *host)
|
||||
{
|
||||
int count;
|
||||
|
||||
PGh[count] = malloc(sizeof (PGconn));
|
||||
PGh[count]->pghost = host ? strdup(host) : NULL;
|
||||
return count;
|
||||
for (count = 0; count < HNDMAX; count++)
|
||||
if (PGh[count] == NULL)
|
||||
break;
|
||||
|
||||
if (count == HNDMAX)
|
||||
{
|
||||
strncpy(msqlErrMsg, msqlErrors[E_NOHANDLERS], BUFSIZ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PGh[count] = malloc(sizeof(PGconn));
|
||||
PGh[count]->pghost = host ? strdup(host) : NULL;
|
||||
return count;
|
||||
}
|
||||
|
||||
int msqlSelectDB(int handle, char *dbname) {
|
||||
char *options = calloc(1, BUFSIZ);
|
||||
char *e = getenv("PG_OPTIONS");
|
||||
|
||||
if (e == NULL)
|
||||
e = "";
|
||||
|
||||
if (PGh[handle]->pghost) {
|
||||
strcat(options, "host=");
|
||||
strncat(options, PGh[handle]->pghost, BUFSIZ);
|
||||
strncat(options, " ", BUFSIZ);
|
||||
free(PGh[handle]->pghost);
|
||||
PGh[handle]->pghost = NULL;
|
||||
}
|
||||
strncat(options, "dbname=", BUFSIZ);
|
||||
strncat(options, dbname, BUFSIZ);
|
||||
strncat(options, " ", BUFSIZ);
|
||||
strncat(options, e, BUFSIZ);
|
||||
free(PGh[handle]);
|
||||
PGh[handle] = PQconnectdb(options);
|
||||
free(options);
|
||||
strncpy(msqlErrMsg, PQerrorMessage(PGh[handle]), BUFSIZ);
|
||||
return (PQstatus(PGh[handle]) == CONNECTION_BAD ? -1 : 0);
|
||||
int
|
||||
msqlSelectDB(int handle, char *dbname)
|
||||
{
|
||||
char *options = calloc(1, BUFSIZ);
|
||||
char *e = getenv("PG_OPTIONS");
|
||||
|
||||
if (e == NULL)
|
||||
e = "";
|
||||
|
||||
if (PGh[handle]->pghost)
|
||||
{
|
||||
strcat(options, "host=");
|
||||
strncat(options, PGh[handle]->pghost, BUFSIZ);
|
||||
strncat(options, " ", BUFSIZ);
|
||||
free(PGh[handle]->pghost);
|
||||
PGh[handle]->pghost = NULL;
|
||||
}
|
||||
strncat(options, "dbname=", BUFSIZ);
|
||||
strncat(options, dbname, BUFSIZ);
|
||||
strncat(options, " ", BUFSIZ);
|
||||
strncat(options, e, BUFSIZ);
|
||||
free(PGh[handle]);
|
||||
PGh[handle] = PQconnectdb(options);
|
||||
free(options);
|
||||
strncpy(msqlErrMsg, PQerrorMessage(PGh[handle]), BUFSIZ);
|
||||
return (PQstatus(PGh[handle]) == CONNECTION_BAD ? -1 : 0);
|
||||
}
|
||||
|
||||
int msqlQuery(int handle, char *query) {
|
||||
char *tq = strdup(query);
|
||||
char *p = tq;
|
||||
PGresult *res;
|
||||
PGconn *conn = PGh[handle];
|
||||
ExecStatusType rcode;
|
||||
|
||||
res = PQexec(conn, p);
|
||||
int
|
||||
msqlQuery(int handle, char *query)
|
||||
{
|
||||
char *tq = strdup(query);
|
||||
char *p = tq;
|
||||
PGresult *res;
|
||||
PGconn *conn = PGh[handle];
|
||||
ExecStatusType rcode;
|
||||
|
||||
rcode = PQresultStatus(res);
|
||||
|
||||
if (rcode == PGRES_TUPLES_OK) {
|
||||
queryres = res;
|
||||
return PQntuples(res);
|
||||
} else if (rcode == PGRES_FATAL_ERROR || rcode == PGRES_NONFATAL_ERROR) {
|
||||
PQclear(res);
|
||||
queryres = NULL;
|
||||
return -1;
|
||||
} else {
|
||||
PQclear(res);
|
||||
queryres = NULL;
|
||||
return 0;
|
||||
}
|
||||
res = PQexec(conn, p);
|
||||
|
||||
rcode = PQresultStatus(res);
|
||||
|
||||
if (rcode == PGRES_TUPLES_OK)
|
||||
{
|
||||
queryres = res;
|
||||
return PQntuples(res);
|
||||
}
|
||||
else if (rcode == PGRES_FATAL_ERROR || rcode == PGRES_NONFATAL_ERROR)
|
||||
{
|
||||
PQclear(res);
|
||||
queryres = NULL;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PQclear(res);
|
||||
queryres = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int msqlCreateDB (int a, char*b) {
|
||||
char tbuf[BUFSIZ];
|
||||
sprintf(tbuf, "create database %s", b);
|
||||
return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
|
||||
int
|
||||
msqlCreateDB(int a, char *b)
|
||||
{
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "create database %s", b);
|
||||
return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int msqlDropDB (int a, char* b) {
|
||||
char tbuf[BUFSIZ];
|
||||
sprintf(tbuf, "drop database %s", b);
|
||||
return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
|
||||
int
|
||||
msqlDropDB(int a, char *b)
|
||||
{
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "drop database %s", b);
|
||||
return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int msqlShutdown(int a) {
|
||||
int
|
||||
msqlShutdown(int a)
|
||||
{
|
||||
}
|
||||
|
||||
int msqlGetProtoInfo(void) {
|
||||
int
|
||||
msqlGetProtoInfo(void)
|
||||
{
|
||||
}
|
||||
|
||||
int msqlReloadAcls(int a) {
|
||||
int
|
||||
msqlReloadAcls(int a)
|
||||
{
|
||||
}
|
||||
|
||||
char *msqlGetServerInfo(void) {
|
||||
char *
|
||||
msqlGetServerInfo(void)
|
||||
{
|
||||
}
|
||||
|
||||
char *msqlGetHostInfo(void) {
|
||||
char *
|
||||
msqlGetHostInfo(void)
|
||||
{
|
||||
}
|
||||
|
||||
char *msqlUnixTimeToDate(time_t date) {
|
||||
char *
|
||||
msqlUnixTimeToDate(time_t date)
|
||||
{
|
||||
}
|
||||
|
||||
char *msqlUnixTimeToTime(time_t time) {
|
||||
char *
|
||||
msqlUnixTimeToTime(time_t time)
|
||||
{
|
||||
}
|
||||
|
||||
void msqlClose(int a) {
|
||||
PQfinish(PGh[a]);
|
||||
PGh[a] = NULL;
|
||||
if (queryres) {
|
||||
free(queryres);
|
||||
queryres = NULL;
|
||||
}
|
||||
void
|
||||
msqlClose(int a)
|
||||
{
|
||||
PQfinish(PGh[a]);
|
||||
PGh[a] = NULL;
|
||||
if (queryres)
|
||||
{
|
||||
free(queryres);
|
||||
queryres = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void msqlDataSeek(m_result *result, int count) {
|
||||
int c;
|
||||
result->cursor = result->queryData;
|
||||
for (c = 1; c < count; c++)
|
||||
if (result->cursor->next)
|
||||
result->cursor = result->cursor->next;
|
||||
void
|
||||
msqlDataSeek(m_result * result, int count)
|
||||
{
|
||||
int c;
|
||||
|
||||
result->cursor = result->queryData;
|
||||
for (c = 1; c < count; c++)
|
||||
if (result->cursor->next)
|
||||
result->cursor = result->cursor->next;
|
||||
}
|
||||
|
||||
void msqlFieldSeek(m_result *result, int count) {
|
||||
int c;
|
||||
result->fieldCursor = result->fieldData;
|
||||
for (c = 1; c < count; c++)
|
||||
if (result->fieldCursor->next)
|
||||
result->fieldCursor = result->fieldCursor->next;
|
||||
void
|
||||
msqlFieldSeek(m_result * result, int count)
|
||||
{
|
||||
int c;
|
||||
|
||||
result->fieldCursor = result->fieldData;
|
||||
for (c = 1; c < count; c++)
|
||||
if (result->fieldCursor->next)
|
||||
result->fieldCursor = result->fieldCursor->next;
|
||||
}
|
||||
|
||||
void msqlFreeResult(m_result *result) {
|
||||
if (result) {
|
||||
/* Clears fields */
|
||||
free(result->fieldData);
|
||||
result->cursor = result->queryData;
|
||||
while (result->cursor) {
|
||||
int c;
|
||||
m_row m = result->cursor->data;
|
||||
|
||||
for (c = 0; m[c]; c++)
|
||||
free(m[c]);
|
||||
void
|
||||
msqlFreeResult(m_result * result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
/* Clears fields */
|
||||
free(result->fieldData);
|
||||
result->cursor = result->queryData;
|
||||
while (result->cursor)
|
||||
{
|
||||
int c;
|
||||
m_row m = result->cursor->data;
|
||||
|
||||
result->cursor = result->cursor->next;
|
||||
}
|
||||
free(result->queryData);
|
||||
free(result);
|
||||
}
|
||||
for (c = 0; m[c]; c++)
|
||||
free(m[c]);
|
||||
|
||||
result->cursor = result->cursor->next;
|
||||
}
|
||||
free(result->queryData);
|
||||
free(result);
|
||||
}
|
||||
}
|
||||
|
||||
m_row msqlFetchRow(m_result *row) {
|
||||
m_data *r = row->cursor;
|
||||
if (r) {
|
||||
row->cursor = row->cursor->next;
|
||||
return (m_row)r->data;
|
||||
}
|
||||
return (m_row)NULL;
|
||||
m_row
|
||||
msqlFetchRow(m_result * row)
|
||||
{
|
||||
m_data *r = row->cursor;
|
||||
|
||||
if (r)
|
||||
{
|
||||
row->cursor = row->cursor->next;
|
||||
return (m_row) r->data;
|
||||
}
|
||||
return (m_row) NULL;
|
||||
}
|
||||
|
||||
m_seq *msqlGetSequenceInfo(int a, char *b) {
|
||||
m_seq *
|
||||
msqlGetSequenceInfo(int a, char *b)
|
||||
{
|
||||
}
|
||||
|
||||
m_field *msqlFetchField (m_result *mr) {
|
||||
m_field *m = (m_field*)mr->fieldCursor;
|
||||
if (m) {
|
||||
mr->fieldCursor = mr->fieldCursor->next;
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
m_field *
|
||||
msqlFetchField(m_result * mr)
|
||||
{
|
||||
m_field *m = (m_field *) mr->fieldCursor;
|
||||
|
||||
if (m)
|
||||
{
|
||||
mr->fieldCursor = mr->fieldCursor->next;
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_result *msqlListDBs(int a) {
|
||||
m_result *m;
|
||||
if (msqlQuery(a, "select datname from pg_database") > 0) {
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
} else return NULL;
|
||||
m_result *
|
||||
msqlListDBs(int a)
|
||||
{
|
||||
m_result *m;
|
||||
|
||||
if (msqlQuery(a, "select datname from pg_database") > 0)
|
||||
{
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_result *msqlListTables(int a) {
|
||||
m_result *m;
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "select relname from pg_class where relkind='r' and relowner=%d", getuid());
|
||||
if (msqlQuery(a, tbuf) > 0) {
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
} else return NULL;
|
||||
m_result *
|
||||
msqlListTables(int a)
|
||||
{
|
||||
m_result *m;
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "select relname from pg_class where relkind='r' and relowner=%d", getuid());
|
||||
if (msqlQuery(a, tbuf) > 0)
|
||||
{
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_result *msqlListFields(int a, char *b) {
|
||||
|
||||
m_result *
|
||||
msqlListFields(int a, char *b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
m_result *msqlListIndex(int a, char *b, char *c) {
|
||||
m_result *m;
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "select relname from pg_class where relkind='i' and relowner=%d", getuid());
|
||||
if (msqlQuery(a, tbuf) > 0) {
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
} else return NULL;
|
||||
m_result *
|
||||
msqlListIndex(int a, char *b, char *c)
|
||||
{
|
||||
m_result *m;
|
||||
char tbuf[BUFSIZ];
|
||||
|
||||
sprintf(tbuf, "select relname from pg_class where relkind='i' and relowner=%d", getuid());
|
||||
if (msqlQuery(a, tbuf) > 0)
|
||||
{
|
||||
m = msqlStoreResult();
|
||||
return m;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_result *msqlStoreResult(void) {
|
||||
if (queryres) {
|
||||
m_result *mr = malloc(sizeof(m_result));
|
||||
m_fdata *mf;
|
||||
m_data *md;
|
||||
int count;
|
||||
mr->queryData = mr->cursor = NULL;
|
||||
mr->numRows = PQntuples(queryres);
|
||||
mr->numFields = PQnfields(queryres);
|
||||
|
||||
mf = calloc(PQnfields(queryres), sizeof(m_fdata));
|
||||
for (count = 0; count < PQnfields(queryres); count++) {
|
||||
(m_fdata*)(mf+count)->field.name = strdup(PQfname(queryres, count));
|
||||
(m_fdata*)(mf+count)->field.table = tfrom;
|
||||
(m_fdata*)(mf+count)->field.type = CHAR_TYPE;
|
||||
(m_fdata*)(mf+count)->field.length = PQfsize(queryres, count);
|
||||
(m_fdata*)(mf+count)->next = (m_fdata*)(mf+count+1);
|
||||
}
|
||||
(m_fdata*)(mf+count-1)->next = NULL;
|
||||
|
||||
md = calloc(PQntuples(queryres), sizeof(m_data));
|
||||
for (count = 0; count < PQntuples(queryres); count++) {
|
||||
m_row rows = calloc(PQnfields(queryres)*sizeof(m_row)+1, 1);
|
||||
int c;
|
||||
|
||||
for (c = 0; c < PQnfields(queryres); c++) {
|
||||
rows[c] = strdup(PQgetvalue(queryres, count, c));
|
||||
}
|
||||
(m_data*)(md+count)->data = rows;
|
||||
|
||||
(m_data*)(md+count)->width = PQnfields(queryres);
|
||||
(m_data*)(md+count)->next = (m_data*)(md+count+1);
|
||||
}
|
||||
(m_data*)(md+count-1)->next = NULL;
|
||||
|
||||
mr->queryData = mr->cursor = md;
|
||||
mr->fieldCursor = mr->fieldData = mf;
|
||||
m_result *
|
||||
msqlStoreResult(void)
|
||||
{
|
||||
if (queryres)
|
||||
{
|
||||
m_result *mr = malloc(sizeof(m_result));
|
||||
m_fdata *mf;
|
||||
m_data *md;
|
||||
int count;
|
||||
|
||||
return mr;
|
||||
} else return NULL;
|
||||
mr->queryData = mr->cursor = NULL;
|
||||
mr->numRows = PQntuples(queryres);
|
||||
mr->numFields = PQnfields(queryres);
|
||||
|
||||
mf = calloc(PQnfields(queryres), sizeof(m_fdata));
|
||||
for (count = 0; count < PQnfields(queryres); count++)
|
||||
{
|
||||
(m_fdata *) (mf + count)->field.name = strdup(PQfname(queryres, count));
|
||||
(m_fdata *) (mf + count)->field.table = tfrom;
|
||||
(m_fdata *) (mf + count)->field.type = CHAR_TYPE;
|
||||
(m_fdata *) (mf + count)->field.length = PQfsize(queryres, count);
|
||||
(m_fdata *) (mf + count)->next = (m_fdata *) (mf + count + 1);
|
||||
}
|
||||
(m_fdata *) (mf + count - 1)->next = NULL;
|
||||
|
||||
md = calloc(PQntuples(queryres), sizeof(m_data));
|
||||
for (count = 0; count < PQntuples(queryres); count++)
|
||||
{
|
||||
m_row rows = calloc(PQnfields(queryres) * sizeof(m_row) + 1, 1);
|
||||
int c;
|
||||
|
||||
for (c = 0; c < PQnfields(queryres); c++)
|
||||
rows[c] = strdup(PQgetvalue(queryres, count, c));
|
||||
(m_data *) (md + count)->data = rows;
|
||||
|
||||
(m_data *) (md + count)->width = PQnfields(queryres);
|
||||
(m_data *) (md + count)->next = (m_data *) (md + count + 1);
|
||||
}
|
||||
(m_data *) (md + count - 1)->next = NULL;
|
||||
|
||||
mr->queryData = mr->cursor = md;
|
||||
mr->fieldCursor = mr->fieldData = mf;
|
||||
|
||||
return mr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
time_t msqlDateToUnixTime(char *a) {
|
||||
time_t
|
||||
msqlDateToUnixTime(char *a)
|
||||
{
|
||||
}
|
||||
|
||||
time_t msqlTimeToUnixTime(char *b) {
|
||||
time_t
|
||||
msqlTimeToUnixTime(char *b)
|
||||
{
|
||||
}
|
||||
|
||||
char *msql_tmpnam(void) {
|
||||
return tmpnam("/tmp/msql.XXXXXX");
|
||||
char *
|
||||
msql_tmpnam(void)
|
||||
{
|
||||
return tmpnam("/tmp/msql.XXXXXX");
|
||||
}
|
||||
|
||||
int msqlLoadConfigFile(char *a) {
|
||||
int
|
||||
msqlLoadConfigFile(char *a)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ extern int assertTest(int val);
|
||||
|
||||
#ifdef ASSERT_CHECKING_TEST
|
||||
extern int assertEnable(int val);
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
@ -68,14 +69,15 @@ assert_test(int val)
|
||||
{
|
||||
return assertTest(val);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* end of file */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -7,16 +7,18 @@ int unlisten(char *relname);
|
||||
int max(int x, int y);
|
||||
int min(int x, int y);
|
||||
int assert_enable(int val);
|
||||
|
||||
#ifdef ASSERT_CHECKING_TEST
|
||||
int assert_test(int val);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ HeapTuple noup(void);
|
||||
* noup () -- revoke permission on column
|
||||
*
|
||||
* Though it's called without args You have to specify referenced
|
||||
* table/column while creating trigger:
|
||||
* table/column while creating trigger:
|
||||
* EXECUTE PROCEDURE noup ('col').
|
||||
*/
|
||||
|
||||
@ -98,8 +98,8 @@ noup()
|
||||
*/
|
||||
if (!isnull)
|
||||
{
|
||||
|
||||
elog(WARN, "%s: update not allowed", args[i] );
|
||||
|
||||
elog(WARN, "%s: update not allowed", args[i]);
|
||||
SPI_finish();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#undef PORTNAME
|
||||
#define PORTNAME OS2
|
||||
#undef PORTNAME
|
||||
#define PORTNAME OS2
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* c.h--
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: c.h,v 1.1 1998/10/31 04:10:53 scrappy Exp $
|
||||
* $Id: c.h,v 1.2 1999/05/25 16:06:01 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -65,7 +65,8 @@
|
||||
#ifndef __cplusplus
|
||||
#ifndef bool
|
||||
typedef char bool;
|
||||
#endif /* ndef bool */
|
||||
|
||||
#endif /* ndef bool */
|
||||
#endif /* not C++ */
|
||||
typedef bool *BoolPtr;
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
|
||||
#ifndef TCPIPV4
|
||||
# define TCPIPV4
|
||||
#endif
|
||||
#define TCPIPV4
|
||||
#endif /*
|
||||
*/
|
||||
|
||||
#ifndef MAXSOCKETS
|
||||
#endif
|
||||
#define MAXSOCKETS 2048
|
||||
#endif /*
|
||||
/*
|
||||
* DEF_PGPORT is the TCP port number on which the Postmaster listens by
|
||||
* default. This can be overriden by command options, environment variables,
|
||||
* and the postconfig hook. (set by build script)
|
||||
*/
|
||||
*/
|
||||
|
||||
/*
|
||||
* DEF_PGPORT is the TCP port number on which the Postmaster listens by
|
||||
* default. This can be overriden by command options, environment variables,
|
||||
* and the postconfig hook. (set by build script)
|
||||
*/
|
||||
|
||||
|
@ -206,28 +206,30 @@ on_error_continue()
|
||||
** get_result
|
||||
**
|
||||
*/
|
||||
PGresult *get_result()
|
||||
PGresult *
|
||||
get_result()
|
||||
{
|
||||
char *cmdstatus = PQcmdStatus(res);
|
||||
|
||||
char *cmdstatus = PQcmdStatus(res);
|
||||
|
||||
was_get_unset_result = TRUE;
|
||||
|
||||
/* we have to store the fetch location somewhere */
|
||||
cmdstatus[0] = NUL;
|
||||
memcpy(&cmdstatus[1],&tuple, sizeof(tuple));
|
||||
memcpy(&cmdstatus[1], &tuple, sizeof(tuple));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**
|
||||
** set_result
|
||||
**
|
||||
*/
|
||||
void set_result(PGresult *newres)
|
||||
void
|
||||
set_result(PGresult *newres)
|
||||
{
|
||||
|
||||
char *cmdstatus = PQcmdStatus(res);
|
||||
char *cmdstatus = PQcmdStatus(res);
|
||||
|
||||
if (newres == NULL)
|
||||
halt("set_result called with null result pointer\n");
|
||||
@ -256,9 +258,10 @@ void set_result(PGresult *newres)
|
||||
** unset_result
|
||||
**
|
||||
*/
|
||||
void unset_result(PGresult *oldres)
|
||||
void
|
||||
unset_result(PGresult *oldres)
|
||||
{
|
||||
char *cmdstatus = PQcmdStatus(oldres);
|
||||
char *cmdstatus = PQcmdStatus(oldres);
|
||||
|
||||
if (oldres == NULL)
|
||||
halt("unset_result called with null result pointer\n");
|
||||
@ -277,8 +280,8 @@ void unset_result(PGresult *oldres)
|
||||
** reset_fetch
|
||||
**
|
||||
*/
|
||||
void reset_fetch()
|
||||
void
|
||||
reset_fetch()
|
||||
{
|
||||
tuple = 0;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ int fetchwithnulls(void *param,...);
|
||||
void on_error_continue();
|
||||
void on_error_stop();
|
||||
PGresult *get_result();
|
||||
void set_result(PGresult *newres);
|
||||
void unset_result(PGresult *oldres);
|
||||
void reset_fetch();
|
||||
void set_result(PGresult *newres);
|
||||
void unset_result(PGresult *oldres);
|
||||
void reset_fetch();
|
||||
|
||||
#define END_OF_TUPLES (-1)
|
||||
|
@ -7,7 +7,7 @@ a modification datetime stamp in a record when that record is UPDATEd.
|
||||
|
||||
Credits
|
||||
This is 95%+ based on autoinc.c, which I used as a starting point as I do
|
||||
not really know what I am doing. I also had help from
|
||||
not really know what I am doing. I also had help from
|
||||
Jan Wieck <jwieck@debis.com> who told me about the datetime_in("now") function.
|
||||
OH, me, I'm Terry Mackintosh <terry@terrym.com>
|
||||
*/
|
||||
@ -17,17 +17,18 @@ OH, me, I'm Terry Mackintosh <terry@terrym.com>
|
||||
|
||||
HeapTuple moddatetime(void);
|
||||
|
||||
HeapTuple moddatetime()
|
||||
HeapTuple
|
||||
moddatetime()
|
||||
{
|
||||
Trigger *trigger; /* to get trigger name */
|
||||
Trigger *trigger; /* to get trigger name */
|
||||
int nargs; /* # of arguments */
|
||||
int attnum; /* positional number of field to change */
|
||||
Datum newdt; /* The current datetime. */
|
||||
char **args; /* arguments */
|
||||
char *relname; /* triggered relation name */
|
||||
Relation rel; /* triggered relation */
|
||||
Datum newdt; /* The current datetime. */
|
||||
char **args; /* arguments */
|
||||
char *relname; /* triggered relation name */
|
||||
Relation rel; /* triggered relation */
|
||||
HeapTuple rettuple = NULL;
|
||||
TupleDesc tupdesc; /* tuple description */
|
||||
TupleDesc tupdesc; /* tuple description */
|
||||
|
||||
if (!CurrentTriggerData)
|
||||
elog(ERROR, "moddatetime: triggers are not initialized.");
|
||||
@ -65,28 +66,31 @@ HeapTuple moddatetime()
|
||||
/* Get the current datetime. */
|
||||
newdt = datetime_in("now");
|
||||
|
||||
/* This gets the position in the turple of the field we want.
|
||||
args[0] being the name of the field to update, as passed in
|
||||
from the trigger.
|
||||
*/
|
||||
/*
|
||||
* This gets the position in the turple of the field we want. args[0]
|
||||
* being the name of the field to update, as passed in from the
|
||||
* trigger.
|
||||
*/
|
||||
attnum = SPI_fnumber(tupdesc, args[0]);
|
||||
|
||||
/* This is were we check to see if the feild we are suppost to update even
|
||||
exits. The above function must return -1 if name not found?
|
||||
*/
|
||||
/*
|
||||
* This is were we check to see if the feild we are suppost to update
|
||||
* even exits. The above function must return -1 if name not found?
|
||||
*/
|
||||
if (attnum < 0)
|
||||
elog(ERROR, "moddatetime (%s): there is no attribute %s", relname,
|
||||
args[0]);
|
||||
|
||||
/* OK, this is where we make sure the datetime field that we are
|
||||
modifying is really a datetime field.
|
||||
Hay, error checking, what a novel idea !-)
|
||||
*/
|
||||
if (SPI_gettypeid(tupdesc, attnum) != DATETIMEOID )
|
||||
args[0]);
|
||||
|
||||
/*
|
||||
* OK, this is where we make sure the datetime field that we are
|
||||
* modifying is really a datetime field. Hay, error checking, what a
|
||||
* novel idea !-)
|
||||
*/
|
||||
if (SPI_gettypeid(tupdesc, attnum) != DATETIMEOID)
|
||||
elog(ERROR, "moddatetime (%s): attribute %s must be of DATETIME type",
|
||||
relname, args[0]);
|
||||
|
||||
/* 1 is the number of items in the arrays attnum and newdt.
|
||||
/* 1 is the number of items in the arrays attnum and newdt.
|
||||
attnum is the positional number of the field to be updated.
|
||||
newdt is the new datetime stamp.
|
||||
NOTE that attnum and newdt are not arrays, but then a 1 ellement array
|
||||
|
@ -1,24 +1,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
char *strtoupper(char *string)
|
||||
char *
|
||||
strtoupper(char *string)
|
||||
{
|
||||
int i ;
|
||||
for (i=0;i<strlen(string);i++)
|
||||
{
|
||||
string[i]=toupper(string[i]);
|
||||
}
|
||||
return string;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
string[i] = toupper(string[i]);
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main ( char argc , char **argv )
|
||||
void
|
||||
main(char argc, char **argv)
|
||||
{
|
||||
char str[250];
|
||||
int sw = 0 ;
|
||||
while ( fgets (str,240,stdin) )
|
||||
{
|
||||
if ( sw == 0 ) printf("%s",strtoupper(str));
|
||||
}
|
||||
char str[250];
|
||||
int sw = 0;
|
||||
|
||||
while (fgets(str, 240, stdin))
|
||||
{
|
||||
if (sw == 0)
|
||||
printf("%s", strtoupper(str));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ check_primary_key()
|
||||
/*
|
||||
* Some checks first...
|
||||
*/
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE,"Check_primary_key Enter Function");
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE, "Check_primary_key Enter Function");
|
||||
#endif
|
||||
/* Called by trigger manager ? */
|
||||
if (!CurrentTriggerData)
|
||||
@ -228,7 +228,7 @@ check_foreign_key()
|
||||
Trigger *trigger; /* to get trigger name */
|
||||
int nargs; /* # of args specified in CREATE TRIGGER */
|
||||
char **args; /* arguments: as described above */
|
||||
char **args_temp ;
|
||||
char **args_temp;
|
||||
int nrefs; /* number of references (== # of plans) */
|
||||
char action; /* 'R'estrict | 'S'etnull | 'C'ascade */
|
||||
int nkeys; /* # of key columns */
|
||||
@ -244,13 +244,15 @@ check_foreign_key()
|
||||
bool isequal = true; /* are keys in both tuples equal (in
|
||||
* UPDATE) */
|
||||
char ident[2 * NAMEDATALEN]; /* to identify myself */
|
||||
int is_update=0;
|
||||
int is_update = 0;
|
||||
int ret;
|
||||
int i,
|
||||
r;
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE,"Check_foreign_key Enter Function");
|
||||
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE, "Check_foreign_key Enter Function");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some checks first...
|
||||
*/
|
||||
@ -275,12 +277,12 @@ check_foreign_key()
|
||||
* key in tg_newtuple is the same as in tg_trigtuple then nothing to
|
||||
* do.
|
||||
*/
|
||||
is_update=0;
|
||||
is_update = 0;
|
||||
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
|
||||
{
|
||||
{
|
||||
newtuple = CurrentTriggerData->tg_newtuple;
|
||||
is_update=1;
|
||||
}
|
||||
is_update = 1;
|
||||
}
|
||||
trigger = CurrentTriggerData->tg_trigger;
|
||||
nargs = trigger->tgnargs;
|
||||
args = trigger->tgargs;
|
||||
@ -288,7 +290,7 @@ check_foreign_key()
|
||||
if (nargs < 5) /* nrefs, action, key, Relation, key - at
|
||||
* least */
|
||||
elog(ERROR, "check_foreign_key: too short %d (< 5) list of arguments", nargs);
|
||||
|
||||
|
||||
nrefs = pg_atoi(args[0], sizeof(int), 0);
|
||||
if (nrefs < 1)
|
||||
elog(ERROR, "check_foreign_key: %d (< 1) number of references specified", nrefs);
|
||||
@ -386,7 +388,7 @@ check_foreign_key()
|
||||
if (plan->nplans <= 0) /* Get typeId of column */
|
||||
argtypes[i] = SPI_gettypeid(tupdesc, fnumber);
|
||||
}
|
||||
args_temp = args;
|
||||
args_temp = args;
|
||||
nargs -= nkeys;
|
||||
args += nkeys;
|
||||
|
||||
@ -397,13 +399,14 @@ check_foreign_key()
|
||||
{
|
||||
void *pplan;
|
||||
char sql[8192];
|
||||
char **args2 = args ;
|
||||
char **args2 = args;
|
||||
|
||||
plan->splan = (void **) malloc(nrefs * sizeof(void *));
|
||||
|
||||
for (r = 0; r < nrefs; r++)
|
||||
{
|
||||
relname = args2[0];
|
||||
|
||||
/*
|
||||
* For 'R'estrict action we construct SELECT query - SELECT 1
|
||||
* FROM _referencing_relation_ WHERE Fkey1 = $1 [AND Fkey2 =
|
||||
@ -417,50 +420,59 @@ check_foreign_key()
|
||||
* For 'C'ascade action we construct DELETE query - DELETE
|
||||
* FROM _referencing_relation_ WHERE Fkey1 = $1 [AND Fkey2 =
|
||||
* $2 [...]] - to delete all referencing tuples.
|
||||
*/
|
||||
/*Max : Cascade with UPDATE query i create update query that
|
||||
updates new key values in referenced tables
|
||||
*/
|
||||
|
||||
|
||||
else if (action == 'c'){
|
||||
if (is_update == 1)
|
||||
{
|
||||
int fn;
|
||||
char *nv;
|
||||
int k ;
|
||||
sprintf(sql, "update %s set ", relname);
|
||||
for (k = 1; k <= nkeys; k++)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Max : Cascade with UPDATE query i create update query that
|
||||
* updates new key values in referenced tables
|
||||
*/
|
||||
|
||||
|
||||
else if (action == 'c')
|
||||
{
|
||||
if (is_update == 1)
|
||||
{
|
||||
int is_char_type =0;
|
||||
char *type;
|
||||
|
||||
fn = SPI_fnumber(tupdesc, args_temp[k-1]);
|
||||
nv = SPI_getvalue(newtuple, tupdesc, fn);
|
||||
type=SPI_gettype(tupdesc,fn);
|
||||
|
||||
if ( (strcmp(type,"text") && strcmp (type,"varchar") &&
|
||||
strcmp(type,"char") && strcmp (type,"bpchar") &&
|
||||
strcmp(type,"date") && strcmp (type,"datetime")) == 0 )
|
||||
is_char_type=1;
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE,"Check_foreign_key Debug value %s type %s %d",
|
||||
nv,type,is_char_type);
|
||||
int fn;
|
||||
char *nv;
|
||||
int k;
|
||||
|
||||
sprintf(sql, "update %s set ", relname);
|
||||
for (k = 1; k <= nkeys; k++)
|
||||
{
|
||||
int is_char_type = 0;
|
||||
char *type;
|
||||
|
||||
fn = SPI_fnumber(tupdesc, args_temp[k - 1]);
|
||||
nv = SPI_getvalue(newtuple, tupdesc, fn);
|
||||
type = SPI_gettype(tupdesc, fn);
|
||||
|
||||
if ((strcmp(type, "text") && strcmp(type, "varchar") &&
|
||||
strcmp(type, "char") && strcmp(type, "bpchar") &&
|
||||
strcmp(type, "date") && strcmp(type, "datetime")) == 0)
|
||||
is_char_type = 1;
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE, "Check_foreign_key Debug value %s type %s %d",
|
||||
nv, type, is_char_type);
|
||||
#endif
|
||||
/* is_char_type =1 i set ' ' for define a new value
|
||||
*/
|
||||
sprintf(sql + strlen(sql), " %s = %s%s%s %s ",
|
||||
args2[k], (is_char_type>0) ? "'" :"" ,
|
||||
nv, (is_char_type >0) ? "'" :"",(k < nkeys) ? ", " : "");
|
||||
is_char_type=0;
|
||||
|
||||
/*
|
||||
* is_char_type =1 i set ' ' for define a new
|
||||
* value
|
||||
*/
|
||||
sprintf(sql + strlen(sql), " %s = %s%s%s %s ",
|
||||
args2[k], (is_char_type > 0) ? "'" : "",
|
||||
nv, (is_char_type > 0) ? "'" : "", (k < nkeys) ? ", " : "");
|
||||
is_char_type = 0;
|
||||
}
|
||||
strcat(sql, " where ");
|
||||
|
||||
}
|
||||
strcat(sql, " where ");
|
||||
|
||||
}
|
||||
else /* DELETE */
|
||||
sprintf(sql, "delete from %s where ", relname);
|
||||
|
||||
}
|
||||
else
|
||||
/* DELETE */
|
||||
sprintf(sql, "delete from %s where ", relname);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* For 'S'etnull action we construct UPDATE query - UPDATE
|
||||
* _referencing_relation_ SET Fkey1 null [, Fkey2 null [...]]
|
||||
@ -500,15 +512,15 @@ check_foreign_key()
|
||||
elog(ERROR, "check_foreign_key: SPI_saveplan returned %d", SPI_result);
|
||||
|
||||
plan->splan[r] = pplan;
|
||||
|
||||
|
||||
args2 += nkeys + 1; /* to the next relation */
|
||||
}
|
||||
plan->nplans = nrefs;
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE,"Check_foreign_key Debug Query is : %s ", sql);
|
||||
#ifdef DEBUG_QUERY
|
||||
elog(NOTICE, "Check_foreign_key Debug Query is : %s ", sql);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If UPDATE and key is not changed ...
|
||||
*/
|
||||
|
@ -352,14 +352,15 @@ c_charin(char *str)
|
||||
{
|
||||
return (string_input(str, 1, 0, NULL));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* end of file */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -14,14 +14,15 @@ char *c_varcharout(char *s);
|
||||
#if 0
|
||||
struct varlena *c_textin(char *str);
|
||||
char *c_char16in(char *str);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@ user_lock(unsigned int id1, unsigned int id2, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
memset(&tag, 0, sizeof(LOCKTAG));
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.relId = 0;
|
||||
tag.tupleId.ip_blkid.bi_hi = id2 >> 16;
|
||||
tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff;
|
||||
@ -44,7 +44,7 @@ user_unlock(unsigned int id1, unsigned int id2, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
memset(&tag, 0, sizeof(LOCKTAG));
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.relId = 0;
|
||||
tag.tupleId.ip_blkid.bi_hi = id2 >> 16;
|
||||
tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff;
|
||||
@ -99,8 +99,8 @@ user_unlock_all()
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -13,8 +13,8 @@ int user_unlock_all(void);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.1 1999/04/10 16:48:05 peter Exp $
|
||||
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.2 1999/05/25 16:06:31 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,177 +25,187 @@
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
int vacuumlo(char *,int);
|
||||
int vacuumlo(char *, int);
|
||||
|
||||
|
||||
/*
|
||||
* This vacuums a database. It returns 1 on success, -1 on failure.
|
||||
*/
|
||||
int vacuumlo(char *database,int verbose)
|
||||
int
|
||||
vacuumlo(char *database, int verbose)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGresult *res, *res2;
|
||||
char buf[BUFSIZE];
|
||||
int matched=0; /* Number matched per scan */
|
||||
int i;
|
||||
|
||||
conn = PQsetdb(NULL, NULL, NULL, NULL, database);
|
||||
|
||||
/* check to see that the backend connection was successfully made */
|
||||
if (PQstatus(conn) == CONNECTION_BAD)
|
||||
{
|
||||
fprintf(stderr, "Connection to database '%s' failed.\n", database);
|
||||
fprintf(stderr, "%s", PQerrorMessage(conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
fprintf(stdout,"Connected to %s\n",database);
|
||||
|
||||
/*
|
||||
* First we create and populate the lo temp table
|
||||
*/
|
||||
buf[0]='\0';
|
||||
strcat(buf,"SELECT oid AS lo ");
|
||||
strcat(buf,"INTO TEMP TABLE vacuum_l ");
|
||||
strcat(buf,"FROM pg_class ");
|
||||
strcat(buf,"WHERE relkind='l'");
|
||||
if(!(res = PQexec(conn,buf))) {
|
||||
fprintf(stderr,"Failed to create temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* Now find any candidate tables who have columns of type oid (the column
|
||||
* oid is ignored, as it has attnum < 1)
|
||||
*/
|
||||
buf[0]='\0';
|
||||
strcat(buf,"SELECT c.relname, a.attname ");
|
||||
strcat(buf,"FROM pg_class c, pg_attribute a, pg_type t ");
|
||||
strcat(buf,"WHERE a.attnum > 0 ");
|
||||
strcat(buf," AND a.attrelid = c.oid ");
|
||||
strcat(buf," AND a.atttypid = t.oid ");
|
||||
strcat(buf," AND t.typname = 'oid' ");
|
||||
strcat(buf," AND c.relname NOT LIKE 'pg_%'");
|
||||
if(!(res = PQexec(conn,buf))) {
|
||||
fprintf(stderr,"Failed to create temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
for(i=0;i<PQntuples(res);i++)
|
||||
{
|
||||
char *table,*field;
|
||||
|
||||
table = PQgetvalue(res,i,0);
|
||||
field = PQgetvalue(res,i,1);
|
||||
|
||||
if(verbose) {
|
||||
fprintf(stdout,"Checking %s in %s: ",field,table);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
res2 = PQexec(conn, "begin");
|
||||
PQclear(res2);
|
||||
|
||||
buf[0] = '\0';
|
||||
strcat(buf,"DELETE FROM vacuum_l ");
|
||||
strcat(buf,"WHERE lo IN (");
|
||||
strcat(buf,"SELECT ");
|
||||
strcat(buf,field);
|
||||
strcat(buf," FROM ");
|
||||
strcat(buf,table);
|
||||
strcat(buf,");");
|
||||
if(!(res2 = PQexec(conn,buf))) {
|
||||
fprintf(stderr,"Failed to check %s in table %s\n",field,table);
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
if(PQresultStatus(res2)!=PGRES_COMMAND_OK) {
|
||||
fprintf(stderr,
|
||||
"Failed to check %s in table %s\n%s\n",
|
||||
field,table,
|
||||
PQerrorMessage(conn)
|
||||
);
|
||||
PQclear(res2);
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
PQclear(res2);
|
||||
PGconn *conn;
|
||||
PGresult *res,
|
||||
*res2;
|
||||
char buf[BUFSIZE];
|
||||
int matched = 0; /* Number matched per scan */
|
||||
int i;
|
||||
|
||||
res2 = PQexec(conn, "end");
|
||||
PQclear(res2);
|
||||
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/* Start the transaction */
|
||||
res = PQexec(conn, "begin");
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* Finally, those entries remaining in vacuum_l are orphans.
|
||||
*/
|
||||
buf[0]='\0';
|
||||
strcat(buf,"SELECT lo ");
|
||||
strcat(buf,"FROM vacuum_l");
|
||||
if(!(res = PQexec(conn,buf))) {
|
||||
fprintf(stderr,"Failed to read temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
matched=PQntuples(res);
|
||||
for(i=0;i<matched;i++)
|
||||
conn = PQsetdb(NULL, NULL, NULL, NULL, database);
|
||||
|
||||
/* check to see that the backend connection was successfully made */
|
||||
if (PQstatus(conn) == CONNECTION_BAD)
|
||||
{
|
||||
Oid lo = (Oid) atoi(PQgetvalue(res,i,0));
|
||||
|
||||
if(verbose) {
|
||||
fprintf(stdout,"\rRemoving lo %6d \n",lo);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if(lo_unlink(conn,lo)<0) {
|
||||
fprintf(stderr,"Failed to remove lo %d\n",lo);
|
||||
}
|
||||
fprintf(stderr, "Connection to database '%s' failed.\n", database);
|
||||
fprintf(stderr, "%s", PQerrorMessage(conn));
|
||||
return -1;
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* That's all folks!
|
||||
*/
|
||||
res = PQexec(conn, "end");
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
|
||||
if(verbose)
|
||||
fprintf(stdout,"\rRemoved %d large objects from %s.\n",matched,database);
|
||||
|
||||
return 0;
|
||||
|
||||
if (verbose)
|
||||
fprintf(stdout, "Connected to %s\n", database);
|
||||
|
||||
/*
|
||||
* First we create and populate the lo temp table
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "SELECT oid AS lo ");
|
||||
strcat(buf, "INTO TEMP TABLE vacuum_l ");
|
||||
strcat(buf, "FROM pg_class ");
|
||||
strcat(buf, "WHERE relkind='l'");
|
||||
if (!(res = PQexec(conn, buf)))
|
||||
{
|
||||
fprintf(stderr, "Failed to create temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* Now find any candidate tables who have columns of type oid (the
|
||||
* column oid is ignored, as it has attnum < 1)
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "SELECT c.relname, a.attname ");
|
||||
strcat(buf, "FROM pg_class c, pg_attribute a, pg_type t ");
|
||||
strcat(buf, "WHERE a.attnum > 0 ");
|
||||
strcat(buf, " AND a.attrelid = c.oid ");
|
||||
strcat(buf, " AND a.atttypid = t.oid ");
|
||||
strcat(buf, " AND t.typname = 'oid' ");
|
||||
strcat(buf, " AND c.relname NOT LIKE 'pg_%'");
|
||||
if (!(res = PQexec(conn, buf)))
|
||||
{
|
||||
fprintf(stderr, "Failed to create temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
char *table,
|
||||
*field;
|
||||
|
||||
table = PQgetvalue(res, i, 0);
|
||||
field = PQgetvalue(res, i, 1);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
fprintf(stdout, "Checking %s in %s: ", field, table);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
res2 = PQexec(conn, "begin");
|
||||
PQclear(res2);
|
||||
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "DELETE FROM vacuum_l ");
|
||||
strcat(buf, "WHERE lo IN (");
|
||||
strcat(buf, "SELECT ");
|
||||
strcat(buf, field);
|
||||
strcat(buf, " FROM ");
|
||||
strcat(buf, table);
|
||||
strcat(buf, ");");
|
||||
if (!(res2 = PQexec(conn, buf)))
|
||||
{
|
||||
fprintf(stderr, "Failed to check %s in table %s\n", field, table);
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
if (PQresultStatus(res2) != PGRES_COMMAND_OK)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Failed to check %s in table %s\n%s\n",
|
||||
field, table,
|
||||
PQerrorMessage(conn)
|
||||
);
|
||||
PQclear(res2);
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
PQclear(res2);
|
||||
|
||||
res2 = PQexec(conn, "end");
|
||||
PQclear(res2);
|
||||
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/* Start the transaction */
|
||||
res = PQexec(conn, "begin");
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* Finally, those entries remaining in vacuum_l are orphans.
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "SELECT lo ");
|
||||
strcat(buf, "FROM vacuum_l");
|
||||
if (!(res = PQexec(conn, buf)))
|
||||
{
|
||||
fprintf(stderr, "Failed to read temp table.\n");
|
||||
PQfinish(conn);
|
||||
return -1;
|
||||
}
|
||||
matched = PQntuples(res);
|
||||
for (i = 0; i < matched; i++)
|
||||
{
|
||||
Oid lo = (Oid) atoi(PQgetvalue(res, i, 0));
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
fprintf(stdout, "\rRemoving lo %6d \n", lo);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (lo_unlink(conn, lo) < 0)
|
||||
fprintf(stderr, "Failed to remove lo %d\n", lo);
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
/*
|
||||
* That's all folks!
|
||||
*/
|
||||
res = PQexec(conn, "end");
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stdout, "\rRemoved %d large objects from %s.\n", matched, database);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int verbose = 0;
|
||||
int arg;
|
||||
int rc=0;
|
||||
|
||||
if (argc < 2)
|
||||
int verbose = 0;
|
||||
int arg;
|
||||
int rc = 0;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-v] database_name [db2 ... dbn]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
fprintf(stderr, "Usage: %s [-v] database_name [db2 ... dbn]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(arg=1;arg<argc;arg++) {
|
||||
if(strcmp("-v",argv[arg])==0)
|
||||
verbose=!verbose;
|
||||
else
|
||||
rc += vacuumlo(argv[arg],verbose);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
for (arg = 1; arg < argc; arg++)
|
||||
{
|
||||
if (strcmp("-v", argv[arg]) == 0)
|
||||
verbose = !verbose;
|
||||
else
|
||||
rc += vacuumlo(argv[arg], verbose);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user