00001
00002
00003
00004
00005
00006
00007
00008 #include "postgres_fe.h"
00009
00010 #include "libpq-fe.h"
00011 #include "pqexpbuffer.h"
00012
00013
00014 int
00015 main(int argc, char **argv)
00016 {
00017 PGconn *conn;
00018 PQExpBufferData sql;
00019 PGresult *res;
00020 PGresult *pkrel_res;
00021 PGresult *fkrel_res;
00022 char *fk_relname;
00023 char *fk_nspname;
00024 char *fk_attname;
00025 char *pk_relname;
00026 char *pk_nspname;
00027 int fk,
00028 pk;
00029
00030 if (argc != 2)
00031 {
00032 fprintf(stderr, "Usage: %s database\n", argv[0]);
00033 exit(EXIT_FAILURE);
00034 }
00035
00036 initPQExpBuffer(&sql);
00037
00038 appendPQExpBuffer(&sql, "dbname=%s", argv[1]);
00039
00040 conn = PQconnectdb(sql.data);
00041 if (PQstatus(conn) == CONNECTION_BAD)
00042 {
00043 fprintf(stderr, "connection error: %s\n", PQerrorMessage(conn));
00044 exit(EXIT_FAILURE);
00045 }
00046
00047
00048
00049 printfPQExpBuffer(&sql, "%s",
00050 "SET search_path = public;"
00051 "SELECT c.relname, (SELECT nspname FROM "
00052 "pg_catalog.pg_namespace n WHERE n.oid = c.relnamespace) AS nspname "
00053 "FROM pg_catalog.pg_class c "
00054 "WHERE c.relkind = 'r' "
00055 "AND c.relhasoids "
00056 "ORDER BY nspname, c.relname"
00057 );
00058
00059 res = PQexec(conn, sql.data);
00060 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
00061 {
00062 fprintf(stderr, "sql error: %s\n", PQerrorMessage(conn));
00063 exit(EXIT_FAILURE);
00064 }
00065 pkrel_res = res;
00066
00067
00068
00069 printfPQExpBuffer(&sql, "%s",
00070 "SELECT c.relname, "
00071 "(SELECT nspname FROM pg_catalog.pg_namespace n WHERE n.oid = c.relnamespace) AS nspname, "
00072 "a.attname "
00073 "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
00074 "WHERE a.attnum > 0 AND c.relkind = 'r' "
00075 "AND a.attrelid = c.oid "
00076 "AND a.atttypid IN ('pg_catalog.oid'::regtype, "
00077 " 'pg_catalog.regclass'::regtype, "
00078 " 'pg_catalog.regoper'::regtype, "
00079 " 'pg_catalog.regoperator'::regtype, "
00080 " 'pg_catalog.regproc'::regtype, "
00081 " 'pg_catalog.regprocedure'::regtype, "
00082 " 'pg_catalog.regtype'::regtype, "
00083 " 'pg_catalog.regconfig'::regtype, "
00084 " 'pg_catalog.regdictionary'::regtype) "
00085 "ORDER BY nspname, c.relname, a.attnum"
00086 );
00087
00088 res = PQexec(conn, sql.data);
00089 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
00090 {
00091 fprintf(stderr, "sql error: %s\n", PQerrorMessage(conn));
00092 exit(EXIT_FAILURE);
00093 }
00094 fkrel_res = res;
00095
00096
00097
00098
00099
00100
00101 for (fk = 0; fk < PQntuples(fkrel_res); fk++)
00102 {
00103 fk_relname = PQgetvalue(fkrel_res, fk, 0);
00104 fk_nspname = PQgetvalue(fkrel_res, fk, 1);
00105 fk_attname = PQgetvalue(fkrel_res, fk, 2);
00106
00107 for (pk = 0; pk < PQntuples(pkrel_res); pk++)
00108 {
00109 pk_relname = PQgetvalue(pkrel_res, pk, 0);
00110 pk_nspname = PQgetvalue(pkrel_res, pk, 1);
00111
00112 printfPQExpBuffer(&sql,
00113 "SELECT 1 "
00114 "FROM \"%s\".\"%s\" t1, "
00115 "\"%s\".\"%s\" t2 "
00116 "WHERE t1.\"%s\"::pg_catalog.oid = t2.oid "
00117 "LIMIT 1",
00118 fk_nspname, fk_relname,
00119 pk_nspname, pk_relname,
00120 fk_attname);
00121
00122 res = PQexec(conn, sql.data);
00123 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
00124 {
00125 fprintf(stderr, "sql error: %s\n", PQerrorMessage(conn));
00126 exit(EXIT_FAILURE);
00127 }
00128
00129 if (PQntuples(res) != 0)
00130 printf("Join %s.%s.%s => %s.%s.oid\n",
00131 fk_nspname, fk_relname, fk_attname,
00132 pk_nspname, pk_relname);
00133
00134 PQclear(res);
00135 }
00136 }
00137
00138 PQclear(fkrel_res);
00139
00140
00141
00142
00143
00144 printfPQExpBuffer(&sql, "%s",
00145 "SELECT c.relname, "
00146 "(SELECT nspname FROM pg_catalog.pg_namespace n WHERE n.oid = c.relnamespace) AS nspname, "
00147 "a.attname "
00148 "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a "
00149 "WHERE a.attnum > 0 AND c.relkind = 'r' "
00150 "AND a.attrelid = c.oid "
00151 "AND a.atttypid IN ('pg_catalog.oid[]'::regtype, "
00152 " 'pg_catalog.regclass[]'::regtype, "
00153 " 'pg_catalog.regoper[]'::regtype, "
00154 " 'pg_catalog.regoperator[]'::regtype, "
00155 " 'pg_catalog.regproc[]'::regtype, "
00156 " 'pg_catalog.regprocedure[]'::regtype, "
00157 " 'pg_catalog.regtype[]'::regtype, "
00158 " 'pg_catalog.regconfig[]'::regtype, "
00159 " 'pg_catalog.regdictionary[]'::regtype) "
00160 "ORDER BY nspname, c.relname, a.attnum"
00161 );
00162
00163 res = PQexec(conn, sql.data);
00164 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
00165 {
00166 fprintf(stderr, "sql error: %s\n", PQerrorMessage(conn));
00167 exit(EXIT_FAILURE);
00168 }
00169 fkrel_res = res;
00170
00171
00172
00173
00174
00175
00176 for (fk = 0; fk < PQntuples(fkrel_res); fk++)
00177 {
00178 fk_relname = PQgetvalue(fkrel_res, fk, 0);
00179 fk_nspname = PQgetvalue(fkrel_res, fk, 1);
00180 fk_attname = PQgetvalue(fkrel_res, fk, 2);
00181
00182 for (pk = 0; pk < PQntuples(pkrel_res); pk++)
00183 {
00184 pk_relname = PQgetvalue(pkrel_res, pk, 0);
00185 pk_nspname = PQgetvalue(pkrel_res, pk, 1);
00186
00187 printfPQExpBuffer(&sql,
00188 "SELECT 1 "
00189 "FROM \"%s\".\"%s\" t1, "
00190 "\"%s\".\"%s\" t2 "
00191 "WHERE t2.oid = ANY(t1.\"%s\")"
00192 "LIMIT 1",
00193 fk_nspname, fk_relname,
00194 pk_nspname, pk_relname,
00195 fk_attname);
00196
00197 res = PQexec(conn, sql.data);
00198 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
00199 {
00200 fprintf(stderr, "sql error: %s\n", PQerrorMessage(conn));
00201 exit(EXIT_FAILURE);
00202 }
00203
00204 if (PQntuples(res) != 0)
00205 printf("Join %s.%s.%s []=> %s.%s.oid\n",
00206 fk_nspname, fk_relname, fk_attname,
00207 pk_nspname, pk_relname);
00208
00209 PQclear(res);
00210 }
00211 }
00212
00213 PQclear(fkrel_res);
00214
00215 PQclear(pkrel_res);
00216
00217 PQfinish(conn);
00218
00219 termPQExpBuffer(&sql);
00220
00221 exit(EXIT_SUCCESS);
00222 }