vacuumlo.v5.patch
application/octet-stream
diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
new file mode 100644
index f6e2a28..64dcad8
*** a/contrib/vacuumlo/vacuumlo.c
--- b/contrib/vacuumlo/vacuumlo.c
***************
*** 23,28 ****
--- 23,29 ----
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
+ #include <limits.h>
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
*************** struct _param
*** 48,53 ****
--- 49,55 ----
char *pg_host;
int verbose;
int dry_run;
+ int transaction_limit;
};
int vacuumlo(char *, struct _param *);
*************** vacuumlo(char *database, struct _param *
*** 70,75 ****
--- 72,78 ----
int i;
static char *password = NULL;
bool new_pass;
+ bool success = true;
if (param->pg_prompt == TRI_YES && password == NULL)
password = simple_prompt("Password: ", 100, false);
*************** vacuumlo(char *database, struct _param *
*** 280,291 ****
--- 283,303 ----
{
fprintf(stderr, "\nFailed to remove lo %u: ", lo);
fprintf(stderr, "%s", PQerrorMessage(conn));
+ if (PQtransactionStatus(conn) == PQTRANS_INERROR) {
+ fprintf(stderr,
+ "Bailing out. Try using -l LIMIT flag, "
+ "with a LIMIT of %d\n", i);
+ success = false;
+ break;
+ }
}
else
deleted++;
}
else
deleted++;
+ if (param->transaction_limit != 0 && deleted >= param->transaction_limit)
+ break;
}
PQclear(res);
*************** vacuumlo(char *database, struct _param *
*** 297,307 ****
PQfinish(conn);
! if (param->verbose)
! fprintf(stdout, "\r%s %d large objects from %s.\n",
! (param->dry_run ? "Would remove" : "Removed"), deleted, database);
! return 0;
}
void
--- 309,326 ----
PQfinish(conn);
! if (param->verbose) {
! if (param->dry_run)
! fprintf(stdout, "\rWould remove");
! else if (success)
! fprintf(stdout, "\rSuccessfully removed");
! else
! fprintf(stdout, "\rFailed to remove");
! fprintf(stdout, " %d large objects from %s.\n", deleted, database);
! }
!
! return ((param->dry_run || success) ? 0 : -1);
}
void
*************** usage(const char *progname)
*** 311,316 ****
--- 330,336 ----
printf("Usage:\n %s [OPTION]... DBNAME...\n\n", progname);
printf("Options:\n");
printf(" -h HOSTNAME database server host or socket directory\n");
+ printf(" -l LIMIT stop after removing LIMIT large objects\n");
printf(" -n don't remove large objects, just show what would be done\n");
printf(" -p PORT database server port\n");
printf(" -U USERNAME user name to connect as\n");
*************** main(int argc, char **argv)
*** 342,347 ****
--- 362,368 ----
param.pg_port = NULL;
param.verbose = 0;
param.dry_run = 0;
+ param.transaction_limit = 0;
if (argc > 1)
{
*************** main(int argc, char **argv)
*** 359,365 ****
while (1)
{
! c = getopt(argc, argv, "h:U:p:vnwW");
if (c == -1)
break;
--- 380,386 ----
while (1)
{
! c = getopt(argc, argv, "h:l:U:p:vnwW");
if (c == -1)
break;
*************** main(int argc, char **argv)
*** 395,400 ****
--- 416,429 ----
}
param.pg_port = strdup(optarg);
break;
+ case 'l':
+ param.transaction_limit = strtol(optarg, NULL, 10);
+ if ((param.transaction_limit < 0) || (param.transaction_limit > INT_MAX))
+ {
+ fprintf(stderr, "%s: invalid transaction limit number: %s, valid range is form 0(disabled) to INT_MAX(%i).\n", progname, optarg, INT_MAX);
+ exit(1);
+ }
+ break;
case 'h':
param.pg_host = strdup(optarg);
break;
diff --git a/doc/src/sgml/vacuumlo.sgml b/doc/src/sgml/vacuumlo.sgml
new file mode 100644
index 471a6ca..905eae1
*** a/doc/src/sgml/vacuumlo.sgml
--- b/doc/src/sgml/vacuumlo.sgml
*************** vacuumlo [options] database [database2 .
*** 57,62 ****
--- 57,72 ----
</varlistentry>
<varlistentry>
+ <term><option>-l</option> <replaceable>limit</></term>
+ <listitem>
+ <para>
+ Stop after removing LIMIT large objects. Useful to avoid
+ exceeding <varname>max_locks_per_transaction</varname>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-w</></term>
<term><option>--no-password</></term>
<listitem>