mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-11-21 03:13:05 +08:00
Major overhaul of large-object implementation, by Denis Perchine with
kibitzing from Tom Lane. Large objects are now all stored in a single system relation "pg_largeobject" --- no more xinv or xinx files, no more relkind 'l'. This should offer substantial performance improvement for large numbers of LOs, since there won't be directory bloat anymore. It'll also fix problems like running out of locktable space when you access thousands of LOs in one transaction. Also clean up cruft in read/write routines. LOs with "holes" in them (never-written byte ranges) now work just like Unix files with holes do: a hole reads as zeroes but doesn't occupy storage space. INITDB forced!
This commit is contained in:
parent
d7186cfa9b
commit
4f44aa04b5
@ -94,7 +94,7 @@ pglo_export(LODumpMaster *pgLO)
|
||||
* Query
|
||||
* ----------
|
||||
*/
|
||||
sprintf(Qbuff, "SELECT x.%s FROM %s x, pg_class c WHERE x.%s = c.oid and c.relkind = 'l'",
|
||||
sprintf(Qbuff, "SELECT DISTINCT x.\"%s\" FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid",
|
||||
ll->lo_attr, ll->lo_table, ll->lo_attr);
|
||||
|
||||
/* puts(Qbuff); */
|
||||
@ -104,7 +104,8 @@ pglo_export(LODumpMaster *pgLO)
|
||||
if ((tuples = PQntuples(pgLO->res)) == 0) {
|
||||
|
||||
if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
|
||||
printf("%s: no large objets in '%s'\n", progname, ll->lo_table);
|
||||
printf("%s: no large objects in '%s'\n",
|
||||
progname, ll->lo_table);
|
||||
continue;
|
||||
|
||||
} else if (check_res(pgLO)) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.5 2000/06/19 13:54:50 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.6 2000/10/24 01:38:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -59,10 +59,9 @@ vacuumlo(char *database, int verbose)
|
||||
* First we create and populate the lo temp table
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "SELECT oid AS lo ");
|
||||
strcat(buf, "SELECT DISTINCT loid AS lo ");
|
||||
strcat(buf, "INTO TEMP TABLE vacuum_l ");
|
||||
strcat(buf, "FROM pg_class ");
|
||||
strcat(buf, "WHERE relkind='l'");
|
||||
strcat(buf, "FROM pg_largeobject ");
|
||||
if (!(res = PQexec(conn, buf)))
|
||||
{
|
||||
fprintf(stderr, "Failed to create temp table.\n");
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.39 2000/10/12 22:16:58 momjian Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.40 2000/10/24 01:38:21 tgl Exp $
|
||||
Postgres documentation
|
||||
-->
|
||||
|
||||
@ -706,7 +706,8 @@ lo_import 152801
|
||||
<listitem>
|
||||
<para>
|
||||
Shows a list of all <productname>Postgres</productname> <quote>large
|
||||
objects</quote> currently stored in the database along with their owners.
|
||||
objects</quote> currently stored in the database, along with any
|
||||
comments provided for them.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# Makefile for catalog
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.30 2000/10/22 05:27:10 momjian Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.31 2000/10/24 01:38:23 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -11,7 +11,8 @@ top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = catalog.o heap.o index.o indexing.o aclchk.o \
|
||||
pg_aggregate.o pg_operator.o pg_proc.o pg_type.o
|
||||
pg_aggregate.o pg_largeobject.o pg_operator.o pg_proc.o \
|
||||
pg_type.o
|
||||
|
||||
BKIFILES = global.bki template1.bki global.description template1.description
|
||||
|
||||
@ -29,7 +30,7 @@ TEMPLATE1_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
|
||||
pg_proc.h pg_type.h pg_attribute.h pg_class.h \
|
||||
pg_inherits.h pg_index.h pg_statistic.h \
|
||||
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
|
||||
pg_language.h \
|
||||
pg_language.h pg_largeobject.h \
|
||||
pg_aggregate.h pg_ipl.h pg_inheritproc.h \
|
||||
pg_rewrite.h pg_listener.h pg_description.h indexing.h \
|
||||
)
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.71 2000/10/22 05:27:10 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.72 2000/10/24 01:38:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -51,6 +51,8 @@ char *Name_pg_inherits_indices[Num_pg_inherits_indices] =
|
||||
{InheritsRelidSeqnoIndex};
|
||||
char *Name_pg_language_indices[Num_pg_language_indices] =
|
||||
{LanguageOidIndex, LanguageNameIndex};
|
||||
char *Name_pg_largeobject_indices[Num_pg_largeobject_indices] =
|
||||
{LargeObjectLOidPNIndex};
|
||||
char *Name_pg_listener_indices[Num_pg_listener_indices] =
|
||||
{ListenerPidRelnameIndex};
|
||||
char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
|
||||
|
184
src/backend/catalog/pg_largeobject.c
Normal file
184
src/backend/catalog/pg_largeobject.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_largeobject.c
|
||||
* routines to support manipulation of the pg_largeobject relation
|
||||
*
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.5 2000/10/24 01:38:23 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
|
||||
|
||||
/*
|
||||
* Create a large object having the given LO identifier.
|
||||
*
|
||||
* We do this by inserting an empty first page, so that the object will
|
||||
* appear to exist with size 0. Note that the unique index will reject
|
||||
* an attempt to create a duplicate page.
|
||||
*
|
||||
* Return value is OID assigned to the page tuple (any use in it?)
|
||||
*/
|
||||
Oid
|
||||
LargeObjectCreate(Oid loid)
|
||||
{
|
||||
Oid retval;
|
||||
Relation pg_largeobject;
|
||||
HeapTuple ntup;
|
||||
Relation idescs[Num_pg_largeobject_indices];
|
||||
Datum values[Natts_pg_largeobject];
|
||||
char nulls[Natts_pg_largeobject];
|
||||
int i;
|
||||
|
||||
pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Form new tuple
|
||||
*/
|
||||
for (i = 0; i < Natts_pg_largeobject; i++)
|
||||
{
|
||||
values[i] = (Datum)NULL;
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(loid);
|
||||
values[i++] = Int32GetDatum(0);
|
||||
values[i++] = DirectFunctionCall1(byteain,
|
||||
CStringGetDatum(""));
|
||||
|
||||
ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls);
|
||||
|
||||
/*
|
||||
* Insert it
|
||||
*/
|
||||
retval = heap_insert(pg_largeobject, ntup);
|
||||
|
||||
/*
|
||||
* Update indices
|
||||
*/
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
CatalogOpenIndices(Num_pg_largeobject_indices, Name_pg_largeobject_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_largeobject_indices, pg_largeobject, ntup);
|
||||
CatalogCloseIndices(Num_pg_largeobject_indices, idescs);
|
||||
}
|
||||
|
||||
heap_close(pg_largeobject, RowExclusiveLock);
|
||||
|
||||
heap_freetuple(ntup);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
LargeObjectDrop(Oid loid)
|
||||
{
|
||||
bool found = false;
|
||||
Relation pg_largeobject;
|
||||
Relation pg_lo_idx;
|
||||
ScanKeyData skey[1];
|
||||
IndexScanDesc sd;
|
||||
RetrieveIndexResult indexRes;
|
||||
HeapTupleData tuple;
|
||||
Buffer buffer;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0],
|
||||
(bits16) 0x0,
|
||||
(AttrNumber) 1,
|
||||
(RegProcedure) F_OIDEQ,
|
||||
ObjectIdGetDatum(loid));
|
||||
|
||||
pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
|
||||
pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
|
||||
|
||||
sd = index_beginscan(pg_lo_idx, false, 1, skey);
|
||||
|
||||
tuple.t_datamcxt = CurrentMemoryContext;
|
||||
tuple.t_data = NULL;
|
||||
|
||||
while ((indexRes = index_getnext(sd, ForwardScanDirection)))
|
||||
{
|
||||
tuple.t_self = indexRes->heap_iptr;
|
||||
heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer);
|
||||
pfree(indexRes);
|
||||
if (tuple.t_data != NULL)
|
||||
{
|
||||
heap_delete(pg_largeobject, &tuple.t_self, NULL);
|
||||
ReleaseBuffer(buffer);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
index_endscan(sd);
|
||||
|
||||
index_close(pg_lo_idx);
|
||||
heap_close(pg_largeobject, RowShareLock);
|
||||
|
||||
if (!found)
|
||||
elog(ERROR, "LargeObjectDrop: large object %u not found", loid);
|
||||
}
|
||||
|
||||
bool
|
||||
LargeObjectExists(Oid loid)
|
||||
{
|
||||
bool retval = false;
|
||||
Relation pg_largeobject;
|
||||
Relation pg_lo_idx;
|
||||
ScanKeyData skey[1];
|
||||
IndexScanDesc sd;
|
||||
RetrieveIndexResult indexRes;
|
||||
HeapTupleData tuple;
|
||||
Buffer buffer;
|
||||
|
||||
/*
|
||||
* See if we can find any tuples belonging to the specified LO
|
||||
*/
|
||||
ScanKeyEntryInitialize(&skey[0],
|
||||
(bits16) 0x0,
|
||||
(AttrNumber) 1,
|
||||
(RegProcedure) F_OIDEQ,
|
||||
ObjectIdGetDatum(loid));
|
||||
|
||||
pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
|
||||
pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
|
||||
|
||||
sd = index_beginscan(pg_lo_idx, false, 1, skey);
|
||||
|
||||
tuple.t_datamcxt = CurrentMemoryContext;
|
||||
tuple.t_data = NULL;
|
||||
|
||||
while ((indexRes = index_getnext(sd, ForwardScanDirection)))
|
||||
{
|
||||
tuple.t_self = indexRes->heap_iptr;
|
||||
heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer);
|
||||
pfree(indexRes);
|
||||
if (tuple.t_data != NULL)
|
||||
{
|
||||
retval = true;
|
||||
ReleaseBuffer(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index_endscan(sd);
|
||||
|
||||
index_close(pg_lo_idx);
|
||||
heap_close(pg_largeobject, RowShareLock);
|
||||
|
||||
return retval;
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.54 2000/10/22 05:27:12 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.55 2000/10/24 01:38:26 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This should be moved to a more appropriate place. It is here
|
||||
@ -32,13 +32,13 @@
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "libpq/be-fsstubs.h"
|
||||
#include "libpq/libpq-fs.h"
|
||||
@ -50,8 +50,7 @@
|
||||
|
||||
/*#define FSDB 1*/
|
||||
#define MAX_LOBJ_FDS 256
|
||||
#define BUFSIZE 1024
|
||||
#define FNAME_BUFSIZE 8192
|
||||
#define BUFSIZE 8192
|
||||
|
||||
/*
|
||||
* LO "FD"s are indexes into this array.
|
||||
@ -141,10 +140,10 @@ lo_close(PG_FUNCTION_ARGS)
|
||||
|
||||
inv_close(cookies[fd]);
|
||||
|
||||
MemoryContextSwitchTo(currentContext);
|
||||
|
||||
deleteLOfd(fd);
|
||||
|
||||
MemoryContextSwitchTo(currentContext);
|
||||
|
||||
PG_RETURN_INT32(0);
|
||||
}
|
||||
|
||||
@ -267,7 +266,7 @@ lo_creat(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_OID(InvalidOid);
|
||||
}
|
||||
|
||||
lobjId = RelationGetRelid(lobjDesc->heap_r);
|
||||
lobjId = lobjDesc->id;
|
||||
|
||||
inv_close(lobjDesc);
|
||||
|
||||
@ -310,8 +309,8 @@ lo_unlink(PG_FUNCTION_ARGS)
|
||||
* any LO-specific data structures at all. (Again, that's probably
|
||||
* more than this module ought to be assuming.)
|
||||
*
|
||||
* XXX there ought to be some code to clean up any open LOs that
|
||||
* reference the specified relation... as is, they remain "open".
|
||||
* XXX there ought to be some code to clean up any open LO FDs that
|
||||
* reference the specified LO... as is, they remain "open".
|
||||
*/
|
||||
PG_RETURN_INT32(inv_drop(lobjId));
|
||||
}
|
||||
@ -367,7 +366,7 @@ lo_import(PG_FUNCTION_ARGS)
|
||||
int nbytes,
|
||||
tmp;
|
||||
char buf[BUFSIZE];
|
||||
char fnamebuf[FNAME_BUFSIZE];
|
||||
char fnamebuf[MAXPGPATH];
|
||||
LargeObjectDesc *lobj;
|
||||
Oid lobjOid;
|
||||
|
||||
@ -382,8 +381,8 @@ lo_import(PG_FUNCTION_ARGS)
|
||||
* open the file to be read in
|
||||
*/
|
||||
nbytes = VARSIZE(filename) - VARHDRSZ;
|
||||
if (nbytes >= FNAME_BUFSIZE)
|
||||
nbytes = FNAME_BUFSIZE-1;
|
||||
if (nbytes >= MAXPGPATH)
|
||||
nbytes = MAXPGPATH-1;
|
||||
memcpy(fnamebuf, VARDATA(filename), nbytes);
|
||||
fnamebuf[nbytes] = '\0';
|
||||
fd = PathNameOpenFile(fnamebuf, O_RDONLY | PG_BINARY, 0666);
|
||||
@ -398,12 +397,7 @@ lo_import(PG_FUNCTION_ARGS)
|
||||
if (lobj == NULL)
|
||||
elog(ERROR, "lo_import: can't create inv object for \"%s\"",
|
||||
fnamebuf);
|
||||
|
||||
/*
|
||||
* the oid for the large object is just the oid of the relation
|
||||
* XInv??? which contains the data.
|
||||
*/
|
||||
lobjOid = RelationGetRelid(lobj->heap_r);
|
||||
lobjOid = lobj->id;
|
||||
|
||||
/*
|
||||
* read in from the Unix file and write to the inversion file
|
||||
@ -411,7 +405,7 @@ lo_import(PG_FUNCTION_ARGS)
|
||||
while ((nbytes = FileRead(fd, buf, BUFSIZE)) > 0)
|
||||
{
|
||||
tmp = inv_write(lobj, buf, nbytes);
|
||||
if (tmp < nbytes)
|
||||
if (tmp != nbytes)
|
||||
elog(ERROR, "lo_import: error while reading \"%s\"",
|
||||
fnamebuf);
|
||||
}
|
||||
@ -435,7 +429,7 @@ lo_export(PG_FUNCTION_ARGS)
|
||||
int nbytes,
|
||||
tmp;
|
||||
char buf[BUFSIZE];
|
||||
char fnamebuf[FNAME_BUFSIZE];
|
||||
char fnamebuf[MAXPGPATH];
|
||||
LargeObjectDesc *lobj;
|
||||
mode_t oumask;
|
||||
|
||||
@ -461,8 +455,8 @@ lo_export(PG_FUNCTION_ARGS)
|
||||
* world-writable export files doesn't seem wise.
|
||||
*/
|
||||
nbytes = VARSIZE(filename) - VARHDRSZ;
|
||||
if (nbytes >= FNAME_BUFSIZE)
|
||||
nbytes = FNAME_BUFSIZE-1;
|
||||
if (nbytes >= MAXPGPATH)
|
||||
nbytes = MAXPGPATH-1;
|
||||
memcpy(fnamebuf, VARDATA(filename), nbytes);
|
||||
fnamebuf[nbytes] = '\0';
|
||||
oumask = umask((mode_t) 0022);
|
||||
@ -473,12 +467,12 @@ lo_export(PG_FUNCTION_ARGS)
|
||||
fnamebuf);
|
||||
|
||||
/*
|
||||
* read in from the Unix file and write to the inversion file
|
||||
* read in from the inversion file and write to the Unix file
|
||||
*/
|
||||
while ((nbytes = inv_read(lobj, buf, BUFSIZE)) > 0)
|
||||
{
|
||||
tmp = FileWrite(fd, buf, nbytes);
|
||||
if (tmp < nbytes)
|
||||
if (tmp != nbytes)
|
||||
elog(ERROR, "lo_export: error while writing \"%s\"",
|
||||
fnamebuf);
|
||||
}
|
||||
@ -513,7 +507,7 @@ lo_commit(bool isCommit)
|
||||
if (cookies[i] != NULL)
|
||||
{
|
||||
if (isCommit)
|
||||
inv_cleanindex(cookies[i]);
|
||||
inv_close(cookies[i]);
|
||||
cookies[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.174 2000/10/22 23:16:55 pjw Exp $
|
||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.175 2000/10/24 01:38:32 tgl Exp $
|
||||
*
|
||||
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
|
||||
*
|
||||
@ -1104,7 +1104,7 @@ dumpBlobs(Archive *AH, char* junkOid, void *junkVal)
|
||||
fprintf(stderr, "%s saving BLOBs\n", g_comment_start);
|
||||
|
||||
/* Cursor to get all BLOB tables */
|
||||
appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT oid from pg_class where relkind = '%c'", RELKIND_LOBJECT);
|
||||
appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT DISTINCT loid FROM pg_largeobject");
|
||||
|
||||
res = PQexec(g_conn, oidQry->data);
|
||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
@ -1874,8 +1874,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
|
||||
* tables before the child tables when traversing the tblinfo*
|
||||
*
|
||||
* we ignore tables that are not type 'r' (ordinary relation) or 'S'
|
||||
* (sequence) or 'v' (view) --- in particular, Large Object
|
||||
* relations (type 'l') are ignored.
|
||||
* (sequence) or 'v' (view).
|
||||
*/
|
||||
|
||||
appendPQExpBuffer(query,
|
||||
@ -1886,7 +1885,6 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
|
||||
"where relname !~ '^pg_' "
|
||||
"and relkind in ('%c', '%c', '%c') "
|
||||
"order by oid",
|
||||
RELKIND_VIEW,
|
||||
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
|
||||
|
||||
res = PQexec(g_conn, query->data);
|
||||
@ -2585,7 +2583,7 @@ getIndices(int *numIndices)
|
||||
* find all the user-defined indices. We do not handle partial
|
||||
* indices.
|
||||
*
|
||||
* Notice we skip indices on inversion objects (relkind 'l')
|
||||
* Notice we skip indices on system classes
|
||||
*
|
||||
* this is a 4-way join !!
|
||||
*/
|
||||
@ -2597,8 +2595,8 @@ getIndices(int *numIndices)
|
||||
"from pg_index i, pg_class t1, pg_class t2, pg_am a "
|
||||
"WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
|
||||
"and t1.relam = a.oid and i.indexrelid > '%u'::oid "
|
||||
"and t2.relname !~ '^pg_' and t2.relkind != '%c' and not i.indisprimary",
|
||||
g_last_builtin_oid, RELKIND_LOBJECT);
|
||||
"and t2.relname !~ '^pg_' and not i.indisprimary",
|
||||
g_last_builtin_oid);
|
||||
|
||||
res = PQexec(g_conn, query->data);
|
||||
if (!res ||
|
||||
|
@ -59,7 +59,7 @@ proc update_attnvals {conn rel} {
|
||||
proc updateStats { dbName } {
|
||||
# datnames is the list to be result
|
||||
set conn [pg_connect $dbName]
|
||||
set res [pg_exec $conn "SELECT relname FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_' and relname !~ '^xinv'"]
|
||||
set res [pg_exec $conn "SELECT relname FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_'"]
|
||||
set ntups [pg_result $res -numTuples]
|
||||
for {set i 0} {$i < $ntups} {incr i} {
|
||||
set rel [pg_result $res -getTuple $i]
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2000 by PostgreSQL Global Development Group
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.24 2000/09/07 04:55:27 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.25 2000/10/24 01:38:38 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "describe.h"
|
||||
@ -1020,10 +1020,6 @@ listTables(const char *infotype, const char *name, bool desc)
|
||||
strcat(buf, "'S'");
|
||||
strcat(buf, ")\n");
|
||||
|
||||
/* ignore large-obj indices */
|
||||
if (showIndices)
|
||||
strcat(buf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
|
||||
|
||||
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||
if (name)
|
||||
{
|
||||
@ -1050,10 +1046,6 @@ listTables(const char *infotype, const char *name, bool desc)
|
||||
strcat(buf, "'S'");
|
||||
strcat(buf, ")\n");
|
||||
|
||||
/* ignore large-obj indices */
|
||||
if (showIndices)
|
||||
strcat(buf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
|
||||
|
||||
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||
if (name)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2000 by PostgreSQL Global Development Group
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.10 2000/04/12 17:16:22 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.11 2000/10/24 01:38:39 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "large_obj.h"
|
||||
@ -193,7 +193,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
||||
/* insert description if given */
|
||||
if (comment_arg)
|
||||
{
|
||||
sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
|
||||
sprintf(buf, "INSERT INTO pg_description VALUES (%u, '", loid);
|
||||
for (i = 0; i < strlen(comment_arg); i++)
|
||||
if (comment_arg[i] == '\'')
|
||||
strcat(buf, "\\'");
|
||||
@ -284,7 +284,7 @@ do_lo_unlink(const char *loid_arg)
|
||||
}
|
||||
|
||||
/* remove the comment as well */
|
||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
|
||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %u", loid);
|
||||
if (!(res = PSQLexec(buf)))
|
||||
{
|
||||
if (own_transaction)
|
||||
@ -328,15 +328,9 @@ do_lo_list(void)
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
strcpy(buf,
|
||||
"SELECT usename as \"Owner\", substring(relname from 5) as \"ID\",\n"
|
||||
" obj_description(pg_class.oid) as \"Description\"\n"
|
||||
"FROM pg_class, pg_user\n"
|
||||
"WHERE usesysid = relowner AND relkind = 'l'\n"
|
||||
"UNION\n"
|
||||
"SELECT NULL as \"Owner\", substring(relname from 5) as \"ID\",\n"
|
||||
" obj_description(pg_class.oid) as \"Description\"\n"
|
||||
"FROM pg_class\n"
|
||||
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'\n"
|
||||
"SELECT DISTINCT loid as \"ID\",\n"
|
||||
" obj_description(loid) as \"Description\"\n"
|
||||
"FROM pg_largeobject\n"
|
||||
"ORDER BY \"ID\"");
|
||||
|
||||
res = PSQLexec(buf);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catname.h,v 1.16 2000/10/22 05:27:20 momjian Exp $
|
||||
* $Id: catname.h,v 1.17 2000/10/24 01:38:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,6 +29,7 @@
|
||||
#define InheritsRelationName "pg_inherits"
|
||||
#define InheritancePrecidenceListRelationName "pg_ipl"
|
||||
#define LanguageRelationName "pg_language"
|
||||
#define LargeObjectRelationName "pg_largeobject"
|
||||
#define ListenerRelationName "pg_listener"
|
||||
#define LogRelationName "pg_log"
|
||||
#define OperatorClassRelationName "pg_opclass"
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catversion.h,v 1.51 2000/10/22 17:55:49 pjw Exp $
|
||||
* $Id: catversion.h,v 1.52 2000/10/24 01:38:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200010231
|
||||
#define CATALOG_VERSION_NO 200010232
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: indexing.h,v 1.44 2000/10/22 05:27:20 momjian Exp $
|
||||
* $Id: indexing.h,v 1.45 2000/10/24 01:38:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,6 +31,7 @@
|
||||
#define Num_pg_index_indices 2
|
||||
#define Num_pg_inherits_indices 1
|
||||
#define Num_pg_language_indices 2
|
||||
#define Num_pg_largeobject_indices 1
|
||||
#define Num_pg_listener_indices 1
|
||||
#define Num_pg_opclass_indices 2
|
||||
#define Num_pg_operator_indices 2
|
||||
@ -62,6 +63,7 @@
|
||||
#define InheritsRelidSeqnoIndex "pg_inherits_relid_seqno_index"
|
||||
#define LanguageNameIndex "pg_language_name_index"
|
||||
#define LanguageOidIndex "pg_language_oid_index"
|
||||
#define LargeObjectLOidPNIndex "pg_largeobject_loid_pn_index"
|
||||
#define ListenerPidRelnameIndex "pg_listener_pid_relname_index"
|
||||
#define OpclassDeftypeIndex "pg_opclass_deftype_index"
|
||||
#define OpclassNameIndex "pg_opclass_name_index"
|
||||
@ -92,6 +94,7 @@ extern char *Name_pg_group_indices[];
|
||||
extern char *Name_pg_index_indices[];
|
||||
extern char *Name_pg_inherits_indices[];
|
||||
extern char *Name_pg_language_indices[];
|
||||
extern char *Name_pg_largeobject_indices[];
|
||||
extern char *Name_pg_listener_indices[];
|
||||
extern char *Name_pg_opclass_indices[];
|
||||
extern char *Name_pg_operator_indices[];
|
||||
@ -191,6 +194,7 @@ DECLARE_UNIQUE_INDEX(pg_index_indexrelid_index on pg_index using btree(indexreli
|
||||
DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops));
|
||||
DECLARE_UNIQUE_INDEX(pg_language_name_index on pg_language using btree(lanname name_ops));
|
||||
DECLARE_UNIQUE_INDEX(pg_language_oid_index on pg_language using btree(oid oid_ops));
|
||||
DECLARE_UNIQUE_INDEX(pg_largeobject_loid_pn_index on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
|
||||
DECLARE_UNIQUE_INDEX(pg_listener_pid_relname_index on pg_listener using btree(listenerpid int4_ops, relname name_ops));
|
||||
/* This column needs to allow multiple zero entries, but is in the cache */
|
||||
DECLARE_INDEX(pg_opclass_deftype_index on pg_opclass using btree(opcdeftype oid_ops));
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_class.h,v 1.43 2000/10/22 17:55:49 pjw Exp $
|
||||
* $Id: pg_class.h,v 1.44 2000/10/24 01:38:41 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -174,7 +174,6 @@ DESCR("");
|
||||
#define XactLockTableId 376
|
||||
|
||||
#define RELKIND_INDEX 'i' /* secondary index */
|
||||
#define RELKIND_LOBJECT 'l' /* large objects */
|
||||
#define RELKIND_RELATION 'r' /* ordinary cataloged heap */
|
||||
#define RELKIND_SPECIAL 's' /* special (non-heap) */
|
||||
#define RELKIND_SEQUENCE 'S' /* SEQUENCE relation */
|
||||
|
63
src/include/catalog/pg_largeobject.h
Normal file
63
src/include/catalog/pg_largeobject.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_largeobject.h
|
||||
* definition of the system "largeobject" relation (pg_largeobject)
|
||||
* along with the relation's initial contents.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_largeobject.h,v 1.5 2000/10/24 01:38:41 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
* information from the DATA() statements.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PG_LARGEOBJECT_H
|
||||
#define PG_LARGEOBJECT_H
|
||||
|
||||
/* ----------------
|
||||
* postgres.h contains the system type definintions and the
|
||||
* CATALOG(), BOOTSTRAP and DATA() sugar words so this file
|
||||
* can be read by both genbki.sh and the C compiler.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* pg_largeobject definition. cpp turns this into
|
||||
* typedef struct FormData_pg_largeobject. Large object id
|
||||
* is stored in loid;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
CATALOG(pg_largeobject)
|
||||
{
|
||||
Oid loid; /* Identifier of large object */
|
||||
int4 pageno; /* Page number (starting from 0) */
|
||||
bytea data; /* Data for page (may be zero-length) */
|
||||
} FormData_pg_largeobject;
|
||||
|
||||
/* ----------------
|
||||
* Form_pg_largeobject corresponds to a pointer to a tuple with
|
||||
* the format of pg_largeobject relation.
|
||||
* ----------------
|
||||
*/
|
||||
typedef FormData_pg_largeobject *Form_pg_largeobject;
|
||||
|
||||
/* ----------------
|
||||
* compiler constants for pg_largeobject
|
||||
* ----------------
|
||||
*/
|
||||
#define Natts_pg_largeobject 3
|
||||
#define Anum_pg_largeobject_loid 1
|
||||
#define Anum_pg_largeobject_pageno 2
|
||||
#define Anum_pg_largeobject_data 3
|
||||
|
||||
extern Oid LargeObjectCreate(Oid loid);
|
||||
extern void LargeObjectDrop(Oid loid);
|
||||
extern bool LargeObjectExists(Oid loid);
|
||||
|
||||
#endif /* PG_LARGEOBJECT_H */
|
@ -8,39 +8,54 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: large_object.h,v 1.17 2000/10/22 05:27:23 momjian Exp $
|
||||
* $Id: large_object.h,v 1.18 2000/10/24 01:38:43 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef LARGE_OBJECT_H
|
||||
#define LARGE_OBJECT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "utils/rel.h"
|
||||
|
||||
#include "access/relscan.h"
|
||||
|
||||
/*
|
||||
* This structure will eventually have lots more stuff associated with it.
|
||||
/*----------
|
||||
* Data about a currently-open large object.
|
||||
*
|
||||
* id is the logical OID of the large object
|
||||
* offset is the current seek offset within the LO
|
||||
* heap_r holds an open-relation reference to pg_largeobject
|
||||
* index_r holds an open-relation reference to pg_largeobject_loid_pn_index
|
||||
*
|
||||
* NOTE: before 7.1, heap_r and index_r held references to the separate
|
||||
* table and index of a specific large object. Now they all live in one rel.
|
||||
*----------
|
||||
*/
|
||||
typedef struct LargeObjectDesc
|
||||
{
|
||||
Relation heap_r; /* heap relation */
|
||||
Relation index_r; /* index relation on seqno attribute */
|
||||
IndexScanDesc iscan; /* index scan we're using */
|
||||
TupleDesc hdesc; /* heap relation tuple desc */
|
||||
TupleDesc idesc; /* index relation tuple desc */
|
||||
uint32 lowbyte; /* low byte on the current page */
|
||||
uint32 highbyte; /* high byte on the current page */
|
||||
typedef struct LargeObjectDesc {
|
||||
Oid id;
|
||||
uint32 offset; /* current seek pointer */
|
||||
ItemPointerData htid; /* tid of current heap tuple */
|
||||
int flags; /* locking info, etc */
|
||||
|
||||
/* flag bits: */
|
||||
#define IFS_RDLOCK (1 << 0)
|
||||
#define IFS_WRLOCK (1 << 1)
|
||||
#define IFS_ATEOF (1 << 2)
|
||||
|
||||
u_long flags; /* locking info, etc */
|
||||
Relation heap_r;
|
||||
Relation index_r;
|
||||
} LargeObjectDesc;
|
||||
|
||||
|
||||
/*
|
||||
* Each "page" (tuple) of a large object can hold this much data
|
||||
*
|
||||
* Calculation is max tuple size less tuple header, loid field (Oid),
|
||||
* pageno field (int32), and varlena header of data (int32). Note we
|
||||
* assume none of the fields will be NULL, hence no need for null bitmap.
|
||||
*/
|
||||
#define LOBLKSIZE (MaxTupleSize \
|
||||
- MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) \
|
||||
- sizeof(Oid) - sizeof(int32) * 2)
|
||||
|
||||
|
||||
/*
|
||||
* Function definitions...
|
||||
*/
|
||||
@ -55,7 +70,4 @@ extern int inv_tell(LargeObjectDesc *obj_desc);
|
||||
extern int inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes);
|
||||
extern int inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes);
|
||||
|
||||
/* added for buffer leak prevention [ PA ] */
|
||||
extern void inv_cleanindex(LargeObjectDesc *obj_desc);
|
||||
|
||||
#endif /* LARGE_OBJECT_H */
|
||||
|
@ -1007,8 +1007,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
|
||||
}
|
||||
|
||||
|
||||
/* filter out large objects unconditionally (they are not system tables) and match users */
|
||||
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
|
||||
/* match users */
|
||||
strcat(tables_query, " and usesysid = relowner");
|
||||
strcat(tables_query, " order by relname");
|
||||
|
||||
|
@ -482,8 +482,8 @@ WHERE p1.aggtransfn = p2.oid AND
|
||||
(p2.pronargs = 1 AND p1.aggbasetype = 0)));
|
||||
oid | aggname | oid | proname
|
||||
-------+---------+-----+-------------
|
||||
16984 | max | 768 | int4larger
|
||||
16998 | min | 769 | int4smaller
|
||||
16996 | max | 768 | int4larger
|
||||
17010 | min | 769 | int4smaller
|
||||
(2 rows)
|
||||
|
||||
-- Cross-check finalfn (if present) against its entry in pg_proc.
|
||||
|
@ -40,6 +40,7 @@ SELECT relname, relhasindex
|
||||
pg_index | t
|
||||
pg_inherits | t
|
||||
pg_language | t
|
||||
pg_largeobject | t
|
||||
pg_listener | t
|
||||
pg_opclass | t
|
||||
pg_operator | t
|
||||
@ -54,5 +55,5 @@ SELECT relname, relhasindex
|
||||
shighway | t
|
||||
tenk1 | t
|
||||
tenk2 | t
|
||||
(44 rows)
|
||||
(45 rows)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user