This is an automated email from the ASF dual-hosted git repository.
nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 95afef05ca5 IGNITE-6141 JDBC: add basic support for BLOB and CLOB
types (#11492)
95afef05ca5 is described below
commit 95afef05ca5cbd278734813162d10e04a09cdcf3
Author: Sergey Korotkov <[email protected]>
AuthorDate: Wed Sep 11 14:23:20 2024 +0700
IGNITE-6141 JDBC: add basic support for BLOB and CLOB types (#11492)
Co-authored-by: rkondakov <[email protected]>
---
.../jdbc2/JdbcAbstractDmlStatementSelfTest.java | 26 +-
.../jdbc2/JdbcAbstractUpdateStatementSelfTest.java | 8 +-
.../apache/ignite/internal/jdbc2/JdbcBlobTest.java | 3 +
.../apache/ignite/internal/jdbc2/JdbcClobTest.java | 452 +++++++++++++++++++++
.../jdbc2/JdbcInsertStatementSelfTest.java | 59 ++-
.../internal/jdbc2/JdbcMergeStatementSelfTest.java | 48 ++-
.../jdbc2/JdbcPreparedStatementSelfTest.java | 54 ++-
.../internal/jdbc2/JdbcResultSetSelfTest.java | 51 ++-
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 +
.../thin/JdbcThinAbstractDmlStatementSelfTest.java | 72 +++-
.../JdbcThinAbstractUpdateStatementSelfTest.java | 8 +-
.../jdbc/thin/JdbcThinConnectionSelfTest.java | 24 +-
.../jdbc/thin/JdbcThinInsertStatementSelfTest.java | 41 +-
.../jdbc/thin/JdbcThinMergeStatementSelfTest.java | 25 +-
.../thin/JdbcThinPreparedStatementSelfTest.java | 82 +++-
.../jdbc/thin/JdbcThinResultSetSelfTest.java | 76 ++--
.../internal/jdbc/thin/JdbcThinConnection.java | 6 +-
.../jdbc/thin/JdbcThinPreparedStatement.java | 8 +-
.../internal/jdbc/thin/JdbcThinResultSet.java | 18 +-
.../org/apache/ignite/internal/jdbc2/JdbcBlob.java | 2 +-
.../org/apache/ignite/internal/jdbc2/JdbcClob.java | 326 +++++++++++++++
.../ignite/internal/jdbc2/JdbcConnection.java | 2 +-
.../internal/jdbc2/JdbcPreparedStatement.java | 4 +-
.../ignite/internal/jdbc2/JdbcResultSet.java | 8 +-
.../processors/query/h2/IgniteH2Indexing.java | 5 +-
.../processors/query/h2/QueryParameters.java | 11 +
26 files changed, 1242 insertions(+), 179 deletions(-)
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
index c1142e19685..d1ddd2ba0ba 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
@@ -20,9 +20,11 @@ package org.apache.ignite.internal.jdbc2;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.sql.Blob;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
+import java.util.Arrays;
import java.util.Collections;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
@@ -53,7 +55,7 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
CFG_URL_PREFIX + "cache=" + DEFAULT_CACHE_NAME +
"@modules/clients/src/test/config/jdbc-bin-config.xml";
/** SQL SELECT query for verification. */
- static final String SQL_SELECT = "select _key, id, firstName, lastName,
age, data from Person";
+ static final String SQL_SELECT = "select _key, id, firstName, lastName,
age, data, text from Person";
/** Alias for _key */
private static final String KEY_ALIAS = "key";
@@ -112,6 +114,7 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
e.addQueryField("firstName", String.class.getName(), null);
e.addQueryField("lastName", String.class.getName(), null);
e.addQueryField("data", byte[].class.getName(), null);
+ e.addQueryField("text", String.class.getName(), null);
cache.setQueryEntities(Collections.singletonList(e));
@@ -189,6 +192,18 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
}
}
+ /**
+ * @param clob Clob.
+ */
+ static String str(Clob clob) {
+ try {
+ return clob.getSubString(1, (int)clob.length());
+ }
+ catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Person.
*/
@@ -213,6 +228,10 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
@QuerySqlField
private final byte[] data;
+ /** CLOB data. */
+ @QuerySqlField
+ private final String text;
+
/**
* @param id ID.
* @param firstName First name.
@@ -229,6 +248,7 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
this.lastName = lastName;
this.age = age;
this.data = getBytes(lastName);
+ this.text = firstName + " " + lastName;
}
/** {@inheritDoc} */
@@ -241,6 +261,8 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
if (id != person.id) return false;
if (age != person.age) return false;
if (firstName != null ? !firstName.equals(person.firstName) :
person.firstName != null) return false;
+ if (data != null ? !Arrays.equals(data, person.data) : person.data
!= null) return false;
+ if (text != null ? !text.equals(person.text) : person.text !=
null) return false;
return lastName != null ? lastName.equals(person.lastName) :
person.lastName == null;
}
@@ -251,6 +273,8 @@ public abstract class JdbcAbstractDmlStatementSelfTest
extends GridCommonAbstrac
result = 31 * result + (firstName != null ? firstName.hashCode() :
0);
result = 31 * result + (lastName != null ? lastName.hashCode() :
0);
result = 31 * result + age;
+ result = 31 * result + (data != null ? Arrays.hashCode(data) : 0);
+ result = 31 * result + (text != null ? text.hashCode() : 0);
return result;
}
}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractUpdateStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractUpdateStatementSelfTest.java
index ace1be66561..66d81a5d0bf 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractUpdateStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractUpdateStatementSelfTest.java
@@ -24,10 +24,10 @@ import java.sql.Statement;
*/
public abstract class JdbcAbstractUpdateStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest {
/** SQL query to populate cache. */
- private static final String ITEMS_SQL = "insert into Person(_key, id,
firstName, lastName, age, data) values " +
- "('p1', 1, 'John', 'White', 25, RAWTOHEX('White')), " +
- "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black')), " +
- "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'))";
+ private static final String ITEMS_SQL = "insert into Person(_key, id,
firstName, lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcBlobTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcBlobTest.java
index 1680161e07a..0b0119e48e9 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcBlobTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcBlobTest.java
@@ -113,6 +113,9 @@ public class JdbcBlobTest {
res = blob.getBytes(1, 0);
assertEquals(0, res.length);
+ blob = new JdbcBlob(new byte[0]);
+ assertEquals(0, blob.getBytes(1, 0).length);
+
blob.free();
try {
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcClobTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcClobTest.java
new file mode 100644
index 00000000000..6dc5826d6e6
--- /dev/null
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcClobTest.java
@@ -0,0 +1,452 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.jdbc2;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Clob;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for JDBC CLOB.
+ */
+public class JdbcClobTest {
+ /** */
+ static final String ERROR_CLOB_FREE = "Clob instance can't be used after
free() has been called.";
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testLength() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertEquals(10, clob.length());
+
+ clob.free();
+ assertThrows(null, clob::length, SQLException.class, ERROR_CLOB_FREE);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetSubString() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob.getSubString(-1, 1), SQLException.class,
null);
+
+ assertThrows(null, () -> clob.getSubString(0, 1), SQLException.class,
null);
+
+ assertThrows(null, () -> clob.getSubString(1, -1), SQLException.class,
null);
+
+ assertThrows(null, () -> clob.getSubString(1, 11), SQLException.class,
null);
+
+ assertEquals("", clob.getSubString(3, 0));
+
+ assertEquals("1", clob.getSubString(1, 1));
+
+ assertEquals("0", clob.getSubString(10, 1));
+
+ assertEquals("12345", clob.getSubString(1, 5));
+
+ assertEquals("34567", clob.getSubString(3, 5));
+
+ assertEquals("567890", clob.getSubString(5, 6));
+
+ assertEquals("1234567890", clob.getSubString(1, 10));
+
+ clob.free();
+ assertThrows(null, () -> clob.getSubString(1, 10), SQLException.class,
ERROR_CLOB_FREE);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetCharacterStream() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ Reader cStream = clob.getCharacterStream();
+ String res = IOUtils.toString(cStream);
+ assertEquals("1234567890", res);
+
+ clob.free();
+ assertThrows(null, () -> clob.getCharacterStream(),
SQLException.class, ERROR_CLOB_FREE);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetCharacterStreamWithParams() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob.getCharacterStream(-1, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.getCharacterStream(0, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.getCharacterStream(1, -1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.getCharacterStream(1, 11),
SQLException.class, null);
+
+ Reader cStream = clob.getCharacterStream(1, 10);
+ String res = IOUtils.toString(cStream);
+ assertEquals("1234567890", res);
+
+ cStream = clob.getCharacterStream(1, 1);
+ res = IOUtils.toString(cStream);
+ assertEquals("1", res);
+
+ cStream = clob.getCharacterStream(10, 1);
+ res = IOUtils.toString(cStream);
+ assertEquals("0", res);
+
+ cStream = clob.getCharacterStream(3, 5);
+ res = IOUtils.toString(cStream);
+ assertEquals("34567", res);
+
+ cStream = clob.getCharacterStream(3, 0);
+ res = IOUtils.toString(cStream);
+ assertEquals("", res);
+
+ clob.free();
+ assertThrows(null, () -> clob.getCharacterStream(1, 1),
SQLException.class, ERROR_CLOB_FREE);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetAsciiStream() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+ byte[] bytes = IOUtils.toByteArray(clob.getAsciiStream());
+ Assert.assertArrayEquals("1234567890".getBytes(UTF_8), bytes);
+
+ clob.free();
+ assertThrows(null, clob::getAsciiStream, SQLException.class,
ERROR_CLOB_FREE);
+
+ Clob emptyClob = new JdbcClob("");
+ bytes = IOUtils.toByteArray(emptyClob.getAsciiStream());
+ Assert.assertArrayEquals("".getBytes(UTF_8), bytes);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetAsciiStreamForNonAsciiDataBufferedRead() throws
Exception {
+ StringBuilder sb = new StringBuilder();
+
+ // Create string in a way which makes sure that all variants in
+ // JdbcClob.Utf8EncodedStringInputStream.encodeNextChunk() are covered.
+ // In particular the check for the surrogate element.
+ for (int i = 0; i < 3277; i++) {
+ sb.append("aa©😀");
+ }
+
+ Clob clob = new JdbcClob(sb.toString());
+
+ InputStream stream = clob.getAsciiStream();
+
+ assertThrows(null, () -> stream.read(null, 0, 1),
NullPointerException.class, null);
+
+ assertThrows(null, () -> stream.read(new byte[10], -1, 5),
IndexOutOfBoundsException.class, null);
+
+ assertThrows(null, () -> stream.read(new byte[10], 5, -1),
IndexOutOfBoundsException.class, null);
+
+ assertThrows(null, () -> stream.read(new byte[10], 11, 1),
IndexOutOfBoundsException.class, null);
+
+ assertThrows(null, () -> stream.read(new byte[10], 5, 6),
IndexOutOfBoundsException.class, null);
+
+ assertEquals(0, stream.read(new byte[10], 5, 0));
+
+ byte[] bytes = IOUtils.toByteArray(stream);
+
+ String reencoded = new String(bytes, UTF_8);
+
+ assertEquals(clob.getSubString(1, (int)clob.length()), reencoded);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testGetAsciiStreamForNonAsciiDataReadByByte() throws Exception
{
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 10; i++) {
+ sb.append("aa©😀");
+ }
+
+ Clob clob = new JdbcClob(sb.toString());
+
+ InputStream stream = clob.getAsciiStream();
+
+ int i = 0;
+ byte[] bytes = new byte[80];
+
+ byte val = (byte)stream.read();
+
+ while (val != -1) {
+ bytes[i++] = val;
+
+ val = (byte)stream.read();
+ }
+
+ String reencoded = new String(bytes, UTF_8);
+
+ assertEquals(clob.getSubString(1, (int)clob.length()), reencoded);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testPositionWithStringPattern() throws Exception {
+ JdbcClob clob1 = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob1.position("0", 0), SQLException.class,
null);
+
+ assertThrows(null, () -> clob1.position("0", -1), SQLException.class,
null);
+
+ assertEquals(1, clob1.position("", 1));
+
+ assertEquals(10, clob1.position("", 10));
+
+ assertEquals(11, clob1.position("", 100));
+
+ assertEquals(-1, clob1.position("a", 11));
+
+ assertEquals(1, clob1.position("1", 1));
+
+ assertEquals(5, clob1.position("56", 1));
+
+ assertEquals(5, clob1.position("56", 5));
+
+ assertEquals(-1, clob1.position("56", 6));
+
+ clob1.free();
+ assertThrows(null, clob1::getAsciiStream, SQLException.class,
ERROR_CLOB_FREE);
+
+ Clob clob2 = new JdbcClob("abbabab");
+
+ assertEquals(5, clob2.position("b", 4));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testPositionWithClobPattern() throws Exception {
+ Clob clob = new JdbcClob("1234567890");
+
+ Clob patternClob = new JdbcClob("567");
+
+ assertThrows(null, () -> clob.position(patternClob, 0),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.position(patternClob, -1),
SQLException.class, null);
+
+ assertEquals(5, clob.position(patternClob, 1));
+
+ assertEquals(5, clob.position(patternClob, 5));
+
+ assertEquals(-1, clob.position(patternClob, 6));
+
+ Clob patternClob2 = new JdbcClob("a");
+
+ assertEquals(-1, clob.position(patternClob2, 1));
+
+ clob.free();
+ assertThrows(null, () -> clob.position(patternClob2, 5),
SQLException.class, ERROR_CLOB_FREE);
+
+ Clob clob2 = new JdbcClob("bbabbabba");
+
+ assertEquals(6, clob2.position(patternClob2, 5));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testSetString() throws Exception {
+ JdbcClob clob1 = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob1.setString(-1, "a"), SQLException.class,
null);
+
+ assertThrows(null, () -> clob1.setString(0, "a"), SQLException.class,
null);
+
+ assertThrows(null, () -> clob1.setString(clob1.length() + 2, "a"),
SQLException.class, null);
+
+ assertThrows(null, () -> clob1.setString(1, null), SQLException.class,
null);
+
+ int written = clob1.setString(1, "a");
+ assertEquals("a", clob1.getSubString(1, 1));
+ assertEquals(1, written);
+
+ written = clob1.setString(5, "abc");
+ assertEquals("abc", clob1.getSubString(5, 3));
+ assertEquals(3, written);
+
+ written = clob1.setString(10, "def");
+ assertEquals("def", clob1.getSubString(10, 3));
+ assertEquals(3, written);
+
+ clob1.free();
+ assertThrows(null, () -> clob1.setString(1, "a"), SQLException.class,
ERROR_CLOB_FREE);
+
+ Clob clob2 = new JdbcClob("12345");
+ written = clob2.setString(3, "abcd");
+ assertEquals("12abcd", clob2.getSubString(1, (int)clob2.length()));
+ assertEquals(4, written);
+
+ Clob clob3 = new JdbcClob("12345");
+ written = clob3.setString(3, "ab");
+ assertEquals("12ab5", clob3.getSubString(1, (int)clob3.length()));
+ assertEquals(2, written);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testSetStringWithSubString() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob.setString(-1, "a", 0, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(0, "a", 0, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(clob.length() + 2, "a", 0, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(1, null, 0, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(1, "a", -1, 1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(1, "a", 0, -1),
SQLException.class, null);
+
+ assertThrows(null, () -> clob.setString(1, "abc", 1, 3),
SQLException.class, null);
+
+ clob.free();
+ assertThrows(null, () -> clob.setString(1, "a", 0, 1),
SQLException.class, ERROR_CLOB_FREE);
+
+ Clob clob2 = new JdbcClob("1234567890");
+ int written = clob2.setString(3, "abcd", 0, 1);
+ assertEquals("12a4567890", clob2.getSubString(1, (int)clob2.length()));
+ assertEquals(1, written);
+
+ clob2 = new JdbcClob("1234567890");
+ written = clob2.setString(1, "abcd", 0, 3);
+ assertEquals("abc4567890", clob2.getSubString(1, (int)clob2.length()));
+ assertEquals(3, written);
+
+ clob2 = new JdbcClob("1234567890");
+ written = clob2.setString(5, "abcd", 2, 2);
+ assertEquals("1234cd7890", clob2.getSubString(1, (int)clob2.length()));
+ assertEquals(2, written);
+
+ clob2 = new JdbcClob("1234567890");
+ written = clob2.setString(9, "abcd", 0, 4);
+ assertEquals("12345678abcd", clob2.getSubString(1,
(int)clob2.length()));
+ assertEquals(4, written);
+
+ clob2 = new JdbcClob("1234567890");
+ written = clob2.setString(11, "abcd", 0, 4);
+ assertEquals("1234567890abcd", clob2.getSubString(1,
(int)clob2.length()));
+ assertEquals(4, written);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testTruncate() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> {
+ clob.truncate(-1);
+
+ return null;
+ }, SQLException.class, null);
+
+ assertThrows(null, () -> {
+ clob.truncate(clob.length() + 1);
+
+ return null;
+ }, SQLException.class, null);
+
+ clob.truncate(9);
+ assertEquals("123456789", clob.getSubString(1, (int)clob.length()));
+
+ clob.truncate(5);
+ assertEquals("12345", clob.getSubString(1, (int)clob.length()));
+
+ clob.truncate(0);
+ assertEquals("", clob.getSubString(1, (int)clob.length()));
+
+ clob.free();
+ assertThrows(null, () -> {
+ clob.truncate(1);
+
+ return null;
+ }, SQLException.class, ERROR_CLOB_FREE);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testSetAsciiStream() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob.setAsciiStream(1L),
SQLFeatureNotSupportedException.class, null);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testSetCharacterStream() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ assertThrows(null, () -> clob.setCharacterStream(1L),
SQLFeatureNotSupportedException.class, null);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testFree() throws Exception {
+ JdbcClob clob = new JdbcClob("1234567890");
+
+ clob.length();
+
+ clob.free();
+
+ clob.free();
+
+ assertThrows(null, clob::length, SQLException.class, ERROR_CLOB_FREE);
+ }
+}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
index 6b39ccb587d..072155f4d3e 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.jdbc2;
import java.sql.BatchUpdateException;
+import java.sql.Blob;
+import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -36,14 +38,14 @@ import org.junit.Test;
*/
public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest {
/** SQL query. */
- private static final String SQL = "insert into Person(_key, id, firstName,
lastName, age, data) values " +
- "('p1', 1, 'John', 'White', 25, RAWTOHEX('White')), " +
- "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black')), " +
- "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'))";
+ private static final String SQL = "insert into Person(_key, id, firstName,
lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** SQL query. */
- private static final String SQL_PREPARED = "insert into Person(_key, id,
firstName, lastName, age, data) values " +
- "(?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?)";
+ private static final String SQL_PREPARED = "insert into Person(_key, id,
firstName, lastName, age, data, text) " +
+ "values (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?)";
/** Statement. */
private Statement stmt;
@@ -83,6 +85,7 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
assertEquals("White", rs.getString("lastName"));
assertEquals(25, rs.getInt("age"));
assertEquals("White",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("John White", str(rs.getClob("text")));
break;
case 2:
@@ -91,6 +94,7 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
assertEquals("Black", rs.getString("lastName"));
assertEquals(35, rs.getInt("age"));
assertEquals("Black",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Joe Black", str(rs.getClob("text")));
break;
case 3:
@@ -99,6 +103,7 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
assertEquals("Green", rs.getString("lastName"));
assertEquals(40, rs.getInt("age"));
assertEquals("Green",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Mike Green", str(rs.getClob("text")));
break;
case 4:
@@ -107,6 +112,7 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
assertEquals("Grey", rs.getString("lastName"));
assertEquals(22, rs.getInt("age"));
assertEquals("Grey",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Leah Grey", str(rs.getClob("text")));
break;
default:
@@ -302,6 +308,9 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
private void formBatch(int id1, int id2) throws SQLException {
int[] ids = new int[] { id1, id2 };
+ Clob clob;
+ Blob blob;
+
int arg = 0;
for (int id: ids) {
String key = "p" + id;
@@ -313,7 +322,14 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
prepStmt.setString(arg + 3, "John");
prepStmt.setString(arg + 4, "White");
prepStmt.setInt(arg + 5, 25);
- prepStmt.setBytes(arg + 6, getBytes("White"));
+
+ blob = conn.createBlob();
+ blob.setBytes(1, getBytes("White"));
+ prepStmt.setBlob(arg + 6, blob);
+
+ clob = conn.createClob();
+ clob.setString(1, "John White");
+ prepStmt.setClob(arg + 7, clob);
break;
@@ -323,7 +339,14 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
prepStmt.setString(arg + 3, "Joe");
prepStmt.setString(arg + 4, "Black");
prepStmt.setInt(arg + 5, 35);
- prepStmt.setBytes(arg + 6, getBytes("Black"));
+
+ blob = conn.createBlob();
+ blob.setBytes(1, getBytes("Black"));
+ prepStmt.setBlob(arg + 6, blob);
+
+ clob = conn.createClob();
+ clob.setString(1, "Joe Black");
+ prepStmt.setClob(arg + 7, clob);
break;
@@ -333,7 +356,14 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
prepStmt.setString(arg + 3, "Mike");
prepStmt.setString(arg + 4, "Green");
prepStmt.setInt(arg + 5, 40);
- prepStmt.setBytes(arg + 6, getBytes("Green"));
+
+ blob = conn.createBlob();
+ blob.setBytes(1, getBytes("Green"));
+ prepStmt.setBlob(arg + 6, blob);
+
+ clob = conn.createClob();
+ clob.setString(1, "Mike Green");
+ prepStmt.setClob(arg + 7, clob);
break;
@@ -343,7 +373,14 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
prepStmt.setString(arg + 3, "Leah");
prepStmt.setString(arg + 4, "Grey");
prepStmt.setInt(arg + 5, 22);
- prepStmt.setBytes(arg + 6, getBytes("Grey"));
+
+ blob = conn.createBlob();
+ blob.setBytes(1, getBytes("Grey"));
+ prepStmt.setBlob(arg + 6, blob);
+
+ clob = conn.createClob();
+ clob.setString(1, "Leah Grey");
+ prepStmt.setClob(arg + 7, clob);
break;
@@ -351,7 +388,7 @@ public class JdbcInsertStatementSelfTest extends
JdbcAbstractDmlStatementSelfTes
assert false;
}
- arg += 6;
+ arg += 7;
}
prepStmt.addBatch();
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMergeStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMergeStatementSelfTest.java
index 3923333a4e5..c5da516d957 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMergeStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMergeStatementSelfTest.java
@@ -30,14 +30,14 @@ import org.junit.Test;
*/
public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest {
/** SQL query. */
- private static final String SQL = "merge into Person(_key, id, firstName,
lastName, age, data) values " +
- "('p1', 1, 'John', 'White', 25, RAWTOHEX('White')), " +
- "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black')), " +
- "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'))";
+ private static final String SQL = "merge into Person(_key, id, firstName,
lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** SQL query. */
- protected static final String SQL_PREPARED = "merge into Person(_key, id,
firstName, lastName, age, data) values " +
- "(?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?)";
+ protected static final String SQL_PREPARED = "merge into Person(_key, id,
firstName, lastName, age, data, text) " +
+ "values (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?)";
/** Statement. */
protected Statement stmt;
@@ -77,6 +77,7 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
assertEquals("White", rs.getString("lastName"));
assertEquals(25, rs.getInt("age"));
assertEquals("White",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("John White", str(rs.getClob("text")));
break;
case 2:
@@ -85,6 +86,7 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
assertEquals("Black", rs.getString("lastName"));
assertEquals(35, rs.getInt("age"));
assertEquals("Black",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Joe Black", str(rs.getClob("text")));
break;
case 3:
@@ -93,6 +95,7 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
assertEquals("Green", rs.getString("lastName"));
assertEquals(40, rs.getInt("age"));
assertEquals("Green",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Mike Green", str(rs.getClob("text")));
break;
case 4:
@@ -101,6 +104,7 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
assertEquals("Grey", rs.getString("lastName"));
assertEquals(22, rs.getInt("age"));
assertEquals("Grey",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Leah Grey", str(rs.getClob("text")));
break;
default:
@@ -159,13 +163,15 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
prepStmt.setString(4, "White");
prepStmt.setInt(5, 25);
prepStmt.setBytes(6, getBytes("White"));
-
- prepStmt.setString(7, "p2");
- prepStmt.setInt(8, 2);
- prepStmt.setString(9, "Joe");
- prepStmt.setString(10, "Black");
- prepStmt.setInt(11, 35);
- prepStmt.setBytes(12, getBytes("Black"));
+ prepStmt.setString(7, "John White");
+
+ prepStmt.setString(8, "p2");
+ prepStmt.setInt(9, 2);
+ prepStmt.setString(10, "Joe");
+ prepStmt.setString(11, "Black");
+ prepStmt.setInt(12, 35);
+ prepStmt.setBytes(13, getBytes("Black"));
+ prepStmt.setString(14, "Joe Black");
prepStmt.addBatch();
prepStmt.setString(1, "p3");
@@ -174,13 +180,15 @@ public class JdbcMergeStatementSelfTest extends
JdbcAbstractDmlStatementSelfTest
prepStmt.setString(4, "Green");
prepStmt.setInt(5, 40);
prepStmt.setBytes(6, getBytes("Green"));
-
- prepStmt.setString(7, "p4");
- prepStmt.setInt(8, 4);
- prepStmt.setString(9, "Leah");
- prepStmt.setString(10, "Grey");
- prepStmt.setInt(11, 22);
- prepStmt.setBytes(12, getBytes("Grey"));
+ prepStmt.setString(7, "Mike Green");
+
+ prepStmt.setString(8, "p4");
+ prepStmt.setInt(9, 4);
+ prepStmt.setString(10, "Leah");
+ prepStmt.setString(11, "Grey");
+ prepStmt.setInt(12, 22);
+ prepStmt.setBytes(13, getBytes("Grey"));
+ prepStmt.setString(14, "Leah Grey");
prepStmt.addBatch();
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
index 98998d21f54..4cbee28c77b 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
@@ -21,6 +21,7 @@ import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Blob;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@@ -38,7 +39,9 @@ import org.junit.Test;
import static java.sql.Types.BIGINT;
import static java.sql.Types.BINARY;
+import static java.sql.Types.BLOB;
import static java.sql.Types.BOOLEAN;
+import static java.sql.Types.CLOB;
import static java.sql.Types.DATALINK;
import static java.sql.Types.DATE;
import static java.sql.Types.DOUBLE;
@@ -108,6 +111,7 @@ public class JdbcPreparedStatementSelfTest extends
GridCommonAbstractTest {
o.strVal = "str";
o.arrVal = new byte[] {1};
o.blobVal = new byte[] {1};
+ o.clobVal = "large str";
o.dateVal = new Date(1);
o.timeVal = new Time(1);
o.tsVal = new Timestamp(1);
@@ -571,31 +575,45 @@ public class JdbcPreparedStatementSelfTest extends
GridCommonAbstractTest {
ResultSet rs = stmt.executeQuery();
- int cnt = 0;
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt("id"));
+ assertFalse(rs.next());
- while (rs.next()) {
- if (cnt == 0)
- assert rs.getInt("id") == 1;
+ stmt.setNull(1, BLOB);
- cnt++;
- }
+ rs = stmt.executeQuery();
- assertEquals(1, cnt);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt("id"));
+ assertFalse(rs.next());
+ }
- stmt.setNull(1, BINARY);
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testClob() throws Exception {
+ stmt = conn.prepareStatement("select * from TestObject where clobVal
is not distinct from ?");
- rs = stmt.executeQuery();
+ Clob clob = conn.createClob();
- cnt = 0;
+ clob.setString(1, "large str");
- while (rs.next()) {
- if (cnt == 0)
- assert rs.getInt("id") == 2;
+ stmt.setClob(1, clob);
- cnt++;
- }
+ ResultSet rs = stmt.executeQuery();
- assert cnt == 1;
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt("id"));
+ assertFalse(rs.next());
+
+ stmt.setNull(1, CLOB);
+
+ rs = stmt.executeQuery();
+
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt("id"));
+ assertFalse(rs.next());
}
/**
@@ -802,6 +820,10 @@ public class JdbcPreparedStatementSelfTest extends
GridCommonAbstractTest {
@QuerySqlField
private byte[] blobVal;
+ /** */
+ @QuerySqlField
+ private String clobVal;
+
/** */
@QuerySqlField
private Date dateVal;
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
index e65bacdc35c..1470a5cfcf3 100644
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
@@ -22,6 +22,8 @@ import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
+import java.sql.Blob;
+import java.sql.Clob;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
@@ -46,6 +48,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
import org.junit.Test;
import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
@@ -64,7 +67,7 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
private static final String SQL =
"select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
"doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal,
urlVal, f1, f2, f3, _val, " +
- "boolVal2, boolVal3, boolVal4 " +
+ "boolVal2, boolVal3, boolVal4, blobVal, clobVal " +
"from TestObject where id = 1";
/** Statement. */
@@ -145,6 +148,8 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
o.bigVal = new BigDecimal(1);
o.strVal = "1";
o.arrVal = new byte[] {1};
+ o.blobVal = new byte[] {1};
+ o.clobVal = "str";
o.dateVal = new Date(1, 1, 1);
o.timeVal = new Time(1, 1, 1);
o.tsVal = new Timestamp(1);
@@ -670,6 +675,38 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
assert cnt == 1;
}
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testBlob() throws Exception {
+ ResultSet rs = stmt.executeQuery(SQL);
+
+ assertTrue(rs.next());
+ Blob blob = rs.getBlob("blobVal");
+ Assert.assertArrayEquals(blob.getBytes(1, (int)blob.length()), new
byte[] {1});
+
+ blob = rs.getBlob(23);
+ Assert.assertArrayEquals(blob.getBytes(1, (int)blob.length()), new
byte[] {1});
+ assertFalse(rs.next());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testClob() throws Exception {
+ ResultSet rs = stmt.executeQuery(SQL);
+
+ assertTrue(rs.next());
+ Clob clob = rs.getClob("clobVal");
+ Assert.assertEquals("str", clob.getSubString(1, (int)clob.length()));
+
+ clob = rs.getClob(24);
+ Assert.assertEquals("str", clob.getSubString(1, (int)clob.length()));
+ assertFalse(rs.next());
+ }
+
/**
* @throws Exception If failed.
*/
@@ -990,6 +1027,14 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
@QuerySqlField(index = false)
private byte[] arrVal;
+ /** */
+ @QuerySqlField(index = false)
+ private byte[] blobVal;
+
+ /** */
+ @QuerySqlField(index = false)
+ private String clobVal;
+
/** */
@QuerySqlField(index = false)
private Date dateVal;
@@ -1056,6 +1101,8 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
if (timeVal != null ? !timeVal.equals(that.timeVal) : that.timeVal
!= null) return false;
if (tsVal != null ? !tsVal.equals(that.tsVal) : that.tsVal !=
null) return false;
if (urlVal != null ? !urlVal.equals(that.urlVal) : that.urlVal !=
null) return false;
+ if (!Arrays.equals(blobVal, that.blobVal)) return false;
+ if (clobVal != null ? !clobVal.equals(that.clobVal) : that.clobVal
!= null) return false;
return true;
}
@@ -1082,6 +1129,8 @@ public class JdbcResultSetSelfTest extends
GridCommonAbstractTest {
res = 31 * res + (f1 != null ? f1.hashCode() : 0);
res = 31 * res + (f2 != null ? f2.hashCode() : 0);
res = 31 * res + (f3 != null ? f3.hashCode() : 0);
+ res = 31 * res + (blobVal != null ? Arrays.hashCode(blobVal) : 0);
+ res = 31 * res + (clobVal != null ? clobVal.hashCode() : 0);
return res;
}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index 450db60030d..f5b133e5fad 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -21,6 +21,7 @@ import java.security.Security;
import org.apache.ignite.common.RunningQueryInfoCheckInitiatorTest;
import org.apache.ignite.internal.jdbc2.JdbcBlobTest;
import org.apache.ignite.internal.jdbc2.JdbcBulkLoadSelfTest;
+import org.apache.ignite.internal.jdbc2.JdbcClobTest;
import org.apache.ignite.internal.jdbc2.JdbcConnectionReopenTest;
import org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest;
import org.apache.ignite.internal.jdbc2.JdbcSchemaCaseSelfTest;
@@ -125,6 +126,7 @@ import org.junit.runners.Suite;
JdbcBulkLoadSelfTest.class,
JdbcSchemaCaseSelfTest.class,
+ JdbcClobTest.class,
JdbcBlobTest.class,
org.apache.ignite.internal.jdbc2.JdbcStreamingSelfTest.class,
JdbcThinStreamingNotOrderedSelfTest.class,
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
index 522fddd7aa1..a69b7a70d4a 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
@@ -18,9 +18,12 @@
package org.apache.ignite.jdbc.thin;
import java.io.Serializable;
+import java.sql.Blob;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
+import java.util.Arrays;
import java.util.Collections;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
@@ -30,6 +33,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.util.typedef.F;
+import static java.nio.charset.StandardCharsets.UTF_16;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
@@ -38,7 +42,7 @@ import static
org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
*/
public abstract class JdbcThinAbstractDmlStatementSelfTest extends
JdbcThinAbstractSelfTest {
/** SQL SELECT query for verification. */
- static final String SQL_SELECT = "select _key, id, firstName, lastName,
age from Person";
+ static final String SQL_SELECT = "select _key, id, firstName, lastName,
age, data, text from Person";
/** Connection. */
protected Connection conn;
@@ -117,6 +121,8 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest
extends JdbcThinAbstr
e.addQueryField("age", Integer.class.getName(), null);
e.addQueryField("firstName", String.class.getName(), null);
e.addQueryField("lastName", String.class.getName(), null);
+ e.addQueryField("data", byte[].class.getName(), null);
+ e.addQueryField("text", String.class.getName(), null);
ccfg.setQueryEntities(Collections.singletonList(e));
@@ -158,6 +164,8 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest
extends JdbcThinAbstr
e.addQueryField("age", Integer.class.getName(), null);
e.addQueryField("firstName", String.class.getName(), null);
e.addQueryField("lastName", String.class.getName(), null);
+ e.addQueryField("data", byte[].class.getName(), null);
+ e.addQueryField("text", String.class.getName(), null);
cache.setQueryEntities(Collections.singletonList(e));
@@ -171,6 +179,49 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest
extends JdbcThinAbstr
return nonBinCacheConfig();
}
+ /**
+ * Helper to get test binary data as string UTF-16 encoding to be in sync
with the RAWTOHEX function
+ * which uses UTF-16 for conversion strings to byte arrays.
+ * @param str String.
+ * @return Byte array with the UTF-16 encoding.
+ */
+ static byte[] getBytes(String str) {
+ return str.getBytes(UTF_16);
+ }
+
+ /**
+ * Helper to convert a binary data (which is a string UTF-16 encoding)
back to string.
+ * @param arr Byte array with the UTF-16 encoding.
+ * @return String.
+ */
+ static String str(byte[] arr) {
+ return new String(arr, UTF_16);
+ }
+
+ /**
+ * @param blob Blob.
+ */
+ static byte[] getBytes(Blob blob) {
+ try {
+ return blob.getBytes(1, (int)blob.length());
+ }
+ catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param clob Clob.
+ */
+ static String str(Clob clob) {
+ try {
+ return clob.getSubString(1, (int)clob.length());
+ }
+ catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Person.
*/
@@ -191,6 +242,14 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest
extends JdbcThinAbstr
@QuerySqlField
private final int age;
+ /** Binary data (BLOB). */
+ @QuerySqlField
+ private final byte[] data;
+
+ /** CLOB. */
+ @QuerySqlField
+ private final String text;
+
/**
* @param id ID.
* @param firstName First name.
@@ -206,6 +265,8 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest
extends JdbcThinAbstr
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
+ this.data = getBytes(lastName);
+ this.text = firstName + " " + lastName;
}
/** {@inheritDoc} */
@@ -218,16 +279,23 @@ public abstract class
JdbcThinAbstractDmlStatementSelfTest extends JdbcThinAbstr
if (id != person.id) return false;
if (age != person.age) return false;
if (firstName != null ? !firstName.equals(person.firstName) :
person.firstName != null) return false;
- return lastName != null ? lastName.equals(person.lastName) :
person.lastName == null;
+ if (lastName != null ? !lastName.equals(person.lastName) :
person.lastName != null) return false;
+ if (data != null ? !Arrays.equals(data, person.data) : person.data
!= null) return false;
+ if (text != null ? !text.equals(person.text) : person.text !=
null) return false;
+ return true;
}
/** {@inheritDoc} */
@Override public int hashCode() {
int result = id;
+
result = 31 * result + (firstName != null ? firstName.hashCode() :
0);
result = 31 * result + (lastName != null ? lastName.hashCode() :
0);
result = 31 * result + age;
+ result = 31 * result + (data != null ? Arrays.hashCode(data) : 0);
+ result = 31 * result + (text != null ? text.hashCode() : 0);
+
return result;
}
}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
index f71d18a1fa1..76e42d016c9 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
@@ -24,10 +24,10 @@ import java.sql.Statement;
*/
public abstract class JdbcThinAbstractUpdateStatementSelfTest extends
JdbcThinAbstractDmlStatementSelfTest {
/** SQL query to populate cache. */
- private static final String ITEMS_SQL = "insert into Person(_key, id,
firstName, lastName, age) values " +
- "('p1', 1, 'John', 'White', 25), " +
- "('p2', 2, 'Joe', 'Black', 35), " +
- "('p3', 3, 'Mike', 'Green', 40)";
+ private static final String ITEMS_SQL = "insert into Person(_key, id,
firstName, lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index 6f97da4c8c9..c8abd5ea63d 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -1742,16 +1742,8 @@ public class JdbcThinConnectionSelfTest extends
JdbcThinAbstractSelfTest {
@Test
public void testCreateClob() throws Exception {
try (Connection conn =
DriverManager.getConnection(urlWithPartitionAwarenessProp)) {
- // Unsupported
- assertThrows(log,
- new Callable<Object>() {
- @Override public Object call() throws Exception {
- return conn.createClob();
- }
- },
- SQLFeatureNotSupportedException.class,
- "SQL-specific types are not supported"
- );
+
+ assertNotNull(conn.createClob());
conn.close();
@@ -1773,16 +1765,8 @@ public class JdbcThinConnectionSelfTest extends
JdbcThinAbstractSelfTest {
@Test
public void testCreateBlob() throws Exception {
try (Connection conn =
DriverManager.getConnection(urlWithPartitionAwarenessProp)) {
- // Unsupported
- assertThrows(log,
- new Callable<Object>() {
- @Override public Object call() throws Exception {
- return conn.createBlob();
- }
- },
- SQLFeatureNotSupportedException.class,
- "SQL-specific types are not supported"
- );
+
+ assertNotNull(conn.createBlob());
conn.close();
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
index c9f46abc2b3..9a787a6269a 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
@@ -17,6 +17,8 @@
package org.apache.ignite.jdbc.thin;
+import java.sql.Blob;
+import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -35,23 +37,23 @@ import org.junit.Test;
*/
public class JdbcThinInsertStatementSelfTest extends
JdbcThinAbstractDmlStatementSelfTest {
/** SQL query. */
- private static final String SQL = "insert into Person(_key, id, firstName,
lastName, age) values " +
- "('p1', 1, 'John', 'White', 25), " +
- "('p2', 2, 'Joe', 'Black', 35), " +
- "('p3', 3, 'Mike', 'Green', 40)";
+ private static final String SQL = "insert into Person(_key, id, firstName,
lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** SQL query. */
- private static final String SQL_PREPARED = "insert into Person(_key, id,
firstName, lastName, age) values " +
- "(?, ?, ?, ?, ?), (?, ?, ?, ?, ?), (?, ?, ?, ?, ?)";
+ private static final String SQL_PREPARED = "insert into Person(_key, id,
firstName, lastName, age, data, text) " +
+ "values (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?,
?, ?)";
/** Test logger. */
private static ListeningTestLogger srvLog;
/** Arguments for prepared statement. */
private final Object[][] args = new Object[][] {
- {"p1", 1, "John", "White", 25},
- {"p3", 3, "Mike", "Green", 40},
- {"p2", 2, "Joe", "Black", 35}
+ {"p1", 1, "John", "White", 25, getBytes("White"), "John White"},
+ {"p3", 3, "Mike", "Green", 40, getBytes("Green"), "Mike Green"},
+ {"p2", 2, "Joe", "Black", 35, getBytes("Black"), "Joe Black"}
};
/** Statement. */
@@ -95,6 +97,14 @@ public class JdbcThinInsertStatementSelfTest extends
JdbcThinAbstractDmlStatemen
prepStmt.setString(paramCnt++, (String)arg[2]);
prepStmt.setString(paramCnt++, (String)arg[3]);
prepStmt.setInt(paramCnt++, (Integer)arg[4]);
+
+ Blob blob = conn.createBlob();
+ blob.setBytes(1, (byte[])arg[5]);
+ prepStmt.setBlob(paramCnt++, blob);
+
+ Clob clob = conn.createClob();
+ clob.setString(1, (String)arg[6]);
+ prepStmt.setClob(paramCnt++, clob);
}
}
@@ -116,6 +126,8 @@ public class JdbcThinInsertStatementSelfTest extends
JdbcThinAbstractDmlStatemen
assertEquals("John", rs.getString("firstName"));
assertEquals("White", rs.getString("lastName"));
assertEquals(25, rs.getInt("age"));
+ assertEquals("White",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("John White", str(rs.getClob("text")));
break;
case 2:
@@ -123,6 +135,8 @@ public class JdbcThinInsertStatementSelfTest extends
JdbcThinAbstractDmlStatemen
assertEquals("Joe", rs.getString("firstName"));
assertEquals("Black", rs.getString("lastName"));
assertEquals(35, rs.getInt("age"));
+ assertEquals("Black",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Joe Black", str(rs.getClob("text")));
break;
case 3:
@@ -130,13 +144,8 @@ public class JdbcThinInsertStatementSelfTest extends
JdbcThinAbstractDmlStatemen
assertEquals("Mike", rs.getString("firstName"));
assertEquals("Green", rs.getString("lastName"));
assertEquals(40, rs.getInt("age"));
- break;
-
- case 4:
- assertEquals("p4", rs.getString("_key"));
- assertEquals("Leah", rs.getString("firstName"));
- assertEquals("Grey", rs.getString("lastName"));
- assertEquals(22, rs.getInt("age"));
+ assertEquals("Green",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Mike Green", str(rs.getClob("text")));
break;
default:
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
index 065f81417b7..8bdf7c6163b 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
@@ -28,14 +28,14 @@ import org.junit.Test;
*/
public class JdbcThinMergeStatementSelfTest extends
JdbcThinAbstractDmlStatementSelfTest {
/** SQL query. */
- private static final String SQL = "merge into Person(_key, id, firstName,
lastName, age) values " +
- "('p1', 1, 'John', 'White', 25), " +
- "('p2', 2, 'Joe', 'Black', 35), " +
- "('p3', 3, 'Mike', 'Green', 40)";
+ private static final String SQL = "merge into Person(_key, id, firstName,
lastName, age, data, text) values " +
+ "('p1', 1, 'John', 'White', 25, RAWTOHEX('White'), 'John White'), " +
+ "('p2', 2, 'Joe', 'Black', 35, RAWTOHEX('Black'), 'Joe Black'), " +
+ "('p3', 3, 'Mike', 'Green', 40, RAWTOHEX('Green'), 'Mike Green')";
/** SQL query. */
- protected static final String SQL_PREPARED = "merge into Person(_key, id,
firstName, lastName, age) values " +
- "(?, ?, ?, ?, ?), (?, ?, ?, ?, ?)";
+ protected static final String SQL_PREPARED = "merge into Person(_key, id,
firstName, lastName, age, data, text) values " +
+ "(?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?)";
/** Statement. */
protected Statement stmt;
@@ -74,6 +74,8 @@ public class JdbcThinMergeStatementSelfTest extends
JdbcThinAbstractDmlStatement
assertEquals("John", rs.getString("firstName"));
assertEquals("White", rs.getString("lastName"));
assertEquals(25, rs.getInt("age"));
+ assertEquals("White",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("John White", str(rs.getClob("text")));
break;
case 2:
@@ -81,6 +83,8 @@ public class JdbcThinMergeStatementSelfTest extends
JdbcThinAbstractDmlStatement
assertEquals("Joe", rs.getString("firstName"));
assertEquals("Black", rs.getString("lastName"));
assertEquals(35, rs.getInt("age"));
+ assertEquals("Black",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Joe Black", str(rs.getClob("text")));
break;
case 3:
@@ -88,13 +92,8 @@ public class JdbcThinMergeStatementSelfTest extends
JdbcThinAbstractDmlStatement
assertEquals("Mike", rs.getString("firstName"));
assertEquals("Green", rs.getString("lastName"));
assertEquals(40, rs.getInt("age"));
- break;
-
- case 4:
- assertEquals("p4", rs.getString("_key"));
- assertEquals("Leah", rs.getString("firstName"));
- assertEquals("Grey", rs.getString("lastName"));
- assertEquals(22, rs.getInt("age"));
+ assertEquals("Green",
str(getBytes(rs.getBlob("data"))));
+ assertEquals("Mike Green", str(rs.getClob("text")));
break;
default:
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
index 2becc186082..7982980491d 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
@@ -52,7 +52,9 @@ import org.junit.Test;
import static java.sql.Types.BIGINT;
import static java.sql.Types.BINARY;
+import static java.sql.Types.BLOB;
import static java.sql.Types.BOOLEAN;
+import static java.sql.Types.CLOB;
import static java.sql.Types.DATE;
import static java.sql.Types.DOUBLE;
import static java.sql.Types.FLOAT;
@@ -79,7 +81,7 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
/** SQL query. */
private static final String SQL_PART =
"select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
- "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal,
objVal " +
+ "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal,
objVal, blobVal, clobVal " +
"from TestObject ";
/** Connection. */
@@ -128,6 +130,8 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
o.bigVal = new BigDecimal(1);
o.strVal = "str";
o.arrVal = new byte[] {1};
+ o.blobVal = new byte[] {1};
+ o.clobVal = "large str";
o.dateVal = new Date(1);
o.timeVal = new Time(1);
o.tsVal = new Timestamp(1);
@@ -854,6 +858,62 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
assert cnt == 1;
}
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testBlob() throws Exception {
+ stmt = conn.prepareStatement(SQL_PART + " where blobVal is not
distinct from ?");
+
+ Blob blob = conn.createBlob();
+
+ blob.setBytes(1, new byte[] {1});
+
+ stmt.setBlob(1, blob);
+
+ ResultSet rs = stmt.executeQuery();
+
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt("id"));
+ assertFalse(rs.next());
+
+ stmt.setNull(1, BLOB);
+
+ rs = stmt.executeQuery();
+
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt("id"));
+ assertFalse(rs.next());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testClob() throws Exception {
+ stmt = conn.prepareStatement(SQL_PART + " where clobVal is not
distinct from ?");
+
+ Clob clob = conn.createClob();
+
+ clob.setString(1, "large str");
+
+ stmt.setClob(1, clob);
+
+ ResultSet rs = stmt.executeQuery();
+
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt("id"));
+ assertFalse(rs.next());
+
+ stmt.setNull(1, CLOB);
+
+ rs = stmt.executeQuery();
+
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt("id"));
+ assertFalse(rs.next());
+ }
+
/**
* @throws Exception If failed.
*/
@@ -1047,12 +1107,6 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
}
});
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- stmt.setBlob(1, (Blob)null);
- }
- });
-
checkNotSupported(new RunnableX() {
@Override public void runx() throws Exception {
stmt.setBlob(1, (InputStream)null);
@@ -1083,12 +1137,6 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
}
});
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- stmt.setClob(1, (Clob)null);
- }
- });
-
checkNotSupported(new RunnableX() {
@Override public void runx() throws Exception {
stmt.setClob(1, (Reader)null);
@@ -1204,6 +1252,14 @@ public class JdbcThinPreparedStatementSelfTest extends
JdbcThinAbstractSelfTest
@QuerySqlField
private byte[] arrVal;
+ /** */
+ @QuerySqlField
+ private byte[] blobVal;
+
+ /** */
+ @QuerySqlField
+ private String clobVal;
+
/** */
@QuerySqlField
private Date dateVal;
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
index 50f1c1079d1..60210c335db 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
@@ -62,7 +62,7 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
/** SQL query. */
private static final String SQL =
"select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
- "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal,
objVal " +
+ "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal,
objVal, blobVal, clobVal " +
"from TestObject where id = 1";
/** Statement. */
@@ -144,6 +144,8 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
o.bigVal = new BigDecimal(1);
o.strVal = "1";
o.arrVal = new byte[] {1};
+ o.blobVal = new byte[] {1};
+ o.clobVal = "str";
o.dateVal = new Date(1, 1, 1);
o.timeVal = new Time(1, 1, 1);
o.tsVal = new Timestamp(1);
@@ -599,6 +601,42 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
assert cnt == 1;
}
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testBlob() throws Exception {
+ ResultSet rs = stmt.executeQuery(SQL);
+
+ assertTrue(rs.next());
+
+ Blob blob = rs.getBlob("blobVal");
+ Assert.assertArrayEquals(blob.getBytes(1, (int)blob.length()), new
byte[] {1});
+
+ blob = rs.getBlob(16);
+ Assert.assertArrayEquals(blob.getBytes(1, (int)blob.length()), new
byte[] {1});
+
+ assertFalse(rs.next());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testClob() throws Exception {
+ ResultSet rs = stmt.executeQuery(SQL);
+
+ assertTrue(rs.next());
+
+ Clob clob = rs.getClob("clobVal");
+ Assert.assertEquals("str", clob.getSubString(1, (int)clob.length()));
+
+ clob = rs.getClob(17);
+ Assert.assertEquals("str", clob.getSubString(1, (int)clob.length()));
+
+ assertFalse(rs.next());
+ }
+
/**
* @throws Exception If failed.
*/
@@ -828,30 +866,6 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
}
});
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- rs.getBlob(1);
- }
- });
-
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- rs.getBlob("id");
- }
- });
-
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- rs.getClob(1);
- }
- });
-
- checkNotSupported(new RunnableX() {
- @Override public void runx() throws Exception {
- rs.getClob("id");
- }
- });
-
checkNotSupported(new RunnableX() {
@Override public void runx() throws Exception {
rs.getCharacterStream(1);
@@ -1740,6 +1754,14 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
@QuerySqlField
private byte[] arrVal;
+ /** */
+ @QuerySqlField
+ private byte[] blobVal;
+
+ /** */
+ @QuerySqlField
+ private String clobVal;
+
/** */
@QuerySqlField
private Date dateVal;
@@ -1806,6 +1828,8 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
if (timeVal != null ? !timeVal.equals(that.timeVal) : that.timeVal
!= null) return false;
if (tsVal != null ? !tsVal.equals(that.tsVal) : that.tsVal !=
null) return false;
if (urlVal != null ? !urlVal.equals(that.urlVal) : that.urlVal !=
null) return false;
+ if (!Arrays.equals(blobVal, that.blobVal)) return false;
+ if (clobVal != null ? !clobVal.equals(that.clobVal) : that.clobVal
!= null) return false;
return true;
}
@@ -1832,6 +1856,8 @@ public class JdbcThinResultSetSelfTest extends
JdbcThinAbstractSelfTest {
res = 31 * res + (objVal != null ? objVal.hashCode() : 0);
res = 31 * res + (f2 != null ? f2.hashCode() : 0);
res = 31 * res + (f3 != null ? f3.hashCode() : 0);
+ res = 31 * res + (blobVal != null ? Arrays.hashCode(blobVal) : 0);
+ res = 31 * res + (clobVal != null ? clobVal.hashCode() : 0);
return res;
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 6a4668a0001..c5a905ac064 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -82,6 +82,8 @@ import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.binary.BinaryMetadata;
import org.apache.ignite.internal.binary.BinaryMetadataHandler;
import org.apache.ignite.internal.binary.BinaryTypeImpl;
+import org.apache.ignite.internal.jdbc2.JdbcBlob;
+import org.apache.ignite.internal.jdbc2.JdbcClob;
import org.apache.ignite.internal.jdbc2.JdbcUtils;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheUtils;
@@ -754,14 +756,14 @@ public class JdbcThinConnection implements Connection {
@Override public Clob createClob() throws SQLException {
ensureNotClosed();
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob("");
}
/** {@inheritDoc} */
@Override public Blob createBlob() throws SQLException {
ensureNotClosed();
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcBlob(new byte[0]);
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
index 6c795ddc4bb..d64aaab423e 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
@@ -305,16 +305,12 @@ public class JdbcThinPreparedStatement extends
JdbcThinStatement implements Prep
/** {@inheritDoc} */
@Override public void setBlob(int paramIdx, Blob x) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ setBytes(paramIdx, x.getBytes(1, (int)x.length()));
}
/** {@inheritDoc} */
@Override public void setClob(int paramIdx, Clob x) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ setString(paramIdx, x.getSubString(1, (int)x.length()));
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
index b75734992e4..1ba7affc761 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
@@ -46,6 +46,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.apache.ignite.internal.jdbc2.JdbcBlob;
+import org.apache.ignite.internal.jdbc2.JdbcClob;
import org.apache.ignite.internal.processors.odbc.SqlStateCode;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest;
@@ -1296,16 +1298,12 @@ public class JdbcThinResultSet implements ResultSet {
/** {@inheritDoc} */
@Override public Blob getBlob(int colIdx) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcBlob(getBytes(colIdx));
}
/** {@inheritDoc} */
@Override public Clob getClob(int colIdx) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob(getString(colIdx));
}
/** {@inheritDoc} */
@@ -1329,16 +1327,12 @@ public class JdbcThinResultSet implements ResultSet {
/** {@inheritDoc} */
@Override public Blob getBlob(String colLb) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcBlob(getBytes(colLb));
}
/** {@inheritDoc} */
@Override public Clob getClob(String colLb) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob(getString(colLb));
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcBlob.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcBlob.java
index 17e9b13d00c..ef2b6b5bd3a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcBlob.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcBlob.java
@@ -54,7 +54,7 @@ public class JdbcBlob implements Blob {
@Override public byte[] getBytes(long pos, int len) throws SQLException {
ensureNotClosed();
- if (pos < 1 || arr.length - pos < 0 || len < 0)
+ if (pos < 1 || (arr.length - pos < 0 && arr.length > 0) || len < 0)
throw new SQLException("Invalid argument. Position can't be less
than 1 or " +
"greater than size of underlying byte array. Requested length
also can't be negative " + "" +
"[pos=" + pos + ", len=" + len + ']');
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcClob.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcClob.java
new file mode 100644
index 00000000000..ecef1abd6ab
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcClob.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.jdbc2;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.sql.Clob;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * CLOB implementation for Ignite JDBC driver.
+ */
+public class JdbcClob implements Clob {
+ /** CLOB's character sequence. */
+ private String chars;
+
+ /**
+ * @param chars CLOB's character sequence.
+ */
+ public JdbcClob(String chars) {
+ this.chars = chars;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long length() throws SQLException {
+ ensureNotClosed();
+
+ return chars.length();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getSubString(long pos, int len) throws
SQLException {
+ ensureNotClosed();
+
+ long zeroBasedPos = pos - 1;
+
+ if (zeroBasedPos < 0 || len < 0 || zeroBasedPos + len > chars.length())
+ throw new SQLException("Invalid argument. Position should be
greater than 0. Length should not be " +
+ "negative. Position + length should be less than CLOB size
[pos=" + pos + ", length=" + len + ']');
+
+ return getSubStringInternal((int)zeroBasedPos, len);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Reader getCharacterStream() throws SQLException {
+ ensureNotClosed();
+
+ return new StringReader(chars);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Reader getCharacterStream(long pos, long len) throws
SQLException {
+ return new StringReader(getSubString(pos, (int)len));
+ }
+
+ /** {@inheritDoc} */
+ @Override public InputStream getAsciiStream() throws SQLException {
+ ensureNotClosed();
+
+ // Encode to UTF-8 since Ignite internally stores strings in UTF-8 by
default.
+ return new Utf8EncodedStringInputStream(chars);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long position(String searchStr, long start) throws
SQLException {
+ ensureNotClosed();
+
+ if (start < 1)
+ throw new SQLException("Invalid argument. Start position should be
greater than zero [start=" +
+ start + ']');
+
+ long zeroBasedIdx = positionInternal(searchStr, start - 1);
+
+ return zeroBasedIdx == -1 ? -1 : zeroBasedIdx + 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long position(Clob searchStr, long start) throws
SQLException {
+ return position(searchStr.getSubString(1, (int)searchStr.length()),
start);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int setString(long pos, String str) throws SQLException {
+ ensureNotClosed();
+
+ long zeroBasedPos = pos - 1;
+
+ if (zeroBasedPos < 0 || str == null || zeroBasedPos > chars.length())
+ throw new SQLException("Invalid argument. Position should be
greater than zero. " +
+ "Position should not exceed CLOB length+1. Source string
should not be null " +
+ "[pos=" + pos + ", str=" + str + ']');
+
+ return setStringInternal((int)zeroBasedPos, str);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int setString(long pos, String str, int off, int len)
throws SQLException {
+ ensureNotClosed();
+
+ long zeroBasedPos = pos - 1;
+
+ if (zeroBasedPos < 0 || str == null || zeroBasedPos > chars.length()
|| off < 0 || len < 0 || off + len > str.length())
+ throw new SQLException("Invalid argument. Position should be
greater than zero. " +
+ "Position should not exceed CLOB length+1. Source string
should not be null. " +
+ "Offset and length shouldn't be negative. Offset + length
should not exceed source string length " +
+ "[pos=" + pos + ", str=" + str + ", offset=" + off + ", len="
+ len + ']');
+
+ return setStringInternal((int)zeroBasedPos, str, off, len);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(long len) throws SQLException {
+ ensureNotClosed();
+
+ if (len < 0 || len > chars.length())
+ throw new SQLException("Invalid argument. Truncation length should
not be negative. Truncation length " +
+ "should not exceed data length [len=" + len + ']');
+
+ chars = chars.substring(0, (int)len);
+ }
+
+ /** {@inheritDoc} */
+ @Override public OutputStream setAsciiStream(long pos) throws SQLException
{
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Writer setCharacterStream(long pos) throws SQLException {
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void free() throws SQLException {
+ chars = null;
+ }
+
+ /**
+ * Ensures CLOB hasn't been closed.
+ */
+ private void ensureNotClosed() throws SQLException {
+ if (chars == null)
+ throw new SQLException("Clob instance can't be used after free()
has been called.");
+ }
+
+ /**
+ * Internal getSubString implementation with zero-based position parameter.
+ */
+ private String getSubStringInternal(int zeroBasedPos, int len) {
+ return chars.substring(zeroBasedPos, zeroBasedPos + len);
+ }
+
+ /**
+ * Internal position implementation with zero-based start parameter.
+ */
+ private long positionInternal(String searchStr, long zeroBasedStart) {
+ return chars.indexOf(searchStr, (int)zeroBasedStart);
+ }
+
+ /**
+ * Internal setString implementation with zero-based position parameter.
+ */
+ private int setStringInternal(int zeroBasedPos, String str) {
+ StringBuilder strBuilder = new StringBuilder(chars);
+
+ // Ensure string buffer capacity
+ if (zeroBasedPos + str.length() > chars.length())
+ strBuilder.setLength(zeroBasedPos + str.length());
+
+ strBuilder.replace(zeroBasedPos, zeroBasedPos + str.length(), str);
+
+ chars = strBuilder.toString();
+
+ return str.length();
+ }
+
+ /**
+ * Internal setString implementation with zero-based position parameter.
+ */
+ private int setStringInternal(int zeroBasedPos, String str, int off, int
len) {
+ StringBuilder strBuilder = new StringBuilder(chars);
+
+ // Ensure string buffer capacity
+ if (zeroBasedPos + str.length() > chars.length())
+ strBuilder.setLength(zeroBasedPos + str.length());
+
+ String replaceStr = str.substring(off, off + len);
+ strBuilder.replace(zeroBasedPos, zeroBasedPos + replaceStr.length(),
replaceStr);
+
+ chars = strBuilder.toString();
+
+ return replaceStr.length();
+ }
+
+ /**
+ * Input stream which encodes the given string to UTF-8.
+ * To save memory for large strings it does it by chunks.
+ */
+ private static class Utf8EncodedStringInputStream extends InputStream {
+ /** String to encode. */
+ private final String chars;
+
+ /** String length. */
+ private final int length;
+
+ /** Start index of the next chunk (substring) to be encoded. */
+ private int charsPos;
+
+ /** Default chunk size. */
+ private static final int DEFAULT_CHUNK_SIZE = 8192;
+
+ /** Buffer containing the current chunk encoding. */
+ private byte[] buf;
+
+ /** Current position in the buffer - index of the next byte to be read
from the input stream. */
+ private int bufPos;
+
+ /**
+ * @param chars String to be encoded.
+ */
+ Utf8EncodedStringInputStream(String chars) {
+ this.chars = chars;
+
+ length = chars.length();
+ charsPos = 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized int read() {
+ if (buf == null || buf.length == 0 || bufPos >= buf.length) {
+ if (charsPos >= length)
+ return -1;
+
+ bufPos = 0;
+
+ encodeNextChunk();
+ }
+
+ return buf[bufPos++] & 0xFF;
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized int read(byte[] b, int off, int len) {
+ if (b == null)
+ throw new NullPointerException();
+
+ if (off < 0 || len < 0 || len > b.length - off)
+ throw new IndexOutOfBoundsException(String.format("Range [%s,
%<s + %s) out of bounds for length %s", off, len, b.length));
+
+ if (len == 0)
+ return 0;
+
+ int i = 0;
+
+ while (i < len) {
+ if (buf == null || buf.length == 0 || bufPos >= buf.length) {
+ if (charsPos >= length)
+ return i > 0 ? i : -1;
+
+ bufPos = 0;
+
+ encodeNextChunk();
+ }
+
+ int encodedChunkSize = Math.min(len - i, buf.length - bufPos);
+
+ U.arrayCopy(buf, bufPos, b, off + i, encodedChunkSize);
+
+ bufPos += encodedChunkSize;
+ i += encodedChunkSize;
+ }
+
+ return i;
+ }
+
+ /**
+ * Encodes the next chunk of the string.
+ * <p>
+ * Makes sure that chunk doesn't contain the malformed surrogate
element at the end
+ * (high surrogate that is not followed by a low surrogate).
+ */
+ private void encodeNextChunk() {
+ int remainingSize = chars.length() - charsPos;
+
+ assert remainingSize > 0;
+
+ int chunkSize;
+
+ if (remainingSize <= DEFAULT_CHUNK_SIZE) {
+ chunkSize = remainingSize;
+ }
+ else if (Character.isHighSurrogate(chars.charAt(charsPos +
DEFAULT_CHUNK_SIZE - 1))) {
+ chunkSize = DEFAULT_CHUNK_SIZE + 1;
+ }
+ else {
+ chunkSize = DEFAULT_CHUNK_SIZE;
+ }
+
+ String subs = chars.substring(charsPos, charsPos + chunkSize);
+ buf = subs.getBytes(UTF_8);
+
+ charsPos += chunkSize;
+ }
+ }
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
index e785e4164d7..31ccf655351 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
@@ -702,7 +702,7 @@ public class JdbcConnection implements Connection {
@Override public Clob createClob() throws SQLException {
ensureNotClosed();
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob("");
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatement.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatement.java
index 858a1b63f8b..dbb0c031344 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatement.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatement.java
@@ -267,9 +267,7 @@ public class JdbcPreparedStatement extends JdbcStatement
implements PreparedStat
/** {@inheritDoc} */
@Override public void setClob(int paramIdx, Clob x) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ setString(paramIdx, x.getSubString(1, (int)x.length()));
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
index eab488c31c3..53746e50c33 100755
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -1299,9 +1299,7 @@ public class JdbcResultSet implements ResultSet {
/** {@inheritDoc} */
@Override public Clob getClob(int colIdx) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob(getString(colIdx));
}
/** {@inheritDoc} */
@@ -1330,9 +1328,7 @@ public class JdbcResultSet implements ResultSet {
/** {@inheritDoc} */
@Override public Clob getClob(String colLb) throws SQLException {
- ensureNotClosed();
-
- throw new SQLFeatureNotSupportedException("SQL-specific types are not
supported.");
+ return new JdbcClob(getString(colLb));
}
/** {@inheritDoc} */
diff --git
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 8e91c71a711..65600be66a7 100644
---
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -122,6 +122,7 @@ import
org.apache.ignite.internal.util.lang.IgniteSingletonIterator;
import org.apache.ignite.internal.util.lang.IgniteThrowableSupplier;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiClosure;
import org.apache.ignite.lang.IgniteBiTuple;
@@ -1090,14 +1091,14 @@ public class IgniteH2Indexing implements
GridQueryIndexing {
if (roEx != null) {
throw new IgniteSQLException(
"Failed to execute DML statement. Cluster in read-only
mode [stmt=" + qryDesc.sql() +
- ", params=" + Arrays.deepToString(qryParams.arguments()) +
"]",
+ ", params=" + S.toString(QueryParameters.class, qryParams)
+ "]",
IgniteQueryErrorCode.CLUSTER_READ_ONLY_MODE_ENABLED,
e
);
}
throw new IgniteSQLException("Failed to execute DML statement
[stmt=" + qryDesc.sql() +
- ", params=" + Arrays.deepToString(qryParams.arguments()) +
"]", e);
+ ", params=" + S.toString(QueryParameters.class, qryParams)
+ "]", e);
}
finally {
runningQueryManager().unregister(qryId, failReason);
diff --git
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/QueryParameters.java
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/QueryParameters.java
index e59e512826e..69d46618de1 100644
---
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/QueryParameters.java
+++
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/QueryParameters.java
@@ -20,16 +20,21 @@ package org.apache.ignite.internal.processors.query.h2;
import java.util.List;
import org.apache.ignite.internal.processors.query.NestedTxMode;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
/**
* Query parameters which vary between requests having the same execution
plan. Essentially, these are the arguments
* of original {@link org.apache.ignite.cache.query.SqlFieldsQuery} which are
not part of {@link QueryDescriptor}.
*/
+@GridToStringInclude(sensitive = true)
public class QueryParameters {
/** Arguments. */
+ @GridToStringInclude(sensitive = true)
private final Object[] args;
/** Partitions. */
+ @GridToStringInclude(sensitive = true)
private final int[] parts;
/** Timeout. */
@@ -51,6 +56,7 @@ public class QueryParameters {
private final boolean autoCommit;
/** Batched arguments. */
+ @GridToStringInclude(sensitive = true)
private final List<Object[]> batchedArgs;
/**
@@ -194,4 +200,9 @@ public class QueryParameters {
this.updateBatchSize
);
}
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryParameters.class, this);
+ }
}