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
0763a565
Commit
0763a565
authored
Mar 03, 2007
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add lo_truncate() to backend and libpq for large object truncation.
Kris Jurka
parent
90d76525
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
372 additions
and
26 deletions
+372
-26
doc/src/sgml/lobj.sgml
doc/src/sgml/lobj.sgml
+32
-1
src/backend/libpq/be-fsstubs.c
src/backend/libpq/be-fsstubs.c
+22
-16
src/backend/storage/large_object/inv_api.c
src/backend/storage/large_object/inv_api.c
+164
-1
src/include/catalog/pg_proc.h
src/include/catalog/pg_proc.h
+3
-1
src/include/libpq/be-fsstubs.h
src/include/libpq/be-fsstubs.h
+2
-1
src/include/storage/large_object.h
src/include/storage/large_object.h
+2
-1
src/interfaces/libpq/exports.txt
src/interfaces/libpq/exports.txt
+2
-1
src/interfaces/libpq/fe-lobj.c
src/interfaces/libpq/fe-lobj.c
+58
-2
src/interfaces/libpq/libpq-fe.h
src/interfaces/libpq/libpq-fe.h
+2
-1
src/interfaces/libpq/libpq-int.h
src/interfaces/libpq/libpq-int.h
+2
-1
src/test/regress/input/largeobject.source
src/test/regress/input/largeobject.source
+19
-0
src/test/regress/output/largeobject.source
src/test/regress/output/largeobject.source
+64
-0
No files found.
doc/src/sgml/lobj.sgml
View file @
0763a565
<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.4
4 2007/02/01 19:10:24
momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.4
5 2007/03/03 19:52:45
momjian Exp $ -->
<chapter id="largeObjects">
<chapter id="largeObjects">
<title id="largeObjects-title">Large Objects</title>
<title id="largeObjects-title">Large Objects</title>
...
@@ -301,6 +301,37 @@ int lo_tell(PGconn *conn, int fd);
...
@@ -301,6 +301,37 @@ int lo_tell(PGconn *conn, int fd);
</para>
</para>
</sect2>
</sect2>
<sect2>
<title>Truncating a Large Object</title>
<para>
To truncate a large object to a given length, call
<synopsis>
int lo_truncate(PGcon *conn, int fd, size_t len);
</synopsis>
<indexterm><primary>lo_truncate</></> truncates the large object
descriptor <parameter>fd</> to length <parameter>len</>. The
<parameter>fd</parameter> argument must have been returned by a
previous <function>lo_open</function>. If <parameter>len</> is
greater than the current large object length, the large object
is extended with null bytes ('\0').
</para>
<para>
The file offset is not changed.
</para>
<para>
On success <function>lo_truncate</function> returns
zero. On error, the return value is negative.
</para>
<para>
<function>lo_truncate</> is new as of <productname>PostgreSQL</productname>
8.3; if this function is run against an older server version, it will
fail and return a negative value.
</para>
<sect2>
<sect2>
<title>Closing a Large Object Descriptor</title>
<title>Closing a Large Object Descriptor</title>
...
...
src/backend/libpq/be-fsstubs.c
View file @
0763a565
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.8
5 2007/02/27 23:48:07 tgl
Exp $
* $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.8
6 2007/03/03 19:52:46 momjian
Exp $
*
*
* NOTES
* NOTES
* This should be moved to a more appropriate place. It is here
* This should be moved to a more appropriate place. It is here
...
@@ -120,12 +120,10 @@ lo_close(PG_FUNCTION_ARGS)
...
@@ -120,12 +120,10 @@ lo_close(PG_FUNCTION_ARGS)
int32
fd
=
PG_GETARG_INT32
(
0
);
int32
fd
=
PG_GETARG_INT32
(
0
);
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
{
ereport
(
ERROR
,
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
PG_RETURN_INT32
(
-
1
);
}
#if FSDB
#if FSDB
elog
(
DEBUG4
,
"lo_close(%d)"
,
fd
);
elog
(
DEBUG4
,
"lo_close(%d)"
,
fd
);
#endif
#endif
...
@@ -152,12 +150,9 @@ lo_read(int fd, char *buf, int len)
...
@@ -152,12 +150,9 @@ lo_read(int fd, char *buf, int len)
int
status
;
int
status
;
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
{
ereport
(
ERROR
,
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
return
-
1
;
}
status
=
inv_read
(
cookies
[
fd
],
buf
,
len
);
status
=
inv_read
(
cookies
[
fd
],
buf
,
len
);
...
@@ -170,12 +165,9 @@ lo_write(int fd, const char *buf, int len)
...
@@ -170,12 +165,9 @@ lo_write(int fd, const char *buf, int len)
int
status
;
int
status
;
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
{
ereport
(
ERROR
,
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
return
-
1
;
}
if
((
cookies
[
fd
]
->
flags
&
IFS_WRLOCK
)
==
0
)
if
((
cookies
[
fd
]
->
flags
&
IFS_WRLOCK
)
==
0
)
ereport
(
ERROR
,
ereport
(
ERROR
,
...
@@ -198,12 +190,9 @@ lo_lseek(PG_FUNCTION_ARGS)
...
@@ -198,12 +190,9 @@ lo_lseek(PG_FUNCTION_ARGS)
int
status
;
int
status
;
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
{
ereport
(
ERROR
,
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
PG_RETURN_INT32
(
-
1
);
}
status
=
inv_seek
(
cookies
[
fd
],
offset
,
whence
);
status
=
inv_seek
(
cookies
[
fd
],
offset
,
whence
);
...
@@ -248,12 +237,9 @@ lo_tell(PG_FUNCTION_ARGS)
...
@@ -248,12 +237,9 @@ lo_tell(PG_FUNCTION_ARGS)
int32
fd
=
PG_GETARG_INT32
(
0
);
int32
fd
=
PG_GETARG_INT32
(
0
);
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
{
ereport
(
ERROR
,
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
PG_RETURN_INT32
(
-
1
);
}
PG_RETURN_INT32
(
inv_tell
(
cookies
[
fd
]));
PG_RETURN_INT32
(
inv_tell
(
cookies
[
fd
]));
}
}
...
@@ -467,6 +453,26 @@ lo_export(PG_FUNCTION_ARGS)
...
@@ -467,6 +453,26 @@ lo_export(PG_FUNCTION_ARGS)
PG_RETURN_INT32
(
1
);
PG_RETURN_INT32
(
1
);
}
}
/*
* lo_truncate -
* truncate a large object to a specified length
*/
Datum
lo_truncate
(
PG_FUNCTION_ARGS
)
{
int32
fd
=
PG_GETARG_INT32
(
0
);
int32
len
=
PG_GETARG_INT32
(
1
);
if
(
fd
<
0
||
fd
>=
cookies_size
||
cookies
[
fd
]
==
NULL
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"invalid large-object descriptor: %d"
,
fd
)));
inv_truncate
(
cookies
[
fd
],
len
);
PG_RETURN_INT32
(
0
);
}
/*
/*
* AtEOXact_LargeObject -
* AtEOXact_LargeObject -
* prepares large objects for transaction commit
* prepares large objects for transaction commit
...
...
src/backend/storage/large_object/inv_api.c
View file @
0763a565
...
@@ -17,7 +17,7 @@
...
@@ -17,7 +17,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.12
2 2007/02/27 23:48:07 tgl
Exp $
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.12
3 2007/03/03 19:52:46 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -681,3 +681,166 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
...
@@ -681,3 +681,166 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
return
nwritten
;
return
nwritten
;
}
}
void
inv_truncate
(
LargeObjectDesc
*
obj_desc
,
int
len
)
{
int32
pageno
=
(
int32
)
(
len
/
LOBLKSIZE
);
int
off
;
ScanKeyData
skey
[
2
];
IndexScanDesc
sd
;
HeapTuple
oldtuple
;
Form_pg_largeobject
olddata
;
struct
{
bytea
hdr
;
char
data
[
LOBLKSIZE
];
}
workbuf
;
char
*
workb
=
VARDATA
(
&
workbuf
.
hdr
);
HeapTuple
newtup
;
Datum
values
[
Natts_pg_largeobject
];
char
nulls
[
Natts_pg_largeobject
];
char
replace
[
Natts_pg_largeobject
];
CatalogIndexState
indstate
;
Assert
(
PointerIsValid
(
obj_desc
));
/* enforce writability because snapshot is probably wrong otherwise */
if
((
obj_desc
->
flags
&
IFS_WRLOCK
)
==
0
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"large object %u was not opened for writing"
,
obj_desc
->
id
)));
open_lo_relation
();
indstate
=
CatalogOpenIndexes
(
lo_heap_r
);
ScanKeyInit
(
&
skey
[
0
],
Anum_pg_largeobject_loid
,
BTEqualStrategyNumber
,
F_OIDEQ
,
ObjectIdGetDatum
(
obj_desc
->
id
));
ScanKeyInit
(
&
skey
[
1
],
Anum_pg_largeobject_pageno
,
BTGreaterEqualStrategyNumber
,
F_INT4GE
,
Int32GetDatum
(
pageno
));
sd
=
index_beginscan
(
lo_heap_r
,
lo_index_r
,
obj_desc
->
snapshot
,
2
,
skey
);
/*
* If possible, get the page the truncation point is in.
* The truncation point may be beyond the end of the LO or
* in a hole.
*/
olddata
=
NULL
;
if
((
oldtuple
=
index_getnext
(
sd
,
ForwardScanDirection
))
!=
NULL
)
{
olddata
=
(
Form_pg_largeobject
)
GETSTRUCT
(
oldtuple
);
Assert
(
olddata
->
pageno
>=
pageno
);
}
/*
* If we found the page of the truncation point we need to
* truncate the data in it. Otherwise if we're in a hole,
* we need to create a page to mark the end of data.
*/
if
(
olddata
!=
NULL
&&
olddata
->
pageno
==
pageno
)
{
/* First, load old data into workbuf */
bytea
*
datafield
=
&
(
olddata
->
data
);
bool
pfreeit
=
false
;
int
pagelen
;
if
(
VARATT_IS_EXTENDED
(
datafield
))
{
datafield
=
(
bytea
*
)
heap_tuple_untoast_attr
((
varattrib
*
)
datafield
);
pfreeit
=
true
;
}
pagelen
=
getbytealen
(
datafield
);
Assert
(
pagelen
<=
LOBLKSIZE
);
memcpy
(
workb
,
VARDATA
(
datafield
),
pagelen
);
if
(
pfreeit
)
pfree
(
datafield
);
/*
* Fill any hole
*/
off
=
len
%
LOBLKSIZE
;
if
(
off
>
pagelen
)
MemSet
(
workb
+
pagelen
,
0
,
off
-
pagelen
);
/* compute length of new page */
SET_VARSIZE
(
&
workbuf
.
hdr
,
off
+
VARHDRSZ
);
/*
* Form and insert updated tuple
*/
memset
(
values
,
0
,
sizeof
(
values
));
memset
(
nulls
,
' '
,
sizeof
(
nulls
));
memset
(
replace
,
' '
,
sizeof
(
replace
));
values
[
Anum_pg_largeobject_data
-
1
]
=
PointerGetDatum
(
&
workbuf
);
replace
[
Anum_pg_largeobject_data
-
1
]
=
'r'
;
newtup
=
heap_modifytuple
(
oldtuple
,
RelationGetDescr
(
lo_heap_r
),
values
,
nulls
,
replace
);
simple_heap_update
(
lo_heap_r
,
&
newtup
->
t_self
,
newtup
);
CatalogIndexInsert
(
indstate
,
newtup
);
heap_freetuple
(
newtup
);
}
else
{
/*
* If the first page we found was after the truncation
* point, we're in a hole that we'll fill, but we need to
* delete the later page.
*/
if
(
olddata
!=
NULL
&&
olddata
->
pageno
>
pageno
)
simple_heap_delete
(
lo_heap_r
,
&
oldtuple
->
t_self
);
/*
* Write a brand new page.
*
* Fill the hole up to the truncation point
*/
off
=
len
%
LOBLKSIZE
;
if
(
off
>
0
)
MemSet
(
workb
,
0
,
off
);
/* compute length of new page */
SET_VARSIZE
(
&
workbuf
.
hdr
,
off
+
VARHDRSZ
);
/*
* Form and insert new tuple
*/
memset
(
values
,
0
,
sizeof
(
values
));
memset
(
nulls
,
' '
,
sizeof
(
nulls
));
values
[
Anum_pg_largeobject_loid
-
1
]
=
ObjectIdGetDatum
(
obj_desc
->
id
);
values
[
Anum_pg_largeobject_pageno
-
1
]
=
Int32GetDatum
(
pageno
);
values
[
Anum_pg_largeobject_data
-
1
]
=
PointerGetDatum
(
&
workbuf
);
newtup
=
heap_formtuple
(
lo_heap_r
->
rd_att
,
values
,
nulls
);
simple_heap_insert
(
lo_heap_r
,
newtup
);
CatalogIndexInsert
(
indstate
,
newtup
);
heap_freetuple
(
newtup
);
}
/*
* Delete any pages after the truncation point
*/
while
((
oldtuple
=
index_getnext
(
sd
,
ForwardScanDirection
))
!=
NULL
)
{
simple_heap_delete
(
lo_heap_r
,
&
oldtuple
->
t_self
);
}
index_endscan
(
sd
);
CatalogCloseIndexes
(
indstate
);
/*
* Advance command counter so that tuple updates will be seen by later
* large-object operations in this transaction.
*/
CommandCounterIncrement
();
}
src/include/catalog/pg_proc.h
View file @
0763a565
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.44
6 2007/02/20 10:00:25 petere
Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.44
7 2007/03/03 19:52:46 momjian
Exp $
*
*
* NOTES
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
* The script catalog/genbki.sh reads this file and generates .bki
...
@@ -1233,6 +1233,8 @@ DATA(insert OID = 715 ( lo_create PGNSP PGUID 12 1 0 f f t f v 1 26 "26" _n
...
@@ -1233,6 +1233,8 @@ DATA(insert OID = 715 ( lo_create PGNSP PGUID 12 1 0 f f t f v 1 26 "26" _n
DESCR
(
"large object create"
);
DESCR
(
"large object create"
);
DATA
(
insert
OID
=
958
(
lo_tell
PGNSP
PGUID
12
1
0
f
f
t
f
v
1
23
"23"
_null_
_null_
_null_
lo_tell
-
_null_
));
DATA
(
insert
OID
=
958
(
lo_tell
PGNSP
PGUID
12
1
0
f
f
t
f
v
1
23
"23"
_null_
_null_
_null_
lo_tell
-
_null_
));
DESCR
(
"large object position"
);
DESCR
(
"large object position"
);
DATA
(
insert
OID
=
1004
(
lo_truncate
PGNSP
PGUID
12
1
0
f
f
t
f
v
2
23
"23 23"
_null_
_null_
_null_
lo_truncate
-
_null_
));
DESCR
(
"truncate large object"
);
DATA
(
insert
OID
=
959
(
on_pl
PGNSP
PGUID
12
1
0
f
f
t
f
i
2
16
"600 628"
_null_
_null_
_null_
on_pl
-
_null_
));
DATA
(
insert
OID
=
959
(
on_pl
PGNSP
PGUID
12
1
0
f
f
t
f
i
2
16
"600 628"
_null_
_null_
_null_
on_pl
-
_null_
));
DESCR
(
"point on line?"
);
DESCR
(
"point on line?"
);
...
...
src/include/libpq/be-fsstubs.h
View file @
0763a565
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/include/libpq/be-fsstubs.h,v 1.2
8 2007/01/05 22:19:55
momjian Exp $
* $PostgreSQL: pgsql/src/include/libpq/be-fsstubs.h,v 1.2
9 2007/03/03 19:52:46
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -34,6 +34,7 @@ extern Datum lowrite(PG_FUNCTION_ARGS);
...
@@ -34,6 +34,7 @@ extern Datum lowrite(PG_FUNCTION_ARGS);
extern
Datum
lo_lseek
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_lseek
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_tell
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_tell
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_unlink
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_unlink
(
PG_FUNCTION_ARGS
);
extern
Datum
lo_truncate
(
PG_FUNCTION_ARGS
);
/*
/*
* These are not fmgr-callable, but are available to C code.
* These are not fmgr-callable, but are available to C code.
...
...
src/include/storage/large_object.h
View file @
0763a565
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/include/storage/large_object.h,v 1.3
6 2007/01/05 22:19:58
momjian Exp $
* $PostgreSQL: pgsql/src/include/storage/large_object.h,v 1.3
7 2007/03/03 19:52:46
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -78,5 +78,6 @@ extern int inv_seek(LargeObjectDesc *obj_desc, int offset, int whence);
...
@@ -78,5 +78,6 @@ extern int inv_seek(LargeObjectDesc *obj_desc, int offset, int whence);
extern
int
inv_tell
(
LargeObjectDesc
*
obj_desc
);
extern
int
inv_tell
(
LargeObjectDesc
*
obj_desc
);
extern
int
inv_read
(
LargeObjectDesc
*
obj_desc
,
char
*
buf
,
int
nbytes
);
extern
int
inv_read
(
LargeObjectDesc
*
obj_desc
,
char
*
buf
,
int
nbytes
);
extern
int
inv_write
(
LargeObjectDesc
*
obj_desc
,
const
char
*
buf
,
int
nbytes
);
extern
int
inv_write
(
LargeObjectDesc
*
obj_desc
,
const
char
*
buf
,
int
nbytes
);
extern
void
inv_truncate
(
LargeObjectDesc
*
obj_desc
,
int
len
);
#endif
/* LARGE_OBJECT_H */
#endif
/* LARGE_OBJECT_H */
src/interfaces/libpq/exports.txt
View file @
0763a565
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.1
4 2006/08/18 19:52:39 tgl
Exp $
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.1
5 2007/03/03 19:52:46 momjian
Exp $
# Functions to be exported by libpq DLLs
# Functions to be exported by libpq DLLs
PQconnectdb 1
PQconnectdb 1
PQsetdbLogin 2
PQsetdbLogin 2
...
@@ -136,3 +136,4 @@ PQdescribePrepared 133
...
@@ -136,3 +136,4 @@ PQdescribePrepared 133
PQdescribePortal 134
PQdescribePortal 134
PQsendDescribePrepared 135
PQsendDescribePrepared 135
PQsendDescribePortal 136
PQsendDescribePortal 136
lo_truncate 137
src/interfaces/libpq/fe-lobj.c
View file @
0763a565
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.6
1 2007/01/05 22:20:01
momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.6
2 2007/03/03 19:52:46
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -122,6 +122,59 @@ lo_close(PGconn *conn, int fd)
...
@@ -122,6 +122,59 @@ lo_close(PGconn *conn, int fd)
}
}
}
}
/*
* lo_truncate
* truncates an existing large object to the given size
*
* returns 0 upon success
* returns -1 upon failure
*/
int
lo_truncate
(
PGconn
*
conn
,
int
fd
,
size_t
len
)
{
PQArgBlock
argv
[
2
];
PGresult
*
res
;
int
retval
;
int
result_len
;
if
(
conn
->
lobjfuncs
==
NULL
)
{
if
(
lo_initialize
(
conn
)
<
0
)
return
-
1
;
}
/* Must check this on-the-fly because it's not there pre-8.3 */
if
(
conn
->
lobjfuncs
->
fn_lo_truncate
==
0
)
{
printfPQExpBuffer
(
&
conn
->
errorMessage
,
libpq_gettext
(
"cannot determine OID of function lo_truncate
\n
"
));
return
-
1
;
}
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
argv
[
0
].
u
.
integer
=
fd
;
argv
[
1
].
isint
=
1
;
argv
[
1
].
len
=
4
;
argv
[
1
].
u
.
integer
=
len
;
res
=
PQfn
(
conn
,
conn
->
lobjfuncs
->
fn_lo_truncate
,
&
retval
,
&
result_len
,
1
,
argv
,
2
);
if
(
PQresultStatus
(
res
)
==
PGRES_COMMAND_OK
)
{
PQclear
(
res
);
return
retval
;
}
else
{
PQclear
(
res
);
return
-
1
;
}
}
/*
/*
* lo_read
* lo_read
* read len bytes of the large object into buf
* read len bytes of the large object into buf
...
@@ -621,6 +674,7 @@ lo_initialize(PGconn *conn)
...
@@ -621,6 +674,7 @@ lo_initialize(PGconn *conn)
/*
/*
* Execute the query to get all the functions at once. In 7.3 and later
* Execute the query to get all the functions at once. In 7.3 and later
* we need to be schema-safe. lo_create only exists in 8.1 and up.
* we need to be schema-safe. lo_create only exists in 8.1 and up.
* lo_truncate only exists in 8.3 and up.
*/
*/
if
(
conn
->
sversion
>=
70300
)
if
(
conn
->
sversion
>=
70300
)
query
=
"select proname, oid from pg_catalog.pg_proc "
query
=
"select proname, oid from pg_catalog.pg_proc "
...
@@ -632,6 +686,7 @@ lo_initialize(PGconn *conn)
...
@@ -632,6 +686,7 @@ lo_initialize(PGconn *conn)
"'lo_unlink', "
"'lo_unlink', "
"'lo_lseek', "
"'lo_lseek', "
"'lo_tell', "
"'lo_tell', "
"'lo_truncate', "
"'loread', "
"'loread', "
"'lowrite') "
"'lowrite') "
"and pronamespace = (select oid from pg_catalog.pg_namespace "
"and pronamespace = (select oid from pg_catalog.pg_namespace "
...
@@ -684,6 +739,8 @@ lo_initialize(PGconn *conn)
...
@@ -684,6 +739,8 @@ lo_initialize(PGconn *conn)
lobjfuncs
->
fn_lo_lseek
=
foid
;
lobjfuncs
->
fn_lo_lseek
=
foid
;
else
if
(
!
strcmp
(
fname
,
"lo_tell"
))
else
if
(
!
strcmp
(
fname
,
"lo_tell"
))
lobjfuncs
->
fn_lo_tell
=
foid
;
lobjfuncs
->
fn_lo_tell
=
foid
;
else
if
(
!
strcmp
(
fname
,
"lo_truncate"
))
lobjfuncs
->
fn_lo_truncate
=
foid
;
else
if
(
!
strcmp
(
fname
,
"loread"
))
else
if
(
!
strcmp
(
fname
,
"loread"
))
lobjfuncs
->
fn_lo_read
=
foid
;
lobjfuncs
->
fn_lo_read
=
foid
;
else
if
(
!
strcmp
(
fname
,
"lowrite"
))
else
if
(
!
strcmp
(
fname
,
"lowrite"
))
...
@@ -694,7 +751,6 @@ lo_initialize(PGconn *conn)
...
@@ -694,7 +751,6 @@ lo_initialize(PGconn *conn)
/*
/*
* Finally check that we really got all large object interface functions
* Finally check that we really got all large object interface functions
* --- except lo_create, which may not exist.
*/
*/
if
(
lobjfuncs
->
fn_lo_open
==
0
)
if
(
lobjfuncs
->
fn_lo_open
==
0
)
{
{
...
...
src/interfaces/libpq/libpq-fe.h
View file @
0763a565
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.13
5 2007/01/05 22:20:01
momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.13
6 2007/03/03 19:52:46
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -489,6 +489,7 @@ extern int lo_lseek(PGconn *conn, int fd, int offset, int whence);
...
@@ -489,6 +489,7 @@ extern int lo_lseek(PGconn *conn, int fd, int offset, int whence);
extern
Oid
lo_creat
(
PGconn
*
conn
,
int
mode
);
extern
Oid
lo_creat
(
PGconn
*
conn
,
int
mode
);
extern
Oid
lo_create
(
PGconn
*
conn
,
Oid
lobjId
);
extern
Oid
lo_create
(
PGconn
*
conn
,
Oid
lobjId
);
extern
int
lo_tell
(
PGconn
*
conn
,
int
fd
);
extern
int
lo_tell
(
PGconn
*
conn
,
int
fd
);
extern
int
lo_truncate
(
PGconn
*
conn
,
int
fd
,
size_t
len
);
extern
int
lo_unlink
(
PGconn
*
conn
,
Oid
lobjId
);
extern
int
lo_unlink
(
PGconn
*
conn
,
Oid
lobjId
);
extern
Oid
lo_import
(
PGconn
*
conn
,
const
char
*
filename
);
extern
Oid
lo_import
(
PGconn
*
conn
,
const
char
*
filename
);
extern
int
lo_export
(
PGconn
*
conn
,
Oid
lobjId
,
const
char
*
filename
);
extern
int
lo_export
(
PGconn
*
conn
,
Oid
lobjId
,
const
char
*
filename
);
...
...
src/interfaces/libpq/libpq-int.h
View file @
0763a565
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.11
8 2007/01/26 17:45:41 neilc
Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.11
9 2007/03/03 19:52:47 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -239,6 +239,7 @@ typedef struct pgLobjfuncs
...
@@ -239,6 +239,7 @@ typedef struct pgLobjfuncs
Oid
fn_lo_unlink
;
/* OID of backend function lo_unlink */
Oid
fn_lo_unlink
;
/* OID of backend function lo_unlink */
Oid
fn_lo_lseek
;
/* OID of backend function lo_lseek */
Oid
fn_lo_lseek
;
/* OID of backend function lo_lseek */
Oid
fn_lo_tell
;
/* OID of backend function lo_tell */
Oid
fn_lo_tell
;
/* OID of backend function lo_tell */
Oid
fn_lo_truncate
;
/* OID of backend function lo_truncate */
Oid
fn_lo_read
;
/* OID of backend function LOread */
Oid
fn_lo_read
;
/* OID of backend function LOread */
Oid
fn_lo_write
;
/* OID of backend function LOwrite */
Oid
fn_lo_write
;
/* OID of backend function LOwrite */
}
PGlobjfuncs
;
}
PGlobjfuncs
;
...
...
src/test/regress/input/largeobject.source
View file @
0763a565
...
@@ -83,6 +83,25 @@ SELECT lo_close(fd) FROM lotest_stash_values;
...
@@ -83,6 +83,25 @@ SELECT lo_close(fd) FROM lotest_stash_values;
END;
END;
-- Test truncation.
BEGIN;
UPDATE lotest_stash_values SET fd=lo_open(loid, CAST((2 | 4) * 16^4 AS integer));
SELECT lo_truncate(fd, 10) FROM lotest_stash_values;
SELECT loread(fd, 15) FROM lotest_stash_values;
SELECT lo_truncate(fd, 10000) FROM lotest_stash_values;
SELECT loread(fd, 10) FROM lotest_stash_values;
SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
SELECT lo_tell(fd) FROM lotest_stash_values;
SELECT lo_truncate(fd, 5000) FROM lotest_stash_values;
SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
SELECT lo_tell(fd) FROM lotest_stash_values;
SELECT lo_close(fd) FROM lotest_stash_values;
END;
-- lo_unlink(lobjId oid) returns integer
-- lo_unlink(lobjId oid) returns integer
-- return value appears to always be 1
-- return value appears to always be 1
SELECT lo_unlink(loid) from lotest_stash_values;
SELECT lo_unlink(loid) from lotest_stash_values;
...
...
src/test/regress/output/largeobject.source
View file @
0763a565
...
@@ -115,6 +115,70 @@ SELECT lo_close(fd) FROM lotest_stash_values;
...
@@ -115,6 +115,70 @@ SELECT lo_close(fd) FROM lotest_stash_values;
0
0
(1 row)
(1 row)
END;
-- Test truncation.
BEGIN;
UPDATE lotest_stash_values SET fd=lo_open(loid, CAST((2 | 4) * 16^4 AS integer));
SELECT lo_truncate(fd, 10) FROM lotest_stash_values;
lo_truncate
-------------
0
(1 row)
SELECT loread(fd, 15) FROM lotest_stash_values;
loread
---------------
\012Whose woo
(1 row)
SELECT lo_truncate(fd, 10000) FROM lotest_stash_values;
lo_truncate
-------------
0
(1 row)
SELECT loread(fd, 10) FROM lotest_stash_values;
loread
------------------------------------------
\000\000\000\000\000\000\000\000\000\000
(1 row)
SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
lo_lseek
----------
10000
(1 row)
SELECT lo_tell(fd) FROM lotest_stash_values;
lo_tell
---------
10000
(1 row)
SELECT lo_truncate(fd, 5000) FROM lotest_stash_values;
lo_truncate
-------------
0
(1 row)
SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
lo_lseek
----------
5000
(1 row)
SELECT lo_tell(fd) FROM lotest_stash_values;
lo_tell
---------
5000
(1 row)
SELECT lo_close(fd) FROM lotest_stash_values;
lo_close
----------
0
(1 row)
END;
END;
-- lo_unlink(lobjId oid) returns integer
-- lo_unlink(lobjId oid) returns integer
-- return value appears to always be 1
-- return value appears to always be 1
...
...
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