vacuumlo.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:4k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * vacuumlo.c
  4.  *   This removes orphaned large objects from a database.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.2 1999/05/25 16:06:31 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <strings.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #include <unistd.h>
  21. #include "libpq-fe.h"
  22. #include "libpq/libpq-fs.h"
  23. #define BUFSIZE 1024
  24. int vacuumlo(char *, int);
  25. /*
  26.  * This vacuums a database. It returns 1 on success, -1 on failure.
  27.  */
  28. int
  29. vacuumlo(char *database, int verbose)
  30. {
  31. PGconn    *conn;
  32. PGresult   *res,
  33.    *res2;
  34. char buf[BUFSIZE];
  35. int matched = 0; /* Number matched per scan */
  36. int i;
  37. conn = PQsetdb(NULL, NULL, NULL, NULL, database);
  38. /* check to see that the backend connection was successfully made */
  39. if (PQstatus(conn) == CONNECTION_BAD)
  40. {
  41. fprintf(stderr, "Connection to database '%s' failed.n", database);
  42. fprintf(stderr, "%s", PQerrorMessage(conn));
  43. return -1;
  44. }
  45. if (verbose)
  46. fprintf(stdout, "Connected to %sn", database);
  47. /*
  48.  * First we create and populate the lo temp table
  49.  */
  50. buf[0] = '';
  51. strcat(buf, "SELECT oid AS lo ");
  52. strcat(buf, "INTO TEMP TABLE vacuum_l ");
  53. strcat(buf, "FROM pg_class ");
  54. strcat(buf, "WHERE relkind='l'");
  55. if (!(res = PQexec(conn, buf)))
  56. {
  57. fprintf(stderr, "Failed to create temp table.n");
  58. PQfinish(conn);
  59. return -1;
  60. }
  61. PQclear(res);
  62. /*
  63.  * Now find any candidate tables who have columns of type oid (the
  64.  * column oid is ignored, as it has attnum < 1)
  65.  */
  66. buf[0] = '';
  67. strcat(buf, "SELECT c.relname, a.attname ");
  68. strcat(buf, "FROM pg_class c, pg_attribute a, pg_type t ");
  69. strcat(buf, "WHERE a.attnum > 0 ");
  70. strcat(buf, "      AND a.attrelid = c.oid ");
  71. strcat(buf, "      AND a.atttypid = t.oid ");
  72. strcat(buf, "      AND t.typname = 'oid' ");
  73. strcat(buf, "      AND c.relname NOT LIKE 'pg_%'");
  74. if (!(res = PQexec(conn, buf)))
  75. {
  76. fprintf(stderr, "Failed to create temp table.n");
  77. PQfinish(conn);
  78. return -1;
  79. }
  80. for (i = 0; i < PQntuples(res); i++)
  81. {
  82. char    *table,
  83.    *field;
  84. table = PQgetvalue(res, i, 0);
  85. field = PQgetvalue(res, i, 1);
  86. if (verbose)
  87. {
  88. fprintf(stdout, "Checking %s in %s: ", field, table);
  89. fflush(stdout);
  90. }
  91. res2 = PQexec(conn, "begin");
  92. PQclear(res2);
  93. buf[0] = '';
  94. strcat(buf, "DELETE FROM vacuum_l ");
  95. strcat(buf, "WHERE lo IN (");
  96. strcat(buf, "SELECT ");
  97. strcat(buf, field);
  98. strcat(buf, " FROM ");
  99. strcat(buf, table);
  100. strcat(buf, ");");
  101. if (!(res2 = PQexec(conn, buf)))
  102. {
  103. fprintf(stderr, "Failed to check %s in table %sn", field, table);
  104. PQclear(res);
  105. PQfinish(conn);
  106. return -1;
  107. }
  108. if (PQresultStatus(res2) != PGRES_COMMAND_OK)
  109. {
  110. fprintf(stderr,
  111. "Failed to check %s in table %sn%sn",
  112. field, table,
  113. PQerrorMessage(conn)
  114. );
  115. PQclear(res2);
  116. PQclear(res);
  117. PQfinish(conn);
  118. return -1;
  119. }
  120. PQclear(res2);
  121. res2 = PQexec(conn, "end");
  122. PQclear(res2);
  123. }
  124. PQclear(res);
  125. /* Start the transaction */
  126. res = PQexec(conn, "begin");
  127. PQclear(res);
  128. /*
  129.  * Finally, those entries remaining in vacuum_l are orphans.
  130.  */
  131. buf[0] = '';
  132. strcat(buf, "SELECT lo ");
  133. strcat(buf, "FROM vacuum_l");
  134. if (!(res = PQexec(conn, buf)))
  135. {
  136. fprintf(stderr, "Failed to read temp table.n");
  137. PQfinish(conn);
  138. return -1;
  139. }
  140. matched = PQntuples(res);
  141. for (i = 0; i < matched; i++)
  142. {
  143. Oid lo = (Oid) atoi(PQgetvalue(res, i, 0));
  144. if (verbose)
  145. {
  146. fprintf(stdout, "rRemoving lo %6d n", lo);
  147. fflush(stdout);
  148. }
  149. if (lo_unlink(conn, lo) < 0)
  150. fprintf(stderr, "Failed to remove lo %dn", lo);
  151. }
  152. PQclear(res);
  153. /*
  154.  * That's all folks!
  155.  */
  156. res = PQexec(conn, "end");
  157. PQclear(res);
  158. PQfinish(conn);
  159. if (verbose)
  160. fprintf(stdout, "rRemoved %d large objects from %s.n", matched, database);
  161. return 0;
  162. }
  163. int
  164. main(int argc, char **argv)
  165. {
  166. int verbose = 0;
  167. int arg;
  168. int rc = 0;
  169. if (argc < 2)
  170. {
  171. fprintf(stderr, "Usage: %s [-v] database_name [db2 ... dbn]n",
  172. argv[0]);
  173. exit(1);
  174. }
  175. for (arg = 1; arg < argc; arg++)
  176. {
  177. if (strcmp("-v", argv[arg]) == 0)
  178. verbose = !verbose;
  179. else
  180. rc += vacuumlo(argv[arg], verbose);
  181. }
  182. return rc;
  183. }