Skip to content

Commit 9515a80

Browse files
authored
feat(jdbc): support JDBC4 CLOB and BLOB in PreparedStatement parameters
1 parent e20d3b6 commit 9515a80

File tree

3 files changed

+83
-23
lines changed

3 files changed

+83
-23
lines changed

src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,14 @@ public void setString(int pos, String value) throws SQLException {
390390
/** @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int) */
391391
public void setCharacterStream(int pos, Reader reader, int length) throws SQLException {
392392
try {
393-
// copy chars from reader to StringBuffer
394-
StringBuffer sb = new StringBuffer();
393+
// copy chars from reader to StringBuilder
394+
StringBuilder sb = new StringBuilder();
395395
char[] cbuf = new char[8192];
396396
int cnt;
397397

398-
while ((cnt = reader.read(cbuf)) > 0) {
398+
while ((cnt = reader.read(cbuf, 0, Math.min(length, cbuf.length))) > 0) {
399399
sb.append(cbuf, 0, cnt);
400+
length -= cnt;
400401
}
401402

402403
// set as string

src/main/java/org/sqlite/jdbc4/JDBC4PreparedStatement.java

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.sqlite.jdbc4;
22

3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
36
import java.io.InputStream;
47
import java.io.Reader;
58
import java.sql.NClob;
@@ -48,14 +51,21 @@ public void setNClob(int parameterIndex, NClob value) throws SQLException {
4851
}
4952

5053
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
51-
// TODO Support this
52-
throw new SQLFeatureNotSupportedException();
54+
requireLengthIsPositiveInt(length);
55+
setCharacterStream(parameterIndex, reader, (int) length);
56+
}
57+
58+
private void requireLengthIsPositiveInt(long length) throws SQLFeatureNotSupportedException {
59+
if (length > Integer.MAX_VALUE || length < 0) {
60+
throw new SQLFeatureNotSupportedException(
61+
"Data must have a length between 0 and Integer.MAX_VALUE");
62+
}
5363
}
5464

5565
public void setBlob(int parameterIndex, InputStream inputStream, long length)
5666
throws SQLException {
57-
// TODO Support this
58-
throw new SQLFeatureNotSupportedException();
67+
requireLengthIsPositiveInt(length);
68+
setBinaryStream(parameterIndex, inputStream, (int) length);
5969
}
6070

6171
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
@@ -69,35 +79,59 @@ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
6979
}
7080

7181
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
72-
// TODO Support this
73-
throw new SQLFeatureNotSupportedException();
82+
requireLengthIsPositiveInt(length);
83+
setAsciiStream(parameterIndex, x, (int) length);
7484
}
7585

7686
public void setBinaryStream(int parameterIndex, InputStream x, long length)
7787
throws SQLException {
78-
// TODO Support this
79-
throw new SQLFeatureNotSupportedException();
88+
requireLengthIsPositiveInt(length);
89+
setBinaryStream(parameterIndex, x, (int) length);
8090
}
8191

8292
public void setCharacterStream(int parameterIndex, Reader reader, long length)
8393
throws SQLException {
84-
// TODO Support this
85-
throw new SQLFeatureNotSupportedException();
94+
requireLengthIsPositiveInt(length);
95+
setCharacterStream(parameterIndex, reader, (int) length);
8696
}
8797

8898
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
89-
// TODO Support this
90-
throw new SQLFeatureNotSupportedException();
99+
byte[] bytes = readBytes(x);
100+
setAsciiStream(parameterIndex, new ByteArrayInputStream(bytes), bytes.length);
101+
}
102+
103+
/**
104+
* Reads given number of bytes from an input stream.
105+
*
106+
* @param istream The input stream.
107+
* @param length The number of bytes to read.
108+
* @return byte array.
109+
* @throws SQLException
110+
*/
111+
private byte[] readBytes(InputStream istream) throws SQLException {
112+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
113+
byte[] bytes = new byte[8192];
114+
115+
try {
116+
int bytesRead;
117+
while ((bytesRead = istream.read(bytes)) > 0) {
118+
baos.write(bytes, 0, bytesRead);
119+
}
120+
return baos.toByteArray();
121+
} catch (IOException cause) {
122+
SQLException exception = new SQLException("Error reading stream");
123+
124+
exception.initCause(cause);
125+
throw exception;
126+
}
91127
}
92128

93129
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
94-
// TODO Support this
95-
throw new SQLFeatureNotSupportedException();
130+
setBytes(parameterIndex, readBytes(x));
96131
}
97132

98133
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
99-
// TODO Support this
100-
throw new SQLFeatureNotSupportedException();
134+
setCharacterStream(parameterIndex, reader, Integer.MAX_VALUE);
101135
}
102136

103137
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
@@ -106,13 +140,11 @@ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLExce
106140
}
107141

108142
public void setClob(int parameterIndex, Reader reader) throws SQLException {
109-
// TODO Support this
110-
throw new SQLFeatureNotSupportedException();
143+
setCharacterStream(parameterIndex, reader, Integer.MAX_VALUE);
111144
}
112145

113146
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
114-
// TODO Support this
115-
throw new SQLFeatureNotSupportedException();
147+
setBytes(parameterIndex, readBytes(inputStream));
116148
}
117149

118150
public void setNClob(int parameterIndex, Reader reader) throws SQLException {

src/test/java/org/sqlite/PrepStmtTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static org.assertj.core.data.Offset.offset;
88

99
import java.io.ByteArrayInputStream;
10+
import java.io.StringReader;
1011
import java.math.BigDecimal;
1112
import java.nio.charset.StandardCharsets;
1213
import java.sql.Connection;
@@ -177,6 +178,32 @@ public void stringRS() throws SQLException {
177178
rs.close();
178179
}
179180

181+
@Test
182+
public void clobRS() throws SQLException {
183+
String name = "Gandhi";
184+
PreparedStatement prep = conn.prepareStatement("select ?;");
185+
prep.setClob(1, new StringReader(name));
186+
ResultSet rs = prep.executeQuery();
187+
assertThat(prep.getUpdateCount()).isEqualTo(-1);
188+
assertThat(rs.next()).isTrue();
189+
assertThat(rs.getString(1)).isEqualTo(name);
190+
assertThat(rs.next()).isFalse();
191+
rs.close();
192+
}
193+
194+
@Test
195+
public void blobRS() throws SQLException {
196+
String name = "Gandhi";
197+
PreparedStatement prep = conn.prepareStatement("select ?;");
198+
prep.setBlob(1, new ByteArrayInputStream(name.getBytes()));
199+
ResultSet rs = prep.executeQuery();
200+
assertThat(prep.getUpdateCount()).isEqualTo(-1);
201+
assertThat(rs.next()).isTrue();
202+
assertThat(rs.getBytes(1)).isEqualTo(name.getBytes());
203+
assertThat(rs.next()).isFalse();
204+
rs.close();
205+
}
206+
180207
@Test
181208
public void finalizePrep() throws SQLException {
182209
conn.prepareStatement("select null;");

0 commit comments

Comments
 (0)