diff --git a/contrib/pg_dumplo/lo_export.c b/contrib/pg_dumplo/lo_export.c index aa007083b3..ec3799ed84 100644 --- a/contrib/pg_dumplo/lo_export.c +++ b/contrib/pg_dumplo/lo_export.c @@ -1,9 +1,9 @@ /* ------------------------------------------------------------------------- * pg_dumplo * - * $PostgreSQL: pgsql/contrib/pg_dumplo/lo_export.c,v 1.12 2003/11/29 19:51:35 pgsql Exp $ + * $PostgreSQL: pgsql/contrib/pg_dumplo/lo_export.c,v 1.13 2004/11/28 23:49:49 tgl Exp $ * - * Karel Zak 1999-2000 + * Karel Zak 1999-2004 * ------------------------------------------------------------------------- */ @@ -29,7 +29,7 @@ load_lolist(LODumpMaster * pgLO) LOlist *ll; int i; int n; - + /* * Now find any candidate tables who have columns of type oid. * @@ -39,15 +39,16 @@ load_lolist(LODumpMaster * pgLO) * NOTE: the system oid column is ignored, as it has attnum < 1. This * shouldn't matter for correctness, but it saves time. */ - pgLO->res = PQexec(pgLO->conn, - "SELECT c.relname, a.attname " - "FROM pg_class c, pg_attribute a, pg_type t " + 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' " - " AND c.relname NOT LIKE 'pg_%'"); + " AND c.relname NOT LIKE 'pg_%' " + " AND n.oid = c.relnamespace"); if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) { @@ -63,6 +64,7 @@ load_lolist(LODumpMaster * pgLO) } pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist)); + memset(pgLO->lolist, 0, (n + 1) * sizeof(LOlist)); if (!pgLO->lolist) { @@ -74,8 +76,8 @@ load_lolist(LODumpMaster * pgLO) { ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0)); ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1)); + ll->lo_schema = strdup(PQgetvalue(pgLO->res, i, 2)); } - ll->lo_table = ll->lo_attr = (char *) NULL; PQclear(pgLO->res); } @@ -98,7 +100,7 @@ pglo_export(LODumpMaster * pgLO) fprintf(pgLO->index, "#\tHost: %s\n", pgLO->host); fprintf(pgLO->index, "#\tDatabase: %s\n", pgLO->db); fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user); - fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\n#\n"); + fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\tschema\n#\n"); } pgLO->counter = 0; @@ -109,8 +111,9 @@ pglo_export(LODumpMaster * pgLO) * Query: find the LOs referenced by this column */ snprintf(Qbuff, QUERY_BUFSIZ, - "SELECT DISTINCT l.loid FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid", - ll->lo_table, ll->lo_attr); + "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); /* puts(Qbuff); */ @@ -124,8 +127,8 @@ pglo_export(LODumpMaster * pgLO) else if ((tuples = PQntuples(pgLO->res)) == 0) { if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR) - printf("%s: no large objects in \"%s\".\"%s\"\n", - progname, ll->lo_table, ll->lo_attr); + printf("%s: no large objects in \"%s\".\"%s\".\"%s\"\n", + progname, ll->lo_schema, ll->lo_table, ll->lo_attr); } else { @@ -140,7 +143,19 @@ pglo_export(LODumpMaster * pgLO) { snprintf(path, BUFSIZ, "%s/%s/%s", pgLO->space, pgLO->db, - ll->lo_table); + ll->lo_schema); + + if (mkdir(path, DIR_UMASK) == -1) + { + if (errno != EEXIST) + { + perror(path); + exit(RE_ERROR); + } + } + + snprintf(path, BUFSIZ, "%s/%s/%s/%s", pgLO->space, pgLO->db, + ll->lo_schema, ll->lo_table); if (mkdir(path, DIR_UMASK) == -1) { @@ -151,8 +166,8 @@ pglo_export(LODumpMaster * pgLO) } } - snprintf(path, BUFSIZ, "%s/%s/%s/%s", pgLO->space, pgLO->db, - ll->lo_table, ll->lo_attr); + snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s", pgLO->space, pgLO->db, + ll->lo_schema, ll->lo_table, ll->lo_attr); if (mkdir(path, DIR_UMASK) == -1) { @@ -164,8 +179,8 @@ pglo_export(LODumpMaster * pgLO) } if (!pgLO->quiet) - printf("dump %s.%s (%d large obj)\n", - ll->lo_table, ll->lo_attr, tuples); + printf("dump %s.%s.%s (%d large obj)\n", + ll->lo_schema, ll->lo_table, ll->lo_attr, tuples); } pgLO->counter += tuples; @@ -180,20 +195,22 @@ pglo_export(LODumpMaster * pgLO) if (pgLO->action == ACTION_SHOW) { - printf("%s.%s: %u\n", ll->lo_table, ll->lo_attr, lo); + printf("%s.%s.%s: %u\n", ll->lo_schema, ll->lo_table, ll->lo_attr, lo); continue; } - snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s", pgLO->space, - pgLO->db, ll->lo_table, ll->lo_attr, val); + snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s/%s", pgLO->space, + pgLO->db, ll->lo_schema, ll->lo_table, ll->lo_attr, val); if (lo_export(pgLO->conn, lo, path) < 0) fprintf(stderr, "%s: lo_export failed:\n%s", progname, PQerrorMessage(pgLO->conn)); else - fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s\n", val, - ll->lo_table, ll->lo_attr, pgLO->db, ll->lo_table, ll->lo_attr, val); + 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); } } diff --git a/contrib/pg_dumplo/lo_import.c b/contrib/pg_dumplo/lo_import.c index c3abb92999..337a0509fe 100644 --- a/contrib/pg_dumplo/lo_import.c +++ b/contrib/pg_dumplo/lo_import.c @@ -1,9 +1,9 @@ /* ------------------------------------------------------------------------- * pg_dumplo * - * $PostgreSQL: pgsql/contrib/pg_dumplo/lo_import.c,v 1.10 2003/11/29 19:51:35 pgsql Exp $ + * $PostgreSQL: pgsql/contrib/pg_dumplo/lo_import.c,v 1.11 2004/11/28 23:49:49 tgl Exp $ * - * Karel Zak 1999-2000 + * Karel Zak 1999-2004 * ------------------------------------------------------------------------- */ @@ -27,26 +27,47 @@ pglo_import(LODumpMaster * pgLO) { LOlist loa; Oid new_oid; + int ret, line=0; char tab[MAX_TABLE_NAME], attr[MAX_ATTR_NAME], + sch[MAX_SCHEMA_NAME], path[BUFSIZ], lo_path[BUFSIZ], Qbuff[QUERY_BUFSIZ]; while (fgets(Qbuff, QUERY_BUFSIZ, pgLO->index)) { - + line++; + if (*Qbuff == '#') continue; if (!pgLO->remove && !pgLO->quiet) printf(Qbuff); - sscanf(Qbuff, "%u\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path); + if ((ret=sscanf(Qbuff, "%u\t%s\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path, sch)) < 5) + { + /* backward compatible mode */ + ret = sscanf(Qbuff, "%u\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path); + strcpy(sch, "public"); + } + if (ret < 4) + { + fprintf(stderr, "%s: index file reading failed at line %d\n", progname, line); + PQexec(pgLO->conn, "ROLLBACK"); + fprintf(stderr, "\n%s: ROLLBACK\n", progname); + exit(RE_ERROR); + } + + loa.lo_schema = sch; loa.lo_table = tab; loa.lo_attr = attr; - snprintf(lo_path, BUFSIZ, "%s/%s", pgLO->space, path); + if (path && *path=='/') + /* absolute path */ + snprintf(lo_path, BUFSIZ, "%s", path); + else + snprintf(lo_path, BUFSIZ, "%s/%s", pgLO->space, path); /* * Import LO @@ -80,10 +101,10 @@ pglo_import(LODumpMaster * pgLO) * UPDATE oid in tab */ snprintf(Qbuff, QUERY_BUFSIZ, - "UPDATE \"%s\" SET \"%s\"=%u WHERE \"%s\"=%u", - loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid); + "UPDATE \"%s\".\"%s\" SET \"%s\"=%u WHERE \"%s\"=%u", + loa.lo_schema, loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid); - /* fprintf(stderr, Qbuff); */ + /*fprintf(stderr, Qbuff);*/ pgLO->res = PQexec(pgLO->conn, Qbuff); diff --git a/contrib/pg_dumplo/main.c b/contrib/pg_dumplo/main.c index 344fdddc95..441f3a5c7c 100644 --- a/contrib/pg_dumplo/main.c +++ b/contrib/pg_dumplo/main.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------- * pg_dumplo * - * $PostgreSQL: pgsql/contrib/pg_dumplo/main.c,v 1.21 2004/11/27 18:51:04 tgl Exp $ + * $PostgreSQL: pgsql/contrib/pg_dumplo/main.c,v 1.22 2004/11/28 23:49:49 tgl Exp $ * * Karel Zak 1999-2000 * ------------------------------------------------------------------------- @@ -150,13 +150,10 @@ main(int argc, char **argv) /* * Check space */ - if (!pgLO->space && !pgLO->action == ACTION_SHOW) + if (pgLO->space==NULL && pgLO->action != ACTION_SHOW) { if (!(pgLO->space = getenv("PWD"))) - { - fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname); - exit(RE_ERROR); - } + pgLO->space = "."; } if (!pgLO->action) @@ -230,9 +227,8 @@ static void parse_lolist(LODumpMaster * pgLO) { LOlist *ll; - char **d, - *loc, - buff[MAX_TABLE_NAME + MAX_ATTR_NAME + 1]; + char **d, *loc, *loc2, + buff[MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 3]; pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist)); @@ -247,16 +243,31 @@ parse_lolist(LODumpMaster * pgLO) d++, ll++) { - strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME); + strncpy(buff, *d, MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 2); - if ((loc = strchr(buff, '.')) == NULL) + if ((loc = strchr(buff, '.')) == NULL || *(loc+1)=='\0') { - fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff); + fprintf(stderr, "%s: '%s' is bad 'table.attr' or 'schema.table.attr'\n", progname, buff); exit(RE_ERROR); } + loc2 = strchr(loc+1, '.'); *loc = '\0'; - ll->lo_table = strdup(buff); - ll->lo_attr = strdup(++loc); + + if (loc2) + { + /* "schema.table.attr" + */ + *loc2 = '\0'; + ll->lo_schema = strdup(buff); + ll->lo_table = strdup(loc+1); + ll->lo_attr = strdup(loc2+1); + } + else + { + ll->lo_schema = strdup("public"); + ll->lo_table = strdup(buff); + ll->lo_attr = strdup(loc+1); + } } ll++; ll->lo_table = ll->lo_attr = (char *) NULL; @@ -277,7 +288,7 @@ usage(void) "-s --space= directory with dump tree (for export/import)\n" "-i --import import large obj dump tree to DB\n" "-e --export export (dump) large obj to dump tree\n" - "-l dump attribute (columns) with LO to dump tree\n" + "-l dump attribute (columns) with LO to dump tree\n" "-a --all dump all LO in DB (default)\n" "-r --remove if is set '-i' try remove old LO\n" "-q --quiet run quietly\n" @@ -288,8 +299,9 @@ usage(void) "Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n" "Example (show): pg_dumplo -w -d my_db\n\n" "Note: * option '-l' must be last option!\n" - " * option '-i' without option '-r' make new large obj in DB\n" + " * default schema is \"public\"\n" + " * option '-i' without option '-r' make new large obj in DB\n" " not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n" - " * if option -s is not set, pg_dumplo uses $PWD\n" + " * if option -s is not set, pg_dumplo uses $PWD or \".\"\n" ); /* puts() */ } diff --git a/contrib/pg_dumplo/pg_dumplo.h b/contrib/pg_dumplo/pg_dumplo.h index 711f53c70a..05991f1b0f 100644 --- a/contrib/pg_dumplo/pg_dumplo.h +++ b/contrib/pg_dumplo/pg_dumplo.h @@ -1,9 +1,9 @@ /* ------------------------------------------------------------------------- * pg_dumplo.h * - * $PostgreSQL: pgsql/contrib/pg_dumplo/pg_dumplo.h,v 1.10 2003/11/29 19:51:35 pgsql Exp $ + * $PostgreSQL: pgsql/contrib/pg_dumplo/pg_dumplo.h,v 1.11 2004/11/28 23:49:49 tgl Exp $ * - * Karel Zak 1999-2000 + * Karel Zak 1999-2004 * ------------------------------------------------------------------------- */ @@ -25,6 +25,7 @@ #define RE_OK 0 #define RE_ERROR 1 +#define MAX_SCHEMA_NAME 128 #define MAX_TABLE_NAME 128 #define MAX_ATTR_NAME 128 @@ -36,10 +37,11 @@ */ typedef struct { - char *lo_table, - *lo_attr; - Oid lo_oid; -} LOlist; + char *lo_schema, + *lo_table, + *lo_attr; + Oid lo_oid; +} LOlist; typedef struct {