Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a2fb7b8

Browse files
committed
Adjust lo_open() so that specifying INV_READ without INV_WRITE creates
a descriptor that uses the current transaction snapshot, rather than SnapshotNow as it did before (and still does if INV_WRITE is set). This means pg_dump will now dump a consistent snapshot of large object contents, as it never could do before. Also, add a lo_create() function that is similar to lo_creat() but allows the desired OID of the large object to be specified. This will simplify pg_restore considerably (but I'll fix that in a separate commit).
1 parent f52a342 commit a2fb7b8

File tree

11 files changed

+265
-96
lines changed

11 files changed

+265
-96
lines changed

doc/src/sgml/lobj.sgml

+74-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.36 2005/01/10 00:04:38 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.37 2005/06/13 02:26:46 tgl Exp $
33
-->
44

55
<chapter id="largeObjects">
@@ -115,26 +115,52 @@ $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.36 2005/01/10 00:04:38 tgl Exp $
115115
Oid lo_creat(PGconn *conn, int mode);
116116
</synopsis>
117117
<indexterm><primary>lo_creat</></>
118-
creates a new large object.
119-
<replaceable class="parameter">mode</replaceable> is a bit mask
120-
describing several different attributes of the new
121-
object. The symbolic constants used here are defined
122-
in the header file <filename>libpq/libpq-fs.h</filename>.
123-
The access type (read, write, or both) is controlled by
124-
or'ing together the bits <symbol>INV_READ</symbol> and
125-
<symbol>INV_WRITE</symbol>. The low-order sixteen bits of the mask have
126-
historically been used at Berkeley to designate the storage manager number on which the large object
127-
should reside. These bits should always be zero now. (The access type
128-
does not actually do anything anymore either, but one or both flag bits
129-
must be set to avoid an error.)
118+
creates a new large object.
130119
The return value is the OID that was assigned to the new large object,
131120
or InvalidOid (zero) on failure.
121+
122+
<replaceable class="parameter">mode</replaceable> is unused and
123+
ignored as of <productname>PostgreSQL</productname> 8.1; however, for
124+
backwards compatibility with earlier releases it is best to
125+
set it to <symbol>INV_READ</symbol>, <symbol>INV_WRITE</symbol>,
126+
or <symbol>INV_READ</symbol> <literal>|</> <symbol>INV_WRITE</symbol>.
127+
(These symbolic constants are defined
128+
in the header file <filename>libpq/libpq-fs.h</filename>.)
132129
</para>
133130

134131
<para>
135132
An example:
136133
<programlisting>
137134
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);
135+
</programlisting>
136+
</para>
137+
138+
<para>
139+
The function
140+
<synopsis>
141+
Oid lo_create(PGconn *conn, Oid lobjId);
142+
</synopsis>
143+
<indexterm><primary>lo_create</></>
144+
also creates a new large object. The OID to be assigned can be
145+
specified by <replaceable class="parameter">lobjId</replaceable>;
146+
if so, failure occurs if that OID is already in use for some large
147+
object. If <replaceable class="parameter">lobjId</replaceable>
148+
is InvalidOid (zero) then <function>lo_create</> assigns an unused
149+
OID (this is the same behavior as <function>lo_creat</>).
150+
The return value is the OID that was assigned to the new large object,
151+
or InvalidOid (zero) on failure.
152+
</para>
153+
154+
<para>
155+
<function>lo_create</> is new as of <productname>PostgreSQL</productname>
156+
8.1; if this function is run against an older server version, it will
157+
fail and return InvalidOid.
158+
</para>
159+
160+
<para>
161+
An example:
162+
<programlisting>
163+
inv_oid = lo_create(conn, desired_oid);
138164
</programlisting>
139165
</para>
140166
</sect2>
@@ -186,19 +212,45 @@ int lo_export(PGconn *conn, Oid lobjId, const char *filename);
186212
int lo_open(PGconn *conn, Oid lobjId, int mode);
187213
</synopsis>
188214
<indexterm><primary>lo_open</></>
189-
The <parameter>lobjId</parameter> argument specifies the OID of the large
190-
object to open. The <parameter>mode</parameter> bits control whether the
191-
object is opened for reading (<symbol>INV_READ</>), writing (<symbol>INV_WRITE</symbol>), or
192-
both.
193-
A large object cannot be opened before it is created.
215+
The <parameter>lobjId</parameter> argument specifies the OID of the large
216+
object to open. The <parameter>mode</parameter> bits control whether the
217+
object is opened for reading (<symbol>INV_READ</>), writing
218+
(<symbol>INV_WRITE</symbol>), or both.
219+
(These symbolic constants are defined
220+
in the header file <filename>libpq/libpq-fs.h</filename>.)
221+
A large object cannot be opened before it is created.
194222
<function>lo_open</function> returns a (non-negative) large object
195223
descriptor for later use in <function>lo_read</function>,
196224
<function>lo_write</function>, <function>lo_lseek</function>,
197225
<function>lo_tell</function>, and <function>lo_close</function>.
198226
The descriptor is only valid for
199227
the duration of the current transaction.
200228
On failure, -1 is returned.
201-
</para>
229+
</para>
230+
231+
<para>
232+
The server currently does not distinguish between modes
233+
<symbol>INV_WRITE</symbol> and <symbol>INV_READ</> <literal>|</>
234+
<symbol>INV_WRITE</symbol>: you are allowed to read from the descriptor
235+
in either case. However there is a significant difference between
236+
these modes and <symbol>INV_READ</> alone: with <symbol>INV_READ</>
237+
you cannot write on the descriptor, and the data read from it will
238+
reflect the contents of the large object at the time of the transaction
239+
snapshot that was active when <function>lo_open</> was executed,
240+
regardless of later writes by this or other transactions. Reading
241+
from a descriptor opened with <symbol>INV_WRITE</symbol> returns
242+
data that reflects all writes of other committed transactions as well
243+
as writes of the current transaction. This is similar to the behavior
244+
of <literal>SERIALIZABLE</> versus <literal>READ COMMITTED</> transaction
245+
modes for ordinary SQL <command>SELECT</> commands.
246+
</para>
247+
248+
<para>
249+
An example:
250+
<programlisting>
251+
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
252+
</programlisting>
253+
</para>
202254
</sect2>
203255

204256
<sect2>
@@ -317,6 +369,7 @@ int lo_unlink(PGconn *conn, Oid lobjId);
317369
equivalent server-side functions. The ones that are actually useful
318370
to call via SQL commands are
319371
<function>lo_creat</function><indexterm><primary>lo_creat</></>,
372+
<function>lo_create</function><indexterm><primary>lo_create</></>,
320373
<function>lo_unlink</function><indexterm><primary>lo_unlink</></>,
321374
<function>lo_import</function><indexterm><primary>lo_import</></>, and
322375
<function>lo_export</function><indexterm><primary>lo_export</></>.
@@ -330,6 +383,8 @@ CREATE TABLE image (
330383

331384
SELECT lo_creat(-1); -- returns OID of new, empty large object
332385

386+
SELECT lo_create(43213); -- attempts to create large object with OID 43213
387+
333388
SELECT lo_unlink(173454); -- deletes large object with OID 173454
334389

335390
INSERT INTO image (name, raster)

src/backend/libpq/be-fsstubs.c

+30-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.77 2004/12/31 21:59:50 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.78 2005/06/13 02:26:48 tgl Exp $
1212
*
1313
* NOTES
1414
* This should be moved to a more appropriate place. It is here
@@ -195,6 +195,12 @@ lo_write(int fd, char *buf, int len)
195195
return -1;
196196
}
197197

198+
if ((cookies[fd]->flags & IFS_WRLOCK) == 0)
199+
ereport(ERROR,
200+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
201+
errmsg("large object descriptor %d was not opened for writing",
202+
fd)));
203+
198204
Assert(fscxt != NULL);
199205
currentContext = MemoryContextSwitchTo(fscxt);
200206

@@ -236,26 +242,33 @@ lo_lseek(PG_FUNCTION_ARGS)
236242
Datum
237243
lo_creat(PG_FUNCTION_ARGS)
238244
{
239-
int32 mode = PG_GETARG_INT32(0);
240-
LargeObjectDesc *lobjDesc;
241-
MemoryContext currentContext;
242245
Oid lobjId;
246+
MemoryContext currentContext;
243247

248+
/* do we actually need fscxt for this? */
244249
CreateFSContext();
245250

246251
currentContext = MemoryContextSwitchTo(fscxt);
247252

248-
lobjDesc = inv_create(mode);
253+
lobjId = inv_create(InvalidOid);
249254

250-
if (lobjDesc == NULL)
251-
{
252-
MemoryContextSwitchTo(currentContext);
253-
PG_RETURN_OID(InvalidOid);
254-
}
255+
MemoryContextSwitchTo(currentContext);
256+
257+
PG_RETURN_OID(lobjId);
258+
}
259+
260+
Datum
261+
lo_create(PG_FUNCTION_ARGS)
262+
{
263+
Oid lobjId = PG_GETARG_OID(0);
264+
MemoryContext currentContext;
255265

256-
lobjId = lobjDesc->id;
266+
/* do we actually need fscxt for this? */
267+
CreateFSContext();
268+
269+
currentContext = MemoryContextSwitchTo(fscxt);
257270

258-
inv_close(lobjDesc);
271+
lobjId = inv_create(lobjId);
259272

260273
MemoryContextSwitchTo(currentContext);
261274

@@ -403,12 +416,13 @@ lo_import(PG_FUNCTION_ARGS)
403416
/*
404417
* create an inversion object
405418
*/
406-
lobj = inv_create(INV_READ | INV_WRITE);
407-
lobjOid = lobj->id;
419+
lobjOid = inv_create(InvalidOid);
408420

409421
/*
410-
* read in from the filesystem and write to the inversion file
422+
* read in from the filesystem and write to the inversion object
411423
*/
424+
lobj = inv_open(lobjOid, INV_WRITE);
425+
412426
while ((nbytes = FileRead(fd, buf, BUFSIZE)) > 0)
413427
{
414428
tmp = inv_write(lobj, buf, nbytes);
@@ -421,8 +435,8 @@ lo_import(PG_FUNCTION_ARGS)
421435
errmsg("could not read server file \"%s\": %m",
422436
fnamebuf)));
423437

424-
FileClose(fd);
425438
inv_close(lobj);
439+
FileClose(fd);
426440

427441
PG_RETURN_OID(lobjOid);
428442
}

0 commit comments

Comments
 (0)