Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve (C|B)LOB on SqlRow construction #2267

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;

public class DRawSqlService implements SpiRawSqlService {

Expand Down Expand Up @@ -48,7 +49,26 @@ public SqlRow sqlRow(ResultSet resultSet, String dbTrueValue, boolean binaryOpti
if (ret.containsKey(name)) {
name = combine(meta.getSchemaName(i), meta.getTableName(i), name);
}
ret.put(name, resultSet.getObject(i));

// convert (C/B)LOBs to java objects.
// A java.sql.Clob depends on an open connection, so storing this object in a map
// that is accessed later, when the connection is closed, will result in a "connection is closed" exception.
// From the java.sql.Clob documentation: "... which means that a Clob object contains a logical pointer to the SQL CLOB
// data rather than the data itself."
switch (meta.getColumnType(i)) {
case Types.CLOB:
case Types.NCLOB:
ret.put(name, resultSet.getString(i));
break;

case Types.BLOB:
ret.put(name, resultSet.getBytes(i));
break;

default:
ret.put(name, resultSet.getObject(i));
break;
}
}
return ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,25 @@
import io.ebean.SqlRow;
import io.ebean.annotation.ForPlatform;
import io.ebean.annotation.Platform;
import io.ebean.datasource.DataSourceConfig;
import io.ebeaninternal.server.core.DefaultServer;
import io.ebeaninternal.server.rawsql.SpiRawSql.Sql;
import org.junit.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.EBasicClob;
import org.tests.model.basic.PersistentFileContent;
import org.tests.model.basic.ResetBasicData;
import org.tests.model.rawsql.ERawSqlAggBean;

import javax.sql.DataSource;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -283,4 +291,58 @@ public void findDuplicateColumnName() throws SQLException {
}
}

@Test
public void testCLobClosedConnection() throws Exception {
final EBasicClob eBasicClob = new EBasicClob();
eBasicClob.setName("eBasicClob");
final String description = "This is the CLob description";
eBasicClob.setDescription(description);
DB.save(eBasicClob);

final String sql = "select description from ebasic_clob where id = ?";

List<SqlRow> rows = new ArrayList<>();
final DataSourceConfig config = ((DefaultServer) DB.getDefault()).getServerConfig().getDataSourceConfig();

try (Connection connection = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setLong(1, eBasicClob.getId());

try (ResultSet resultSet = stmt.executeQuery()) {
while (resultSet.next()) {
rows.add(RawSqlBuilder.sqlRow(resultSet, "true", false));
}
}
}

assertThat(rows).hasSize(1);
assertThat(rows.get(0).getString("description")).isEqualTo(description);
}

@Test
public void testBLobClosedConnection() throws Exception {
final PersistentFileContent pfc = new PersistentFileContent();
final byte[] bytes = "This is the blob as String".getBytes(StandardCharsets.UTF_8);
pfc.setContent(bytes);
DB.save(pfc);

List<SqlRow> rows = new ArrayList<>();
final DataSourceConfig config = ((DefaultServer) DB.getDefault()).getServerConfig().getDataSourceConfig();

final String sql = "select content from persistent_file_content where id = ?";
try (Connection connection = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setLong(1, pfc.getId());

try (ResultSet resultSet = stmt.executeQuery()) {
while (resultSet.next()) {
rows.add(RawSqlBuilder.sqlRow(resultSet, "true", false));
}
}
}

assertThat(rows).hasSize(1);
assertThat(rows.get(0).get("content")).isEqualTo(bytes);
}

}