Source code: postgresql/largeobject/LargeObject.java
1 package postgresql.largeobject;
2
3 import java.io.*;
4 import java.lang.*;
5 import java.net.*;
6 import java.util.*;
7 import java.sql.*;
8
9 import postgresql.fastpath.*;
10
11 /**
12 * This class implements the large object interface to postgresql.
13 *
14 * <p>It provides the basic methods required to run the interface, plus
15 * a pair of methods that provide InputStream and OutputStream classes
16 * for this object.
17 *
18 * <p>Normally, client code would use the getAsciiStream, getBinaryStream,
19 * or getUnicodeStream methods in ResultSet, or setAsciiStream,
20 * setBinaryStream, or setUnicodeStream methods in PreparedStatement to
21 * access Large Objects.
22 *
23 * <p>However, sometimes lower level access to Large Objects are required,
24 * that are not supported by the JDBC specification.
25 *
26 * <p>Refer to postgresql.largeobject.LargeObjectManager on how to gain access
27 * to a Large Object, or how to create one.
28 *
29 * @see postgresql.largeobject.LargeObjectManager
30 * @see postgresql.ResultSet#getAsciiStream
31 * @see postgresql.ResultSet#getBinaryStream
32 * @see postgresql.ResultSet#getUnicodeStream
33 * @see postgresql.PreparedStatement#setAsciiStream
34 * @see postgresql.PreparedStatement#setBinaryStream
35 * @see postgresql.PreparedStatement#setUnicodeStream
36 * @see java.sql.ResultSet#getAsciiStream
37 * @see java.sql.ResultSet#getBinaryStream
38 * @see java.sql.ResultSet#getUnicodeStream
39 * @see java.sql.PreparedStatement#setAsciiStream
40 * @see java.sql.PreparedStatement#setBinaryStream
41 * @see java.sql.PreparedStatement#setUnicodeStream
42 *
43 */
44 public class LargeObject
45 {
46 /**
47 * Indicates a seek from the begining of a file
48 */
49 public static final int SEEK_SET = 0;
50
51 /**
52 * Indicates a seek from the current position
53 */
54 public static final int SEEK_CUR = 1;
55
56 /**
57 * Indicates a seek from the end of a file
58 */
59 public static final int SEEK_END = 2;
60
61 private Fastpath fp; // Fastpath API to use
62 private int oid; // OID of this object
63 private int fd; // the descriptor of the open large object
64
65 /**
66 * This opens a large object.
67 *
68 * <p>If the object does not exist, then an SQLException is thrown.
69 *
70 * @param fp FastPath API for the connection to use
71 * @param oid of the Large Object to open
72 * @param mode Mode of opening the large object
73 * (defined in LargeObjectManager)
74 * @exception SQLException if a database-access error occurs.
75 * @see postgresql.largeobject.LargeObjectManager
76 */
77 protected LargeObject(Fastpath fp,int oid,int mode) throws SQLException
78 {
79 this.fp = fp;
80 this.oid = oid;
81
82 FastpathArg args[] = new FastpathArg[2];
83 args[0] = new FastpathArg(oid);
84 args[1] = new FastpathArg(mode);
85 this.fd = fp.getInteger("lo_open",args);
86 }
87
88 /**
89 * @return the OID of this LargeObject
90 */
91 public int getOID()
92 {
93 return oid;
94 }
95
96 /**
97 * This method closes the object. You must not call methods in this
98 * object after this is called.
99 * @exception SQLException if a database-access error occurs.
100 */
101 public void close() throws SQLException
102 {
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!!
106 }
107
108 /**
109 * Reads some data from the object, and return as a byte[] array
110 *
111 * @param len number of bytes to read
112 * @return byte[] array containing data read
113 * @exception SQLException if a database-access error occurs.
114 */
115 public byte[] read(int len) throws SQLException
116 {
117 // This is the original method, where the entire block (len bytes)
118 // is retrieved in one go.
119 FastpathArg args[] = new FastpathArg[2];
120 args[0] = new FastpathArg(fd);
121 args[1] = new FastpathArg(len);
122 return fp.getData("loread",args);
123
124 // This version allows us to break this down into 4k blocks
125 //if(len<=4048) {
126 //// handle as before, return the whole block in one go
127 //FastpathArg args[] = new FastpathArg[2];
128 //args[0] = new FastpathArg(fd);
129 //args[1] = new FastpathArg(len);
130 //return fp.getData("loread",args);
131 //} else {
132 //// return in 4k blocks
133 //byte[] buf=new byte[len];
134 //int off=0;
135 //while(len>0) {
136 //int bs=4048;
137 //len-=bs;
138 //if(len<0) {
139 //bs+=len;
140 //len=0;
141 //}
142 //read(buf,off,bs);
143 //off+=bs;
144 //}
145 //return buf;
146 //}
147 }
148
149 /**
150 * Reads some data from the object into an existing array
151 *
152 * @param buf destination array
153 * @param off offset within array
154 * @param len number of bytes to read
155 * @exception SQLException if a database-access error occurs.
156 */
157 public void read(byte buf[],int off,int len) throws SQLException
158 {
159 System.arraycopy(read(len),0,buf,off,len);
160 }
161
162 /**
163 * Writes an array to the object
164 *
165 * @param buf array to write
166 * @exception SQLException if a database-access error occurs.
167 */
168 public void write(byte buf[]) throws SQLException
169 {
170 FastpathArg args[] = new FastpathArg[2];
171 args[0] = new FastpathArg(fd);
172 args[1] = new FastpathArg(buf);
173 fp.fastpath("lowrite",false,args);
174 }
175
176 /**
177 * Writes some data from an array to the object
178 *
179 * @param buf destination array
180 * @param off offset within array
181 * @param len number of bytes to write
182 * @exception SQLException if a database-access error occurs.
183 */
184 public void write(byte buf[],int off,int len) throws SQLException
185 {
186 byte data[] = new byte[len];
187 System.arraycopy(buf,off,data,0,len);
188 write(data);
189 }
190
191 /**
192 * Sets the current position within the object.
193 *
194 * <p>This is similar to the fseek() call in the standard C library. It
195 * allows you to have random access to the large object.
196 *
197 * @param pos position within object
198 * @param ref Either SEEK_SET, SEEK_CUR or SEEK_END
199 * @exception SQLException if a database-access error occurs.
200 */
201 public void seek(int pos,int ref) throws SQLException
202 {
203 FastpathArg args[] = new FastpathArg[3];
204 args[0] = new FastpathArg(fd);
205 args[1] = new FastpathArg(pos);
206 args[2] = new FastpathArg(ref);
207 fp.fastpath("lo_lseek",false,args);
208 }
209
210 /**
211 * Sets the current position within the object.
212 *
213 * <p>This is similar to the fseek() call in the standard C library. It
214 * allows you to have random access to the large object.
215 *
216 * @param pos position within object from begining
217 * @exception SQLException if a database-access error occurs.
218 */
219 public void seek(int pos) throws SQLException
220 {
221 seek(pos,SEEK_SET);
222 }
223
224 /**
225 * @return the current position within the object
226 * @exception SQLException if a database-access error occurs.
227 */
228 public int tell() throws SQLException
229 {
230 FastpathArg args[] = new FastpathArg[1];
231 args[0] = new FastpathArg(fd);
232 return fp.getInteger("lo_tell",args);
233 }
234
235 /**
236 * This method is inefficient, as the only way to find out the size of
237 * the object is to seek to the end, record the current position, then
238 * return to the original position.
239 *
240 * <p>A better method will be found in the future.
241 *
242 * @return the size of the large object
243 * @exception SQLException if a database-access error occurs.
244 */
245 public int size() throws SQLException
246 {
247 int cp = tell();
248 seek(0,SEEK_END);
249 int sz = tell();
250 seek(cp,SEEK_SET);
251 return sz;
252 }
253
254 /**
255 * Returns an InputStream from this object.
256 *
257 * <p>This InputStream can then be used in any method that requires an
258 * InputStream.
259 *
260 * @exception SQLException if a database-access error occurs.
261 */
262 public InputStream getInputStream() throws SQLException
263 {
264 throw postgresql.Driver.notImplemented();
265 }
266
267 /**
268 * Returns an OutputStream to this object
269 *
270 * <p>This OutputStream can then be used in any method that requires an
271 * OutputStream.
272 *
273 * @exception SQLException if a database-access error occurs.
274 */
275 public OutputStream getOutputStream() throws SQLException
276 {
277 throw postgresql.Driver.notImplemented();
278 }
279 }