New findoidjoins examines oid columns to find join relationships.

This commit is contained in:
Bruce Momjian 1998-08-11 02:32:00 +00:00
parent ffb120ecc6
commit 85c165cd4c
8 changed files with 1284 additions and 1 deletions

View File

@ -18,6 +18,11 @@ earthdistance -
Operator for computing earth distance for two points Operator for computing earth distance for two points
by Hal Snyder <hal@vailsys.com> by Hal Snyder <hal@vailsys.com>
findoidjoins -
Finds the joins used by oid columns by examining the actual
values in the oid columns and row oids.
by Bruce Momjian <root@candle.pha.pa.us>
fulltextindex - fulltextindex -
Full text indexing using triggers Full text indexing using triggers
by Maarten Boekhold <maartenb@dutepp0.et.tudelft.nl> by Maarten Boekhold <maartenb@dutepp0.et.tudelft.nl>

View File

@ -0,0 +1,20 @@
#
# Makefile, requires pgsql/contrib/pginterface
#
#
PGINTERFACE = pginterface.o halt.o # these have to be in your library search path
TARGET = findoidjoins
CFLAGS = -g -Wall -I. -I../../src/interfaces/libpq -I/usr/local/pgsql/include
LDFLAGS = -L/usr/local/pgsql/lib -lpq
all : $(TARGET)
findoidjoins: $(PGINTERFACE) findoidjoins.c
gcc -o $@ $(CFLAGS) $@.c $(PGINTERFACE) $(LDFLAGS)
clean:
rm -f *.o $(TARGET) log core
install:
install -s -o bin -g bin $(TARGET) /usr/local/pgsql/bin

View File

@ -0,0 +1,68 @@
findoidjoins
This program scans the a database, and prints oid fields, and the tables
they join to. PostgreSQL version 6.3.2 crashes with aggregates on
views, so I have removed the view pg_user from the list of relations to
examine.
Run on am empty database, it returns the system join relationships:
---------------------------------------------------------------------------
Join pg_aggregate.aggfinaltype => pg_proc.oid
Join pg_aggregate.aggfinaltype => pg_type.oid
Join pg_aggregate.aggowner => pg_proc.oid
Join pg_aggregate.aggbasetype => pg_proc.oid
Join pg_aggregate.aggbasetype => pg_type.oid
Join pg_aggregate.aggtranstype1 => pg_proc.oid
Join pg_aggregate.aggtranstype1 => pg_type.oid
Join pg_aggregate.aggtranstype2 => pg_type.oid
Join pg_am.amowner => pg_proc.oid
Join pg_amop.amopid => pg_am.oid
Join pg_amop.amopopr => pg_operator.oid
Join pg_amop.amopclaid => pg_opclass.oid
Join pg_amproc.amproc => pg_operator.oid
Join pg_amproc.amproc => pg_proc.oid
Join pg_amproc.amopclaid => pg_opclass.oid
Join pg_amproc.amopclaid => pg_operator.oid
Join pg_amproc.amopclaid => pg_proc.oid
Join pg_amproc.amid => pg_am.oid
Join pg_attribute.attrelid => pg_class.oid
Join pg_attribute.atttypid => pg_type.oid
Join pg_class.relam => pg_am.oid
Join pg_class.reltype => pg_type.oid
Join pg_class.relowner => pg_proc.oid
Join pg_description.objoid => pg_proc.oid
Join pg_description.objoid => pg_type.oid
Join pg_index.indexrelid => pg_class.oid
Join pg_index.indrelid => pg_class.oid
Join pg_index.indproc => pg_proc.oid
Join pg_opclass.opcdeftype => pg_type.oid
Join pg_operator.oprcom => pg_operator.oid
Join pg_operator.oprrsortop => pg_operator.oid
Join pg_operator.oprlsortop => pg_operator.oid
Join pg_operator.oprnegate => pg_operator.oid
Join pg_operator.oprresult => pg_type.oid
Join pg_operator.oprright => pg_type.oid
Join pg_operator.oprleft => pg_type.oid
Join pg_operator.oprowner => pg_proc.oid
Join pg_parg.partype => pg_type.oid
Join pg_parg.parproid => pg_operator.oid
Join pg_parg.parproid => pg_proc.oid
Join pg_proc.prolang => pg_language.oid
Join pg_proc.prorettype => pg_type.oid
Join pg_proc.proowner => pg_proc.oid
Join pg_rewrite.ev_class => pg_class.oid
Join pg_statistic.starelid => pg_class.oid
Join pg_type.typrelid => pg_class.oid
Join pg_type.typowner => pg_proc.oid
Join pg_type.typelem => pg_operator.oid
Join pg_type.typelem => pg_proc.oid
Join pg_type.typelem => pg_type.oid
---------------------------------------------------------------------------
Bruce Momjian (root@candle.pha.pa.us)

View File

@ -0,0 +1,93 @@
/*
* findoidjoins.c, required pgsql/contrib/pginterface
*
*/
#include <stdio.h>
#include "halt.h"
#include <libpq-fe.h>
#include "pginterface.h"
PGresult *attres, *relres;
int
main(int argc, char **argv)
{
char query[4000];
char relname[256];
char relname2[256];
char attname[256];
int count;
if (argc != 2)
halt("Usage: %s database\n", argv[0]);
connectdb(argv[1], NULL, NULL, NULL, NULL);
on_error_continue();
on_error_stop();
doquery("BEGIN WORK");
doquery("\
DECLARE c_attributes BINARY CURSOR FOR \
SELECT relname, a.attname \
FROM pg_class c, pg_attribute a, pg_type t \
WHERE a.attnum > 0 AND \
relkind = 'r' AND \
typname = 'oid' AND \
a.attrelid = c.oid AND \
a.atttypid = t.oid \
ORDER BY 1; \
");
doquery("FETCH ALL IN c_attributes");
attres = get_result();
doquery("\
DECLARE c_relations BINARY CURSOR FOR \
SELECT relname \
FROM pg_class c \
WHERE relkind = 'r' AND \
relname != 'pg_user' \
ORDER BY 1; \
");
doquery("FETCH ALL IN c_relations");
relres = get_result();
set_result(attres);
while (fetch(relname, attname) != END_OF_TUPLES)
{
set_result(relres);
reset_fetch();
while (fetch(relname2) != END_OF_TUPLES)
{
unset_result(relres);
sprintf(query,"\
DECLARE c_matches BINARY CURSOR FOR \
SELECT count(*)
FROM %s t1, %s t2 \
WHERE t1.%s = t2.oid", relname, relname2, attname);
doquery(query);
doquery("FETCH ALL IN c_matches");
fetch(&count);
if (count != 0)
printf("Join %s.%s => %s.oid\n", relname, attname, relname2);
doquery("CLOSE c_matches");
set_result(relres);
}
set_result(attres);
}
set_result(relres);
doquery("CLOSE c_relations");
PQclear(relres);
set_result(attres);
doquery("CLOSE c_attributes");
PQclear(attres);
unset_result(attres);
doquery("COMMIT WORK");
disconnectdb();
return 0;
}

View File

@ -22,6 +22,11 @@ useful if you are running the query engine on a system with a different
architecture than the database server. If you pass a NULL pointer, the architecture than the database server. If you pass a NULL pointer, the
column is skipped, and you can use libpq to handle it as you wish. column is skipped, and you can use libpq to handle it as you wish.
There are two functions, get_result() and set_result, that allow you to
handle multiple result sets at the same time.
There is a reset_fetch() that starts the fetch back at the beginning.
There is a demo program called pginsert that demonstrates how the There is a demo program called pginsert that demonstrates how the
library can be used. library can be used.

View File

@ -22,6 +22,9 @@ static PGresult *res = NULL;
static int on_error_state = ON_ERROR_STOP; static int on_error_state = ON_ERROR_STOP;
static in_result_block = false;
static was_get_unset_result = false;
/* LOCAL VARIABLES */ /* LOCAL VARIABLES */
static int tuple; static int tuple;
@ -64,9 +67,10 @@ disconnectdb()
PGresult * PGresult *
doquery(char *query) doquery(char *query)
{ {
if (res != NULL) if (res != NULL && in_result_block == false && was_get_unset_result == false)
PQclear(res); PQclear(res);
was_get_unset_result = false;
res = PQexec(conn, query); res = PQexec(conn, query);
if (on_error_state == ON_ERROR_STOP && if (on_error_state == ON_ERROR_STOP &&
@ -187,3 +191,69 @@ on_error_continue()
{ {
on_error_state = ON_ERROR_CONTINUE; on_error_state = ON_ERROR_CONTINUE;
} }
/*
**
** get_result
**
*/
PGresult *get_result()
{
was_get_unset_result = true;
/* we have to store the fetch location somewhere */
memcpy(&res->cmdStatus[CMDSTATUS_LEN-sizeof(tuple)],&tuple, sizeof(tuple));
return res;
}
/*
**
** set_result
**
*/
void set_result(PGresult *newres)
{
if (newres == NULL)
halt("set_result called with null result pointer\n");
if (res != NULL && was_get_unset_result == false)
if (in_result_block == false)
PQclear(res);
else
memcpy(&res->cmdStatus[CMDSTATUS_LEN-sizeof(tuple)], &tuple, sizeof(tuple));
in_result_block = true;
was_get_unset_result = false;
memcpy(&tuple, &newres->cmdStatus[CMDSTATUS_LEN-sizeof(tuple)], sizeof(tuple));
res = newres;
}
/*
**
** unset_result
**
*/
void unset_result(PGresult *oldres)
{
if (oldres == NULL)
halt("unset_result called with null result pointer\n");
if (in_result_block == false)
halt("Unset of result without being set.\n");
was_get_unset_result = true;
memcpy(&oldres->cmdStatus[CMDSTATUS_LEN-sizeof(tuple)], &tuple, sizeof(tuple));
in_result_block = false;
}
/*
**
** reset_fetch
**
*/
void reset_fetch()
{
tuple = 0;
}

View File

@ -10,5 +10,9 @@ int fetch(void *param,...);
int fetchwithnulls(void *param,...); int fetchwithnulls(void *param,...);
void on_error_continue(); void on_error_continue();
void on_error_stop(); void on_error_stop();
PGresult *get_result();
void set_result(PGresult *newres);
void unset_result(PGresult *oldres);
void reset_fetch();
#define END_OF_TUPLES (-1) #define END_OF_TUPLES (-1)

1018
doc/src/graphics/catalogs.ps Normal file

File diff suppressed because it is too large Load Diff