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:
Tom Lane 2000-10-24 01:38:44 +00:00
parent d7186cfa9b
commit 4f44aa04b5
21 changed files with 735 additions and 1205 deletions

View File

@ -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)) {

View File

@ -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");

View File

@ -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>

View File

@ -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 \
)

View File

@ -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] =

View 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;
}

View File

@ -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

View File

@ -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 ||

View File

@ -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]

View File

@ -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)
{

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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));

View File

@ -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 */

View 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 */

View File

@ -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 */

View File

@ -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");

View File

@ -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.

View File

@ -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)