- Mailing list pgsql-bugs
From | Ian Grant |
---|---|
Subject | |
Date | |
Msg-id | E1329ve-0000DW-00@wisbech.cl.cam.ac.uk Whole thread Raw |
Responses |
Re: large object seek/write bug
|
List | pgsql-bugs |
Hi, I sent this message to pgsql-bugs@postresql.org a couple of weeks ago and I got an automated response from pgsql-bugs-owner@hub.org indicating that I'd been subscribed to this list, but I've not seen any traffic from it all since then. Either there are really very few bugs in PostgreSQL (congratulations!) or something is wrong with my subscription. Any (non-automatic) feedback would be welcomed. Here's the message again: I'm using V 7.0 on a Linux machine and I believe I have found a bug in the large object interface provided by libpq. The code below will reproduce it, I hope. Basically it creates a large object, writes six 'a' characters to it, then closes it. Then, in another transaction, it opens the object, seeks to position 1 from the start, writes a 'b', then seeks to position 3 from the start and writes another 'b'. Then it closes the object and COMMITs the transaction. Finally, in a further separate transaction, it calls lo_export to write out the resulting object to a file testloseek.c.lobj I find this file, instead of containing the string 'ababaa' as expected, contains '^@b^@baa' where ^@ is ASCII NUL. Compile with something like gcc -o testloseek testloseek.c -lpq The program sets the PQtrace to STDOUT and writes messages to STDERR, so run it with STDOUT redirected to a log file. This is a C version of a basic regression test of guile-pg, my Guile language bindings for libpq. You may recall I reported a similar bug a year or so ago, and I believed it was then fixed by Tatsuo, after a couple of iterations. I'm sorry to be the bearer of bad news ... Please reply to me directly since I'm not on the list. Thanks Ian #include <stdio.h> #include "libpq-fe.h" #include "libpq/libpq-fs.h" void exec_cmd(PGconn *conn, char *str); main (int argc, char *argv[]) { PGconn *conn; int lobj_fd; char buf[256]; int ret, i; Oid lobj_id; conn = PQconnectdb("dbname=test"); if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Can't connect to backend.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } exec_cmd(conn, "BEGIN TRANSACTION"); PQtrace (conn, stdout); if ((lobj_id = lo_creat(conn, INV_READ | INV_WRITE)) < 0) { fprintf(stderr, "Can't create lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } fprintf(stderr, "lo_creat() returned OID %ld.\n", lobj_id); if ((lobj_fd = lo_open(conn, lobj_id, INV_READ | INV_WRITE)) < 0) { fprintf(stderr, "Can't open lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } fprintf(stderr, "lo_open returned fd = %d.\n", lobj_fd); if ((ret = lo_write(conn, lobj_fd, "aaaaaa", 6)) != 6) { fprintf(stderr, "Can't write lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } ret = lo_close(conn, lobj_fd); printf("lo_close returned %d.\n", ret); exec_cmd(conn, "END TRANSACTION"); exec_cmd(conn, "BEGIN TRANSACTION"); if ((lobj_fd = lo_open(conn, lobj_id, INV_READ | INV_WRITE)) < 0) { fprintf(stderr, "Can't open lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } fprintf(stderr, "lo_open returned fd = %d.\n", lobj_fd); if (ret) fprintf(stderr, "Error message: %s\n", PQerrorMessage(conn)); if ((ret = lo_lseek(conn, lobj_fd, 1, 0)) != 1) { fprintf(stderr, "error (%d) lseeking in large object.\n", ret); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } if ((ret = lo_write(conn, lobj_fd, "b", 1)) != 1) { fprintf(stderr, "Can't write lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } if ((ret = lo_lseek(conn, lobj_fd, 3, 0)) != 3) { fprintf(stderr, "error (%d) lseeking in large object.\n", ret); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } if ((ret = lo_write(conn, lobj_fd, "b", 1)) != 1) { fprintf(stderr, "Can't write lobj.\n"); fprintf(stderr, "ERROR: %s\n", PQerrorMessage(conn)); exit(1); } ret = lo_close(conn, lobj_fd); printf("lo_close returned %d.\n", ret); if (ret) fprintf(stderr, "Error message: %s\n", PQerrorMessage(conn)); PQuntrace(conn); exec_cmd(conn, "END TRANSACTION"); exec_cmd(conn, "BEGIN TRANSACTION"); ret = lo_export(conn, lobj_id, "testloseek.c.lobj"); printf("lo_export returned %d.\n", ret); if (ret != 1) fprintf(stderr, "Error message: %s\n", PQerrorMessage(conn)); exec_cmd(conn, "END TRANSACTION"); exit(0); } void exec_cmd(PGconn *conn, char *str) { PGresult *res; if ((res = PQexec(conn, str)) == NULL) { fprintf(stderr, "Error executing %s.\n", str); fprintf(stderr, "Error message: %s\n", PQerrorMessage(conn)); exit(1); } if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "Error executing %s.\n", str); fprintf(stderr, "Error message: %s\n", PQerrorMessage(conn)); PQclear(res); exit(1); } PQclear(res); } -- Ian Grant, Computer Lab., New Museums Site, Pembroke Street, Cambridge Phone: +44 1223 334420 Personal e-mail: iang at pobox dot com
pgsql-bugs by date: