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

Commit bb7b718

Browse files
author
Peter Mount
committed
Web Feb 14 17:29:00 GMT 2001 peter@retep.org.uk
- Fixed bug in LargeObject & BlobOutputStream where the stream's output was not flushed when either the stream or the blob were closed. - Fixed PreparedStatement.setBinaryStream() where it ignored the length
1 parent c1abe85 commit bb7b718

File tree

7 files changed

+224
-8
lines changed

7 files changed

+224
-8
lines changed

src/interfaces/jdbc/CHANGELOG

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Web Feb 14 17:29:00 GMT 2001 peter@retep.org.uk
2+
- Fixed bug in LargeObject & BlobOutputStream where the stream's output
3+
was not flushed when either the stream or the blob were closed.
4+
- Fixed PreparedStatement.setBinaryStream() where it ignored the length
5+
16
Tue Feb 13 16:33:00 GMT 2001 peter@retep.org.uk
27
- More TestCases implemented. Refined the test suite api's.
38
- Removed need for SimpleDateFormat in ResultSet.getDate() improving

src/interfaces/jdbc/build.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
build file to allow ant (http://jakarta.apache.org/ant/) to be used
44
to build the PostgreSQL JDBC Driver.
55
6-
$Id: build.xml,v 1.5 2001/02/07 09:13:20 peter Exp $
6+
$Id: build.xml,v 1.6 2001/02/14 17:45:13 peter Exp $
77
88
-->
99

@@ -26,6 +26,7 @@
2626
<property name="database" value="jdbc:postgresql:test" />
2727
<property name="username" value="test" />
2828
<property name="password" value="password" />
29+
<property name="tablename" value="jdbctest" />
2930
<property name="junit.ui" value="textui" />
3031

3132
<!--

src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,11 @@ public void setBinaryStream(int parameterIndex, InputStream x, int length) throw
431431
// is buffered internally anyhow, so there would be no performance
432432
// boost gained, if anything it would be worse!
433433
int c=x.read();
434-
while(c>-1) {
434+
int p=0;
435+
while(c>-1 && p<length) {
435436
los.write(c);
436437
c=x.read();
438+
p++;
437439
}
438440
los.close();
439441
} catch(IOException se) {

src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public void flush() throws IOException {
9292
*/
9393
public void close() throws IOException {
9494
try {
95+
flush();
9596
lo.close();
9697
lo=null;
9798
} catch(SQLException se) {

src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public class LargeObject
6262
private int oid; // OID of this object
6363
private int fd; // the descriptor of the open large object
6464

65+
private BlobOutputStream os; // The current output stream
66+
67+
private boolean closed=false; // true when we are closed
68+
6569
/**
6670
* This opens a large object.
6771
*
@@ -100,9 +104,25 @@ public int getOID()
100104
*/
101105
public void close() throws SQLException
102106
{
103-
FastpathArg args[] = new FastpathArg[1];
104-
args[0] = new FastpathArg(fd);
105-
fp.fastpath("lo_close",false,args); // true here as we dont care!!
107+
if(!closed) {
108+
// flush any open output streams
109+
if(os!=null) {
110+
try {
111+
// we can't call os.close() otherwise we go into an infinite loop!
112+
os.flush();
113+
} catch(IOException ioe) {
114+
throw new SQLException(ioe.getMessage());
115+
} finally {
116+
os=null;
117+
}
118+
}
119+
120+
// finally close
121+
FastpathArg args[] = new FastpathArg[1];
122+
args[0] = new FastpathArg(fd);
123+
fp.fastpath("lo_close",false,args); // true here as we dont care!!
124+
closed=true;
125+
}
106126
}
107127

108128
/**
@@ -279,7 +299,9 @@ public InputStream getInputStream() throws SQLException
279299
*/
280300
public OutputStream getOutputStream() throws SQLException
281301
{
282-
return new BlobOutputStream(this);
302+
if(os==null)
303+
os = new BlobOutputStream(this);
304+
return os;
283305
}
284306

285307
}

src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,14 @@ public static TestSuite suite() {
207207

208208
// MetaData
209209

210-
// Fastpath/LargeObject
211-
212210
// Other misc tests, based on previous problems users have had or specific
213211
// features some applications require.
214212
suite.addTestSuite(JBuilderTest.class);
215213
suite.addTestSuite(MiscTest.class);
216214

215+
// Fastpath/LargeObject
216+
suite.addTestSuite(BlobTest.class);
217+
217218
// That's all folks
218219
return suite;
219220
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package org.postgresql.test.jdbc2;
2+
3+
import org.postgresql.test.JDBC2Tests;
4+
import junit.framework.TestCase;
5+
import java.io.*;
6+
import java.sql.*;
7+
8+
import org.postgresql.largeobject.*;
9+
10+
/**
11+
* $Id: BlobTest.java,v 1.1 2001/02/14 17:45:17 peter Exp $
12+
*
13+
* Some simple tests based on problems reported by users. Hopefully these will
14+
* help prevent previous problems from re-occuring ;-)
15+
*
16+
*/
17+
public class BlobTest extends TestCase {
18+
19+
public BlobTest(String name) {
20+
super(name);
21+
}
22+
23+
/**
24+
* The table format used by this TestCase
25+
*/
26+
private static final String BLOB_TABLE_FMT = "id name,lo oid";
27+
28+
/**
29+
* Tests one method of uploading a blob to the database
30+
*/
31+
public void testUploadBlob_LOOP() {
32+
try {
33+
Connection con = JDBC2Tests.openDB();
34+
35+
JDBC2Tests.createTable(con,BLOB_TABLE_FMT);
36+
37+
con.setAutoCommit(false);
38+
assert(!con.getAutoCommit());
39+
40+
assert(uploadFile(con,"build.xml",LOOP)>0);
41+
42+
// Now compare the blob & the file. Note this actually tests the
43+
// InputStream implementation!
44+
assert(compareBlobs(con));
45+
46+
JDBC2Tests.closeDB(con);
47+
} catch(Exception ex) {
48+
assert(ex.getMessage(),false);
49+
}
50+
}
51+
52+
/**
53+
* Tests one method of uploading a blob to the database
54+
*/
55+
public void testUploadBlob_NATIVE() {
56+
try {
57+
Connection con = JDBC2Tests.openDB();
58+
59+
JDBC2Tests.createTable(con,BLOB_TABLE_FMT);
60+
61+
con.setAutoCommit(false);
62+
assert(!con.getAutoCommit());
63+
64+
assert(uploadFile(con,"build.xml",NATIVE_STREAM)>0);
65+
66+
// Now compare the blob & the file. Note this actually tests the
67+
// InputStream implementation!
68+
assert(compareBlobs(con));
69+
70+
JDBC2Tests.closeDB(con);
71+
} catch(Exception ex) {
72+
assert(ex.getMessage(),false);
73+
}
74+
}
75+
76+
private static final int LOOP = 0; // LargeObject API using loop
77+
private static final int NATIVE_STREAM = 1; // LargeObject API using OutputStream
78+
private static final int JDBC_STREAM = 2; // JDBC API using OutputStream
79+
80+
/**
81+
* Helper - uploads a file into a blob using old style methods. We use this
82+
* because it always works, and we can use it as a base to test the new
83+
* methods.
84+
*/
85+
private int uploadFile(Connection con,String file,int method) throws Exception {
86+
LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
87+
88+
FileInputStream fis = new FileInputStream(file);
89+
90+
int oid = lom.create(LargeObjectManager.READWRITE);
91+
LargeObject blob = lom.open(oid);
92+
93+
int s,t;
94+
byte buf[];
95+
OutputStream os;
96+
97+
switch(method)
98+
{
99+
case LOOP:
100+
buf = new byte[2048];
101+
t=0;
102+
while((s=fis.read(buf,0,buf.length))>0) {
103+
t+=s;
104+
blob.write(buf,0,s);
105+
}
106+
break;
107+
108+
case NATIVE_STREAM:
109+
os = blob.getOutputStream();
110+
s= fis.read();
111+
while(s>-1) {
112+
os.write(s);
113+
s=fis.read();
114+
}
115+
os.close();
116+
break;
117+
118+
case JDBC_STREAM:
119+
File f = new File(file);
120+
PreparedStatement ps = con.prepareStatement(JDBC2Tests.insert("?"));
121+
ps.setBinaryStream(1,fis,(int) f.length());
122+
ps.execute();
123+
break;
124+
125+
default:
126+
assert("Unknown method in uploadFile",false);
127+
}
128+
129+
blob.close();
130+
fis.close();
131+
132+
// Insert into the table
133+
Statement st = con.createStatement();
134+
st.executeUpdate(JDBC2Tests.insert("id,lo","'"+file+"',"+oid));
135+
con.commit();
136+
st.close();
137+
138+
return oid;
139+
}
140+
141+
/**
142+
* Helper - compares the blobs in a table with a local file. Note this alone
143+
* tests the InputStream methods!
144+
*/
145+
private boolean compareBlobs(Connection con) throws Exception {
146+
boolean result=true;
147+
148+
LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
149+
150+
Statement st = con.createStatement();
151+
ResultSet rs = st.executeQuery(JDBC2Tests.select("id,lo"));
152+
assert(rs!=null);
153+
154+
while(rs.next()) {
155+
String file = rs.getString(1);
156+
int oid = rs.getInt(2);
157+
158+
FileInputStream fis = new FileInputStream(file);
159+
LargeObject blob = lom.open(oid);
160+
InputStream bis = blob.getInputStream();
161+
162+
int f=fis.read();
163+
int b=bis.read();
164+
int c=0;
165+
while(f>=0 && b>=0 & result) {
166+
result=(f==b);
167+
f=fis.read();
168+
b=bis.read();
169+
c++;
170+
}
171+
result=result && f==-1 && b==-1;
172+
173+
if(!result)
174+
System.out.println("\nBlob compare failed at "+c+" of "+blob.size());
175+
176+
blob.close();
177+
fis.close();
178+
}
179+
rs.close();
180+
st.close();
181+
182+
return result;
183+
}
184+
}

0 commit comments

Comments
 (0)