24 #include "catalog/pg_class_d.h" 53 static int vacuumlo(
const char *database,
const struct _param *param);
85 #define PARAMS_ARRAY_SIZE 7 96 keywords[3] =
"password";
98 keywords[4] =
"dbname";
100 keywords[5] =
"fallback_application_name";
109 pg_log_error(
"connection to database \"%s\" failed", database);
127 pg_log_error(
"connection to database \"%s\" failed: %s",
137 fprintf(
stdout,
"Test run: no large objects will be removed!\n");
154 strcat(buf,
"CREATE TEMP TABLE vacuum_l AS ");
156 strcat(buf,
"SELECT oid AS lo FROM pg_largeobject_metadata");
158 strcat(buf,
"SELECT DISTINCT loid AS lo FROM pg_largeobject");
174 strcat(buf,
"ANALYZE vacuum_l");
195 strcat(buf,
"SELECT s.nspname, c.relname, a.attname ");
196 strcat(buf,
"FROM pg_class c, pg_attribute a, pg_namespace s, pg_type t ");
197 strcat(buf,
"WHERE a.attnum > 0 AND NOT a.attisdropped ");
198 strcat(buf,
" AND a.attrelid = c.oid ");
199 strcat(buf,
" AND a.atttypid = t.oid ");
200 strcat(buf,
" AND c.relnamespace = s.oid ");
201 strcat(buf,
" AND t.typname in ('oid', 'lo') ");
203 strcat(buf,
" AND s.nspname !~ '^pg_'");
224 fprintf(
stdout,
"Checking %s in %s.%s\n", field, schema, table);
230 if (!schema || !table || !field)
245 "DELETE FROM vacuum_l " 246 "WHERE lo IN (SELECT %s FROM %s.%s)",
247 field, schema, table);
278 res =
PQexec(conn,
"begin");
290 "DECLARE myportal CURSOR WITH HOLD FOR SELECT lo FROM vacuum_l");
325 for (i = 0; i < matched; i++)
356 res2 =
PQexec(conn,
"commit");
367 res2 =
PQexec(conn,
"begin");
387 res =
PQexec(conn,
"commit");
403 fprintf(
stdout,
"\rWould remove %ld large objects from database \"%s\".\n",
407 "\rSuccessfully removed %ld large objects from database \"%s\".\n",
410 fprintf(
stdout,
"\rRemoval from database \"%s\" failed at object %ld of %ld.\n",
411 database, deleted, matched);
414 return ((param->
dry_run || success) ? 0 : -1);
420 printf(
"%s removes unreferenced large objects from databases.\n\n", progname);
421 printf(
"Usage:\n %s [OPTION]... DBNAME...\n\n", progname);
423 printf(
" -l, --limit=LIMIT commit after removing each LIMIT large objects\n");
424 printf(
" -n, --dry-run don't remove large objects, just show what would be done\n");
425 printf(
" -v, --verbose write a lot of progress messages\n");
426 printf(
" -V, --version output version information, then exit\n");
427 printf(
" -?, --help show this help, then exit\n");
428 printf(
"\nConnection options:\n");
429 printf(
" -h, --host=HOSTNAME database server host or socket directory\n");
430 printf(
" -p, --port=PORT database server port\n");
431 printf(
" -U, --username=USERNAME user name to connect as\n");
432 printf(
" -w, --no-password never prompt for password\n");
433 printf(
" -W, --password force password prompt\n");
435 printf(
"Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
436 printf(
"%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
443 static struct option long_options[] = {
480 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
485 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
487 puts(
"vacuumlo (PostgreSQL) " PG_VERSION);
492 while ((c =
getopt_long(argc, argv,
"h:l:np:U:vwW", long_options, &optindex)) != -1)
497 fprintf(stderr,
_(
"Try \"%s --help\" for more information.\n"), progname);
506 pg_log_error(
"transaction limit must not be negative (0 disables)");
515 port = strtol(
optarg, NULL, 10);
516 if ((port < 1) || (port > 65535))
536 fprintf(stderr,
_(
"Try \"%s --help\" for more information.\n"), progname);
544 pg_log_error(
"missing required argument: database name");
545 fprintf(stderr,
_(
"Try \"%s --help\" for more information.\n"), progname);
549 for (c =
optind; c < argc; c++)
552 rc += (
vacuumlo(argv[c], ¶m) != 0);
char * PQerrorMessage(const PGconn *conn)
#define PARAMS_ARRAY_SIZE
int main(int argc, char **argv)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
const char * get_progname(const char *argv0)
#define pg_log_error(...)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
int lo_unlink(PGconn *conn, Oid lobjId)
void pg_logging_init(const char *argv0)
void PQfinish(PGconn *conn)
char * simple_prompt(const char *prompt, bool echo)
int PQserverVersion(const PGconn *conn)
int PQntuples(const PGresult *res)
ExecStatusType PQresultStatus(const PGresult *res)
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
#define required_argument
char * pg_strdup(const char *in)
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
void PQclear(PGresult *res)
static int vacuumlo(const char *database, const struct _param *param)
#define ALWAYS_SECURE_SEARCH_PATH_SQL
static Datum values[MAXATTR]
int PQconnectionNeedsPassword(const PGconn *conn)
PGresult * PQexec(PGconn *conn, const char *query)
static void usage(const char *progname)
ConnStatusType PQstatus(const PGconn *conn)
void PQfreemem(void *ptr)