diff --git a/docs/_docs/SQL/JDBC/jdbc-driver.adoc b/docs/_docs/SQL/JDBC/jdbc-driver.adoc index ffd36a8ddde3a..9959f7109b4ff 100644 --- a/docs/_docs/SQL/JDBC/jdbc-driver.adoc +++ b/docs/_docs/SQL/JDBC/jdbc-driver.adoc @@ -231,6 +231,24 @@ while (rs.next()) { } ---- +=== BLOB and CLOB Values + +The JDBC Thin driver supports standard `java.sql.Blob` and `java.sql.Clob` objects for binary and character values. +Store BLOB data in SQL `BINARY` columns and CLOB data in SQL `VARCHAR` columns. + +You can create values with `Connection.createBlob()` and `Connection.createClob()`, bind them with `PreparedStatement.setBlob()` and `PreparedStatement.setClob()`, and read them with `ResultSet.getBlob()` and `ResultSet.getClob()`. + +[source,java] +---- +include::{javaFile}[tags=blob-clob, indent=0] +---- + +BLOB values also support binary stream APIs, including `PreparedStatement.setBlob(int, InputStream)`, `PreparedStatement.setBlob(int, InputStream, long)`, `PreparedStatement.setBinaryStream()`, `ResultSet.getBinaryStream()`, and `Blob.getBinaryStream()`. +When a stream length is provided, it must be non-negative and must match the actual number of bytes read from the stream. + +CLOB values are supported through `Clob` object methods such as `setString()`, `getSubString()`, and `getCharacterStream()`. +Reader-based CLOB setter APIs, such as `PreparedStatement.setClob(int, Reader)`, and direct `ResultSet.getCharacterStream()` calls are not supported. + === Partition Awareness [[partition-awareness]] Partition awareness is a feature that makes the JDBC driver "aware" of the partition distribution in the cluster. diff --git a/docs/_docs/code-snippets/java/src/main/java/org/apache/ignite/snippets/JDBCThinDriver.java b/docs/_docs/code-snippets/java/src/main/java/org/apache/ignite/snippets/JDBCThinDriver.java index 6ab942b7f2bb6..bdb03a8b12a92 100644 --- a/docs/_docs/code-snippets/java/src/main/java/org/apache/ignite/snippets/JDBCThinDriver.java +++ b/docs/_docs/code-snippets/java/src/main/java/org/apache/ignite/snippets/JDBCThinDriver.java @@ -16,6 +16,11 @@ */ package org.apache.ignite.snippets; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.sql.Blob; +import java.sql.Clob; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -132,6 +137,60 @@ void partitionAwareness() throws ClassNotFoundException, SQLException { conn.close(); } + void blobAndClob() throws ClassNotFoundException, SQLException { + + Connection conn = getConnection(); + // tag::blob-clob[] + conn.createStatement().executeUpdate( + "CREATE TABLE IF NOT EXISTS DocumentStore (id INT PRIMARY KEY, payload BINARY, body VARCHAR)"); + + byte[] payload = "binary payload".getBytes(StandardCharsets.UTF_8); + + PreparedStatement insert = conn.prepareStatement( + "INSERT INTO DocumentStore(id, payload, body) VALUES (?, ?, ?)"); + + Blob blob = conn.createBlob(); + blob.setBytes(1, payload); + + Clob clob = conn.createClob(); + clob.setString(1, "large text body"); + + insert.setInt(1, 1); + insert.setBlob(2, blob); + insert.setClob(3, clob); + insert.executeUpdate(); + + PreparedStatement streamInsert = conn.prepareStatement( + "INSERT INTO DocumentStore(id, payload, body) VALUES (?, ?, ?)"); + + streamInsert.setInt(1, 2); + streamInsert.setBlob(2, new ByteArrayInputStream(payload), payload.length); + streamInsert.setString(3, "large text body"); + streamInsert.executeUpdate(); + + PreparedStatement select = conn.prepareStatement("SELECT payload, body FROM DocumentStore WHERE id = ?"); + + select.setInt(1, 1); + + ResultSet rs = select.executeQuery(); + + if (rs.next()) { + Blob selectedBlob = rs.getBlob("payload"); + byte[] selectedPayload = selectedBlob.getBytes(1, (int)selectedBlob.length()); + + Clob selectedClob = rs.getClob("body"); + String selectedBody = selectedClob.getSubString(1, (int)selectedClob.length()); + + InputStream selectedPayloadStream = rs.getBinaryStream("payload"); + + assert selectedPayload.length == payload.length; + assert selectedBody.equals("large text body"); + assert selectedPayloadStream != null; + } + // end::blob-clob[] + conn.close(); + } + void handleException() throws ClassNotFoundException, SQLException { Connection conn = getConnection();