postgresql/contrib/pg_dumplo/lo_export.c

220 lines
5.2 KiB
C
Raw Normal View History

/* -------------------------------------------------------------------------
* pg_dumplo
*
2004-11-29 07:49:49 +08:00
* $PostgreSQL: pgsql/contrib/pg_dumplo/lo_export.c,v 1.13 2004/11/28 23:49:49 tgl Exp $
*
2004-11-29 07:49:49 +08:00
* Karel Zak 1999-2004
* -------------------------------------------------------------------------
*/
2000-06-16 03:05:22 +08:00
#include "postgres_fe.h"
2000-06-16 03:05:22 +08:00
#include <fcntl.h>
2001-03-22 12:01:46 +08:00
#include <errno.h>
2000-06-16 03:05:22 +08:00
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
2000-06-16 03:05:22 +08:00
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
2000-06-16 03:05:22 +08:00
#include "pg_dumplo.h"
2001-03-22 12:01:46 +08:00
extern int errno;
2000-06-16 03:05:22 +08:00
2001-03-22 12:01:46 +08:00
void
load_lolist(LODumpMaster * pgLO)
2000-06-16 03:05:22 +08:00
{
2001-03-22 12:01:46 +08:00
LOlist *ll;
int i;
int n;
2004-11-29 07:49:49 +08:00
/*
* Now find any candidate tables who have columns of type oid.
*
* NOTE: System tables including pg_largeobject will be ignored.
* Otherwise we'd end up dumping all LOs, referenced or not.
*
* NOTE: the system oid column is ignored, as it has attnum < 1. This
* shouldn't matter for correctness, but it saves time.
2001-03-22 12:01:46 +08:00
*/
2004-11-29 07:49:49 +08:00
pgLO->res = PQexec(pgLO->conn, "SELECT c.relname, a.attname, n.nspname "
"FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a, "
" pg_catalog.pg_type t, pg_catalog.pg_namespace n "
"WHERE a.attnum > 0 "
" AND a.attrelid = c.oid "
" AND a.atttypid = t.oid "
" AND t.typname = 'oid' "
" AND c.relkind = 'r' "
2004-11-29 07:49:49 +08:00
" AND c.relname NOT LIKE 'pg_%' "
" AND n.oid = c.relnamespace");
2001-03-22 12:01:46 +08:00
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn));
exit(RE_ERROR);
}
2001-03-22 12:01:46 +08:00
if ((n = PQntuples(pgLO->res)) == 0)
{
fprintf(stderr, "%s: No OID columns in the database.\n", progname);
2000-06-16 03:05:22 +08:00
exit(RE_ERROR);
2001-03-22 12:01:46 +08:00
}
2000-06-16 03:05:22 +08:00
pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist));
2004-11-29 07:49:49 +08:00
memset(pgLO->lolist, 0, (n + 1) * sizeof(LOlist));
2001-03-22 12:01:46 +08:00
if (!pgLO->lolist)
{
2000-06-16 03:05:22 +08:00
fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR);
2001-03-22 12:01:46 +08:00
}
for (i = 0, ll = pgLO->lolist; i < n; i++, ll++)
{
2000-06-16 03:05:22 +08:00
ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
2001-03-22 12:01:46 +08:00
ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
2004-11-29 07:49:49 +08:00
ll->lo_schema = strdup(PQgetvalue(pgLO->res, i, 2));
2000-06-16 03:05:22 +08:00
}
2001-03-22 12:01:46 +08:00
2000-06-16 03:05:22 +08:00
PQclear(pgLO->res);
}
2001-03-22 12:01:46 +08:00
void
pglo_export(LODumpMaster * pgLO)
2000-06-16 03:05:22 +08:00
{
2001-03-22 12:01:46 +08:00
LOlist *ll;
int tuples;
2000-06-16 03:05:22 +08:00
char path[BUFSIZ],
2001-03-22 12:01:46 +08:00
Qbuff[QUERY_BUFSIZ];
if (pgLO->action != ACTION_SHOW)
{
time_t t;
2000-06-16 03:05:22 +08:00
time(&t);
fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n");
fprintf(pgLO->index, "#\tDate: %s", ctime(&t));
fprintf(pgLO->index, "#\tHost: %s\n", pgLO->host);
fprintf(pgLO->index, "#\tDatabase: %s\n", pgLO->db);
fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user);
2004-11-29 07:49:49 +08:00
fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\tschema\n#\n");
2000-06-16 03:05:22 +08:00
}
2001-03-22 12:01:46 +08:00
2000-06-16 03:05:22 +08:00
pgLO->counter = 0;
2001-03-22 12:01:46 +08:00
for (ll = pgLO->lolist; ll->lo_table != NULL; ll++)
{
/*
* Query: find the LOs referenced by this column
2000-06-16 03:05:22 +08:00
*/
snprintf(Qbuff, QUERY_BUFSIZ,
2004-11-29 07:49:49 +08:00
"SELECT DISTINCT l.loid FROM \"%s\".\"%s\" x, pg_catalog.pg_largeobject l "
"WHERE x.\"%s\" = l.loid",
ll->lo_schema, ll->lo_table, ll->lo_attr);
2001-03-22 12:01:46 +08:00
2000-06-16 03:05:22 +08:00
/* puts(Qbuff); */
2001-03-22 12:01:46 +08:00
2000-06-16 03:05:22 +08:00
pgLO->res = PQexec(pgLO->conn, Qbuff);
2001-03-22 12:01:46 +08:00
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn));
2001-03-22 12:01:46 +08:00
}
else if ((tuples = PQntuples(pgLO->res)) == 0)
{
2000-06-16 03:05:22 +08:00
if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
2004-11-29 07:49:49 +08:00
printf("%s: no large objects in \"%s\".\"%s\".\"%s\"\n",
progname, ll->lo_schema, ll->lo_table, ll->lo_attr);
2001-03-22 12:01:46 +08:00
}
else
{
int t;
char *val;
/*
2000-06-16 03:05:22 +08:00
* Create DIR/FILE
*/
2001-03-22 12:01:46 +08:00
if (pgLO->action != ACTION_SHOW)
{
snprintf(path, BUFSIZ, "%s/%s/%s", pgLO->space, pgLO->db,
2004-11-29 07:49:49 +08:00
ll->lo_schema);
2000-06-16 03:05:22 +08:00
2001-03-22 12:01:46 +08:00
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
2000-06-16 03:05:22 +08:00
perror(path);
2001-03-22 12:01:46 +08:00
exit(RE_ERROR);
}
2000-06-16 03:05:22 +08:00
}
2004-11-29 07:49:49 +08:00
snprintf(path, BUFSIZ, "%s/%s/%s/%s", pgLO->space, pgLO->db,
2004-11-29 07:49:49 +08:00
ll->lo_schema, ll->lo_table);
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_schema, ll->lo_table, ll->lo_attr);
2001-03-22 12:01:46 +08:00
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
2000-06-16 03:05:22 +08:00
perror(path);
2001-03-22 12:01:46 +08:00
exit(RE_ERROR);
}
2000-06-16 03:05:22 +08:00
}
2001-03-22 12:01:46 +08:00
2000-06-16 03:05:22 +08:00
if (!pgLO->quiet)
2004-11-29 07:49:49 +08:00
printf("dump %s.%s.%s (%d large obj)\n",
ll->lo_schema, ll->lo_table, ll->lo_attr, tuples);
2000-06-16 03:05:22 +08:00
}
pgLO->counter += tuples;
2001-03-22 12:01:46 +08:00
for (t = 0; t < tuples; t++)
{
Oid lo;
2000-06-16 03:05:22 +08:00
val = PQgetvalue(pgLO->res, t, 0);
2001-03-22 12:01:46 +08:00
lo = atooid(val);
2001-03-22 12:01:46 +08:00
if (pgLO->action == ACTION_SHOW)
{
2004-11-29 07:49:49 +08:00
printf("%s.%s.%s: %u\n", ll->lo_schema, ll->lo_table, ll->lo_attr, lo);
2000-06-16 03:05:22 +08:00
continue;
}
2001-03-22 12:01:46 +08:00
2004-11-29 07:49:49 +08:00
snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s/%s", pgLO->space,
pgLO->db, ll->lo_schema, ll->lo_table, ll->lo_attr, val);
2001-03-22 12:01:46 +08:00
if (lo_export(pgLO->conn, lo, path) < 0)
fprintf(stderr, "%s: lo_export failed:\n%s", progname,
PQerrorMessage(pgLO->conn));
2001-03-22 12:01:46 +08:00
else
2004-11-29 07:49:49 +08:00
fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s/%s\t%s\n",
val, ll->lo_table, ll->lo_attr, pgLO->db,
ll->lo_schema, ll->lo_table, ll->lo_attr,
val, ll->lo_schema);
2000-06-16 03:05:22 +08:00
}
}
PQclear(pgLO->res);
}
}