Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
280a77d3
Commit
280a77d3
authored
Nov 21, 2000
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code review and cleanup.
parent
22c528fc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
61 deletions
+102
-61
contrib/vacuumlo/README.vacuumlo
contrib/vacuumlo/README.vacuumlo
+18
-10
contrib/vacuumlo/vacuumlo.c
contrib/vacuumlo/vacuumlo.c
+84
-51
No files found.
contrib/vacuumlo/README.vacuumlo
View file @
280a77d3
$Header: /cvsroot/pgsql/contrib/vacuumlo/Attic/README.vacuumlo,v 1.
1 2000/06/19 14:02:16 momjian
Exp $
$Header: /cvsroot/pgsql/contrib/vacuumlo/Attic/README.vacuumlo,v 1.
2 2000/11/21 17:54:21 tgl
Exp $
This is a simple utility that will remove any orphaned large objects out of a
This is a simple utility that will remove any orphaned large objects out of a
PostgreSQL database.
PostgreSQL database. An orphaned LO is considered to be any LO whose OID
does not appear in any OID data column of the database.
Compiling
Compiling
--------
--------
Simply run make. A single executable "vacuumlo" is created.
Simply run make. A single executable "vacuumlo" is created.
Useage
------
Usage
-----
vacuumlo [-v] database [db2 ... dbn]
vacuumlo [-v] database [db2 ... dbn]
The -v flag outputs some progress messages to stdout.
The -v flag outputs some progress messages to stdout.
Method
Method
------
------
First, it builds a temporary table which contains all of the oid's of the
First, it builds a temporary table which contains all of the oid's of the
large objects in that database.
large objects in that database.
It then scans through any columns in the database that are of type 'oid', and
It then scans through all columns in the database that are of type 'oid',
removes any entries from the temporary table.
and removes any matching entries from the temporary table.
The remaining entries in the temp table identify orphaned LOs. These are
removed.
Finally, it runs through the first table, and removes from the second table, any
Notes
oid's it finds. What is left are the orphans, and these are removed.
-----
I decided to place this in contrib as it needs further testing, but hopefully,
I decided to place this in contrib as it needs further testing, but hopefully,
this (or a variant of it) would make it into the backe
d as a "vacuum lo" command
this (or a variant of it) would make it into the backe
nd as a "vacuum lo"
in a later release.
command
in a later release.
Peter Mount <peter@retep.org.uk>
Peter Mount <peter@retep.org.uk>
http://www.retep.org.uk
http://www.retep.org.uk
...
...
contrib/vacuumlo/vacuumlo.c
View file @
280a77d3
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.
6 2000/10/24 01:38:20
tgl Exp $
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.
7 2000/11/21 17:54:21
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -24,13 +24,15 @@
...
@@ -24,13 +24,15 @@
#include "libpq-fe.h"
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "libpq/libpq-fs.h"
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
#define BUFSIZE 1024
#define BUFSIZE 1024
int
vacuumlo
(
char
*
,
int
);
int
vacuumlo
(
char
*
,
int
);
/*
/*
* This vacuums
a database. It returns 1
on success, -1 on failure.
* This vacuums
LOs of one database. It returns 0
on success, -1 on failure.
*/
*/
int
int
vacuumlo
(
char
*
database
,
int
verbose
)
vacuumlo
(
char
*
database
,
int
verbose
)
...
@@ -39,7 +41,8 @@ vacuumlo(char *database, int verbose)
...
@@ -39,7 +41,8 @@ vacuumlo(char *database, int verbose)
PGresult
*
res
,
PGresult
*
res
,
*
res2
;
*
res2
;
char
buf
[
BUFSIZE
];
char
buf
[
BUFSIZE
];
int
matched
=
0
;
/* Number matched per scan */
int
matched
;
int
deleted
;
int
i
;
int
i
;
conn
=
PQsetdb
(
NULL
,
NULL
,
NULL
,
NULL
,
database
);
conn
=
PQsetdb
(
NULL
,
NULL
,
NULL
,
NULL
,
database
);
...
@@ -47,8 +50,9 @@ vacuumlo(char *database, int verbose)
...
@@ -47,8 +50,9 @@ vacuumlo(char *database, int verbose)
/* check to see that the backend connection was successfully made */
/* check to see that the backend connection was successfully made */
if
(
PQstatus
(
conn
)
==
CONNECTION_BAD
)
if
(
PQstatus
(
conn
)
==
CONNECTION_BAD
)
{
{
fprintf
(
stderr
,
"Connection to database '%s' failed
.
\n
"
,
database
);
fprintf
(
stderr
,
"Connection to database '%s' failed
:
\n
"
,
database
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQfinish
(
conn
);
return
-
1
;
return
-
1
;
}
}
...
@@ -56,23 +60,49 @@ vacuumlo(char *database, int verbose)
...
@@ -56,23 +60,49 @@ vacuumlo(char *database, int verbose)
fprintf
(
stdout
,
"Connected to %s
\n
"
,
database
);
fprintf
(
stdout
,
"Connected to %s
\n
"
,
database
);
/*
/*
* First we create and populate the
lo
temp table
* First we create and populate the
LO
temp table
*/
*/
buf
[
0
]
=
'\0'
;
buf
[
0
]
=
'\0'
;
strcat
(
buf
,
"SELECT DISTINCT loid AS lo "
);
strcat
(
buf
,
"SELECT DISTINCT loid AS lo "
);
strcat
(
buf
,
"INTO TEMP TABLE vacuum_l "
);
strcat
(
buf
,
"INTO TEMP TABLE vacuum_l "
);
strcat
(
buf
,
"FROM pg_largeobject "
);
strcat
(
buf
,
"FROM pg_largeobject "
);
if
(
!
(
res
=
PQexec
(
conn
,
buf
)))
res
=
PQexec
(
conn
,
buf
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
fprintf
(
stderr
,
"Failed to create temp table:
\n
"
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQclear
(
res
);
PQfinish
(
conn
);
return
-
1
;
}
PQclear
(
res
);
/*
* Vacuum the temp table so that planner will generate decent plans
* for the DELETEs below.
*/
buf
[
0
]
=
'\0'
;
strcat
(
buf
,
"VACUUM ANALYZE vacuum_l "
);
res
=
PQexec
(
conn
,
buf
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
{
fprintf
(
stderr
,
"Failed to create temp table.
\n
"
);
fprintf
(
stderr
,
"Failed to vacuum temp table:
\n
"
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQclear
(
res
);
PQfinish
(
conn
);
PQfinish
(
conn
);
return
-
1
;
return
-
1
;
}
}
PQclear
(
res
);
PQclear
(
res
);
/*
/*
* Now find any candidate tables who have columns of type oid (the
* Now find any candidate tables who have columns of type oid.
* column oid is ignored, as it has attnum < 1)
*
* NOTE: the temp table formed above is ignored, because its real
* table name will be pg_something. Also, pg_largeobject will be
* ignored. If either of these were scanned, obviously we'd end up
* with nothing to delete...
*
* NOTE: the system oid column is ignored, as it has attnum < 1.
* This shouldn't matter for correctness, but it saves time.
*/
*/
buf
[
0
]
=
'\0'
;
buf
[
0
]
=
'\0'
;
strcat
(
buf
,
"SELECT c.relname, a.attname "
);
strcat
(
buf
,
"SELECT c.relname, a.attname "
);
...
@@ -81,13 +111,18 @@ vacuumlo(char *database, int verbose)
...
@@ -81,13 +111,18 @@ vacuumlo(char *database, int verbose)
strcat
(
buf
,
" AND a.attrelid = c.oid "
);
strcat
(
buf
,
" AND a.attrelid = c.oid "
);
strcat
(
buf
,
" AND a.atttypid = t.oid "
);
strcat
(
buf
,
" AND a.atttypid = t.oid "
);
strcat
(
buf
,
" AND t.typname = 'oid' "
);
strcat
(
buf
,
" AND t.typname = 'oid' "
);
strcat
(
buf
,
" AND c.relkind = 'r'"
);
strcat
(
buf
,
" AND c.relname NOT LIKE 'pg_%'"
);
strcat
(
buf
,
" AND c.relname NOT LIKE 'pg_%'"
);
if
(
!
(
res
=
PQexec
(
conn
,
buf
)))
res
=
PQexec
(
conn
,
buf
);
if
(
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
{
{
fprintf
(
stderr
,
"Failed to create temp table.
\n
"
);
fprintf
(
stderr
,
"Failed to find OID columns:
\n
"
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQclear
(
res
);
PQfinish
(
conn
);
PQfinish
(
conn
);
return
-
1
;
return
-
1
;
}
}
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
{
{
char
*
table
,
char
*
table
,
...
@@ -97,50 +132,36 @@ vacuumlo(char *database, int verbose)
...
@@ -97,50 +132,36 @@ vacuumlo(char *database, int verbose)
field
=
PQgetvalue
(
res
,
i
,
1
);
field
=
PQgetvalue
(
res
,
i
,
1
);
if
(
verbose
)
if
(
verbose
)
{
fprintf
(
stdout
,
"Checking %s in %s
\n
"
,
field
,
table
);
fprintf
(
stdout
,
"Checking %s in %s: "
,
field
,
table
);
fflush
(
stdout
);
/*
}
* We use a DELETE with implicit join for efficiency. This
* is a Postgres-ism and not portable to other DBMSs, but
res2
=
PQexec
(
conn
,
"begin"
);
* then this whole program is a Postgres-ism.
PQclear
(
res2
);
*/
sprintf
(
buf
,
"DELETE FROM vacuum_l WHERE lo =
\"
%s
\"
.
\"
%s
\"
"
,
buf
[
0
]
=
'\0'
;
table
,
field
);
strcat
(
buf
,
"DELETE FROM vacuum_l "
);
res2
=
PQexec
(
conn
,
buf
);
strcat
(
buf
,
"WHERE lo IN ("
);
strcat
(
buf
,
"SELECT "
);
strcat
(
buf
,
field
);
strcat
(
buf
,
" FROM "
);
strcat
(
buf
,
table
);
strcat
(
buf
,
");"
);
if
(
!
(
res2
=
PQexec
(
conn
,
buf
)))
{
fprintf
(
stderr
,
"Failed to check %s in table %s
\n
"
,
field
,
table
);
PQclear
(
res
);
PQfinish
(
conn
);
return
-
1
;
}
if
(
PQresultStatus
(
res2
)
!=
PGRES_COMMAND_OK
)
if
(
PQresultStatus
(
res2
)
!=
PGRES_COMMAND_OK
)
{
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Failed to check %s in table %s:
\n
"
,
"Failed to check %s in table %s
\n
%s
\n
"
,
field
,
table
);
field
,
table
,
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQerrorMessage
(
conn
)
);
PQclear
(
res2
);
PQclear
(
res2
);
PQclear
(
res
);
PQclear
(
res
);
PQfinish
(
conn
);
PQfinish
(
conn
);
return
-
1
;
return
-
1
;
}
}
PQclear
(
res2
);
PQclear
(
res2
);
res2
=
PQexec
(
conn
,
"end"
);
PQclear
(
res2
);
}
}
PQclear
(
res
);
PQclear
(
res
);
/* Start the transaction */
/*
* Run the actual deletes in a single transaction. Note that this
* would be a bad idea in pre-7.1 Postgres releases (since rolling
* back a table delete used to cause problems), but it should
* be safe now.
*/
res
=
PQexec
(
conn
,
"begin"
);
res
=
PQexec
(
conn
,
"begin"
);
PQclear
(
res
);
PQclear
(
res
);
...
@@ -150,25 +171,35 @@ vacuumlo(char *database, int verbose)
...
@@ -150,25 +171,35 @@ vacuumlo(char *database, int verbose)
buf
[
0
]
=
'\0'
;
buf
[
0
]
=
'\0'
;
strcat
(
buf
,
"SELECT lo "
);
strcat
(
buf
,
"SELECT lo "
);
strcat
(
buf
,
"FROM vacuum_l"
);
strcat
(
buf
,
"FROM vacuum_l"
);
if
(
!
(
res
=
PQexec
(
conn
,
buf
)))
res
=
PQexec
(
conn
,
buf
);
if
(
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
{
{
fprintf
(
stderr
,
"Failed to read temp table.
\n
"
);
fprintf
(
stderr
,
"Failed to read temp table:
\n
"
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
PQclear
(
res
);
PQfinish
(
conn
);
PQfinish
(
conn
);
return
-
1
;
return
-
1
;
}
}
matched
=
PQntuples
(
res
);
matched
=
PQntuples
(
res
);
deleted
=
0
;
for
(
i
=
0
;
i
<
matched
;
i
++
)
for
(
i
=
0
;
i
<
matched
;
i
++
)
{
{
Oid
lo
=
(
Oid
)
atoi
(
PQgetvalue
(
res
,
i
,
0
));
Oid
lo
=
atooid
(
PQgetvalue
(
res
,
i
,
0
));
if
(
verbose
)
if
(
verbose
)
{
{
fprintf
(
stdout
,
"
\r
Removing lo %6
d
\n
"
,
lo
);
fprintf
(
stdout
,
"
\r
Removing lo %6
u
"
,
lo
);
fflush
(
stdout
);
fflush
(
stdout
);
}
}
if
(
lo_unlink
(
conn
,
lo
)
<
0
)
if
(
lo_unlink
(
conn
,
lo
)
<
0
)
fprintf
(
stderr
,
"Failed to remove lo %d
\n
"
,
lo
);
{
fprintf
(
stderr
,
"
\n
Failed to remove lo %u: "
,
lo
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
}
else
deleted
++
;
}
}
PQclear
(
res
);
PQclear
(
res
);
...
@@ -177,10 +208,12 @@ vacuumlo(char *database, int verbose)
...
@@ -177,10 +208,12 @@ vacuumlo(char *database, int verbose)
*/
*/
res
=
PQexec
(
conn
,
"end"
);
res
=
PQexec
(
conn
,
"end"
);
PQclear
(
res
);
PQclear
(
res
);
PQfinish
(
conn
);
PQfinish
(
conn
);
if
(
verbose
)
if
(
verbose
)
fprintf
(
stdout
,
"
\r
Removed %d large objects from %s.
\n
"
,
matched
,
database
);
fprintf
(
stdout
,
"
\r
Removed %d large objects from %s.
\n
"
,
deleted
,
database
);
return
0
;
return
0
;
}
}
...
@@ -204,7 +237,7 @@ main(int argc, char **argv)
...
@@ -204,7 +237,7 @@ main(int argc, char **argv)
if
(
strcmp
(
"-v"
,
argv
[
arg
])
==
0
)
if
(
strcmp
(
"-v"
,
argv
[
arg
])
==
0
)
verbose
=
!
verbose
;
verbose
=
!
verbose
;
else
else
rc
+=
vacuumlo
(
argv
[
arg
],
verbose
);
rc
+=
(
vacuumlo
(
argv
[
arg
],
verbose
)
!=
0
);
}
}
return
rc
;
return
rc
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment