Mercurial > hg > monetdb-java
comparison src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java @ 0:a5a898f6886c
Copy of MonetDB java directory changeset e6e32756ad31.
author | Sjoerd Mullender <sjoerd@acm.org> |
---|---|
date | Wed, 21 Sep 2016 09:34:48 +0200 (2016-09-21) |
parents | |
children | 7e0d71a22677 e092fa8d9ab7 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a5a898f6886c |
---|---|
1 /* | |
2 * This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
5 * | |
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. | |
7 */ | |
8 | |
9 package nl.cwi.monetdb.jdbc; | |
10 | |
11 import java.sql.*; | |
12 import java.util.Arrays; | |
13 import java.io.*; | |
14 | |
15 /** | |
16 * The MonetBlob class implements the {@link java.sql.Blob} interface. Because | |
17 * MonetDB/SQL currently has no support for streams, this class is a | |
18 * shallow wrapper of a byte[]. It is more or less supplied to | |
19 * enable an application that depends on it to run. It may be obvious | |
20 * that it is a real resource expensive workaround that contradicts the | |
21 * benefits for a Blob: avoidance of huge resource consumption. | |
22 * | |
23 * @author Fabian Groffen | |
24 */ | |
25 public class MonetBlob implements Blob { | |
26 private byte[] buf; | |
27 | |
28 protected MonetBlob(byte[] data) { | |
29 buf = data; | |
30 } | |
31 | |
32 static MonetBlob create(String in) { | |
33 int len = in.length() / 2; | |
34 byte[] buf = new byte[len]; | |
35 for (int i = 0; i < len; i++) | |
36 buf[i] = (byte)Integer.parseInt(in.substring(2 * i, (2 * i) + 2), 16); | |
37 return new MonetBlob(buf); | |
38 } | |
39 | |
40 | |
41 //== begin interface Blob | |
42 | |
43 /** | |
44 * This method frees the Blob object and releases the resources that | |
45 * it holds. The object is invalid once the free method is called. | |
46 * | |
47 * After free has been called, any attempt to invoke a method other | |
48 * than free will result in a SQLException being thrown. If free is | |
49 * called multiple times, the subsequent calls to free are treated | |
50 * as a no-op. | |
51 * | |
52 * @throws SQLException if an error occurs releasing the Blob's | |
53 * resources | |
54 * @throws SQLFeatureNotSupportedException - if the JDBC driver does | |
55 * not support this method | |
56 */ | |
57 @Override | |
58 public void free() throws SQLException { | |
59 buf = null; | |
60 } | |
61 | |
62 /** | |
63 * Retrieves the BLOB value designated by this Blob instance as a | |
64 * stream. | |
65 * | |
66 * @return a stream containing the BLOB data | |
67 * @throws SQLException if there is an error accessing the BLOB value | |
68 * @throws SQLFeatureNotSupportedException if the JDBC driver does | |
69 * not support this method | |
70 */ | |
71 @Override | |
72 public InputStream getBinaryStream() throws SQLException { | |
73 if (buf == null) | |
74 throw new SQLException("This Blob object has been freed", "M1M20"); | |
75 return new ByteArrayInputStream(buf); | |
76 } | |
77 | |
78 /** | |
79 * Returns an InputStream object that contains a partial Blob value, | |
80 * starting with the byte specified by pos, which is length bytes in | |
81 * length. | |
82 * | |
83 * @param pos the offset to the first byte of the partial value to | |
84 * be retrieved. The first byte in the Blob is at position 1 | |
85 * @param length the length in bytes of the partial value to be | |
86 * retrieved | |
87 * @return InputStream through which the partial Blob value can be | |
88 * read. | |
89 * @throws SQLException if pos is less than 1 or if pos is | |
90 * greater than the number of bytes in the Blob or if pos + | |
91 * length is greater than the number of bytes in the Blob | |
92 * @throws SQLFeatureNotSupportedException if the JDBC driver does | |
93 * not support this method | |
94 */ | |
95 @Override | |
96 public InputStream getBinaryStream(long pos, long length) | |
97 throws SQLException | |
98 { | |
99 if (buf == null) | |
100 throw new SQLException("This Blob object has been freed", "M1M20"); | |
101 if (pos < 1) | |
102 throw new SQLException("pos is less than 1", "M1M05"); | |
103 if (pos - 1 > buf.length) | |
104 throw new SQLException("pos is greater than the number of bytes in the Blob", "M1M05"); | |
105 if (pos - 1 + length > buf.length) | |
106 throw new SQLException("pos + length is greater than the number of bytes in the Blob", "M1M05"); | |
107 return new ByteArrayInputStream(buf, (int)(pos - 1), (int)length); | |
108 } | |
109 | |
110 /** | |
111 * Retrieves all or part of the BLOB value that this Blob object | |
112 * represents, as an array of bytes. This byte array contains up to | |
113 * length consecutive bytes starting at position pos. | |
114 * | |
115 * @param pos the ordinal position of the first byte in the BLOB | |
116 * value to be extracted; the first byte is at position 1. | |
117 * @param length the number of consecutive bytes to be copied | |
118 * @return a byte array containing up to length consecutive bytes | |
119 * from the BLOB value designated by this Blob object, | |
120 * starting with the byte at position pos. | |
121 * @throws SQLException if there is an error accessing the | |
122 * BLOB value | |
123 */ | |
124 @Override | |
125 public byte[] getBytes(long pos, int length) throws SQLException { | |
126 if (buf == null) | |
127 throw new SQLException("This Blob object has been freed", "M1M20"); | |
128 try { | |
129 return Arrays.copyOfRange(buf, (int) pos - 1, (int) pos - 1 + length); | |
130 } catch (IndexOutOfBoundsException e) { | |
131 throw new SQLException(e.getMessage(), "M0M10"); | |
132 } | |
133 } | |
134 | |
135 /** | |
136 * Returns the number of bytes in the BLOB value designated by this | |
137 * Blob object. | |
138 * | |
139 * @return length of the BLOB in bytes | |
140 * @throws SQLException if there is an error accessing the length | |
141 * of the BLOB value | |
142 */ | |
143 @Override | |
144 public long length() throws SQLException { | |
145 if (buf == null) | |
146 throw new SQLException("This Blob object has been freed", "M1M20"); | |
147 return (long)buf.length; | |
148 } | |
149 | |
150 /** | |
151 * Retrieves the byte position in the BLOB value designated by this | |
152 * Blob object at which pattern begins. The search begins at | |
153 * position start. | |
154 * | |
155 * @param pattern the Blob object designating the BLOB value for | |
156 * which to search | |
157 * @param start the position in the BLOB value at which to begin | |
158 * searching; the first position is 1 | |
159 * @return the position at which the pattern begins, else -1 | |
160 * @throws SQLException if there is an error accessing the | |
161 * BLOB value | |
162 */ | |
163 @Override | |
164 public long position(Blob pattern, long start) throws SQLException { | |
165 return position(pattern.getBytes(1L, (int)pattern.length()), start); | |
166 } | |
167 | |
168 /** | |
169 * Retrieves the byte position at which the specified byte array | |
170 * pattern begins within the BLOB value that this Blob object | |
171 * represents. The search for pattern begins at position start. | |
172 * | |
173 * @param pattern the byte array for which to search | |
174 * @param start the position at which to begin searching; | |
175 * the first position is 1 | |
176 * @return the position at which the pattern appears, else -1 | |
177 * @throws SQLException if there is an error accessing the | |
178 * BLOB value | |
179 */ | |
180 @Override | |
181 public long position(byte[] pattern, long start) throws SQLException { | |
182 if (buf == null) | |
183 throw new SQLException("This Blob object has been freed", "M1M20"); | |
184 try { | |
185 for (int i = (int)(start - 1); i < buf.length - pattern.length; i++) { | |
186 int j; | |
187 for (j = 0; j < pattern.length; j++) { | |
188 if (buf[i + j] != pattern[j]) | |
189 break; | |
190 } | |
191 if (j == pattern.length) | |
192 return i; | |
193 } | |
194 } catch (IndexOutOfBoundsException e) { | |
195 throw new SQLException(e.getMessage(), "M0M10"); | |
196 } | |
197 return -1; | |
198 } | |
199 | |
200 /** | |
201 * Retrieves a stream that can be used to write to the BLOB value | |
202 * that this Blob object represents. The stream begins at position | |
203 * pos. The bytes written to the stream will overwrite the existing | |
204 * bytes in the Blob object starting at the position pos. If the end | |
205 * of the Blob value is reached while writing to the stream, then | |
206 * the length of the Blob value will be increased to accomodate the | |
207 * extra bytes. | |
208 * | |
209 * @param pos the position in the BLOB value at which to start | |
210 * writing; the first position is 1 | |
211 * @return a java.io.OutputStream object to which data can be | |
212 * written | |
213 * @throws SQLException if there is an error accessing the BLOB | |
214 * value or if pos is less than 1 | |
215 * @throws SQLFeatureNotSupportedException if the JDBC driver does | |
216 * not support this method | |
217 */ | |
218 @Override | |
219 public OutputStream setBinaryStream(long pos) throws SQLException { | |
220 if (buf == null) | |
221 throw new SQLException("This Blob object has been freed", "M1M20"); | |
222 if (pos < 1) | |
223 throw new SQLException("pos is less than 1", "M1M05"); | |
224 throw new SQLFeatureNotSupportedException("Operation setBinaryStream(long pos) currently not supported", "0A000"); | |
225 } | |
226 | |
227 /** | |
228 * Writes the given array of bytes to the BLOB value that this Blob | |
229 * object represents, starting at position pos, and returns the | |
230 * number of bytes written. | |
231 * | |
232 * @param pos the position in the BLOB object at which to start | |
233 * writing | |
234 * @param bytes the array of bytes to be written to the BLOB value | |
235 * that this Blob object represents | |
236 * @return the number of bytes written | |
237 * @throws SQLException if there is an error accessing the | |
238 * BLOB value | |
239 */ | |
240 @Override | |
241 public int setBytes(long pos, byte[] bytes) throws SQLException { | |
242 return setBytes(pos, bytes, 1, bytes.length); | |
243 } | |
244 | |
245 /** | |
246 * Writes all or part of the given byte array to the BLOB value that | |
247 * this Blob object represents and returns the number of bytes | |
248 * written. Writing starts at position pos in the BLOB value; len | |
249 * bytes from the given byte array are written. | |
250 * | |
251 * @param pos the position in the BLOB object at which to start | |
252 * writing | |
253 * @param bytes the array of bytes to be written to this BLOB | |
254 * object | |
255 * @param offset the offset into the array bytes at which to start | |
256 * reading the bytes to be set | |
257 * @param len the number of bytes to be written to the BLOB value | |
258 * from the array of bytes bytes | |
259 * @return the number of bytes written | |
260 * @throws SQLException if there is an error accessing the | |
261 * BLOB value | |
262 */ | |
263 @Override | |
264 public int setBytes(long pos, byte[] bytes, int offset, int len) | |
265 throws SQLException | |
266 { | |
267 if (buf == null) | |
268 throw new SQLException("This Blob object has been freed", "M1M20"); | |
269 try { | |
270 /* transactions? what are you talking about? */ | |
271 for (int i = (int)pos; i < len; i++) | |
272 buf[i] = bytes[offset - 1 + i]; | |
273 } catch (IndexOutOfBoundsException e) { | |
274 throw new SQLException(e.getMessage(), "M0M10"); | |
275 } | |
276 return len; | |
277 } | |
278 | |
279 /** | |
280 * Truncates the BLOB value that this Blob object represents to be | |
281 * len bytes in length. | |
282 * | |
283 * @param len the length, in bytes, to which the BLOB value | |
284 * should be truncated | |
285 * @throws SQLException if there is an error accessing the | |
286 * BLOB value | |
287 */ | |
288 @Override | |
289 public void truncate(long len) throws SQLException { | |
290 if (buf == null) | |
291 throw new SQLException("This Blob object has been freed", "M1M20"); | |
292 if (buf.length > len) { | |
293 byte[] newbuf = new byte[(int)len]; | |
294 for (int i = 0; i < len; i++) | |
295 newbuf[i] = buf[i]; | |
296 buf = newbuf; | |
297 } | |
298 } | |
299 } |