未验证 提交 05acc9b2 编写于 作者: H huolibo 提交者: GitHub

[TD-14038]<fix>: bind result when statement is closed release the res… (#10774)

* [TD-14038]<fix>: bind result when statement is closed release the resource

* [TD-14038]<fix>: bind result fix test case

* [TD-14038]<fix>: release related resource when connection or statement close
上级 b8c8514a
package com.taosdata.jdbc;
import java.sql.*;
import java.util.Properties;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class TSDBConnection extends AbstractConnection {
private TSDBJNIConnector connector;
private final TSDBDatabaseMetaData databaseMetaData;
private boolean batchFetch;
private CopyOnWriteArrayList<Statement> statements = new CopyOnWriteArrayList<>();
public Boolean getBatchFetch() {
return this.batchFetch;
......@@ -67,11 +69,25 @@ public class TSDBConnection extends AbstractConnection {
}
public void close() throws SQLException {
if (isClosed) {
if (isClosed)
return;
synchronized (this) {
if (isClosed) {
return;
}
for (Statement statement : statements) {
statement.close();
}
this.connector.closeConnection();
this.isClosed = true;
}
this.connector.closeConnection();
this.isClosed = true;
}
public void unregisterStatement(Statement stmt) {
this.statements.remove(stmt);
}
public void registerStatement(Statement stmt) {
this.statements.addIfAbsent(stmt);
}
public boolean isClosed() throws SQLException {
......
......@@ -28,72 +28,86 @@ public class TSDBStatement extends AbstractStatement {
TSDBStatement(TSDBConnection connection) {
this.connection = connection;
connection.registerStatement(this);
}
public ResultSet executeQuery(String sql) throws SQLException {
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
}
//TODO:
// this is an unreasonable implementation, if the paratemer is a insert statement,
// the JNI connector will execute the sql at first and return a pointer: pSql,
// we use this pSql and invoke the isUpdateQuery(long pSql) method to decide .
// but the insert sql is already executed in database.
//execute query
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (this.connection.getConnector().isUpdateQuery(pSql)) {
this.connection.getConnector().freeResultSet(pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
synchronized (this) {
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
}
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
//TODO:
// this is an unreasonable implementation, if the paratemer is a insert statement,
// the JNI connector will execute the sql at first and return a pointer: pSql,
// we use this pSql and invoke the isUpdateQuery(long pSql) method to decide .
// but the insert sql is already executed in database.
//execute query
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (this.connection.getConnector().isUpdateQuery(pSql)) {
this.connection.getConnector().freeResultSet(pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
}
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
resultSet = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision);
resultSet.setBatchFetch(this.connection.getBatchFetch());
return resultSet;
}
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
TSDBResultSet res = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision);
res.setBatchFetch(this.connection.getBatchFetch());
return res;
}
public int executeUpdate(String sql) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (!this.connection.getConnector().isUpdateQuery(pSql)) {
synchronized (this) {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (!this.connection.getConnector().isUpdateQuery(pSql)) {
this.connection.getConnector().freeResultSet(pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEUPDATE);
}
int affectedRows = this.connection.getConnector().getAffectedRows(pSql);
this.connection.getConnector().freeResultSet(pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEUPDATE);
return affectedRows;
}
int affectedRows = this.connection.getConnector().getAffectedRows(pSql);
this.connection.getConnector().freeResultSet(pSql);
return affectedRows;
}
public void close() throws SQLException {
if (isClosed)
return;
connection.unregisterStatement(this);
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
isClosed = true;
}
public boolean execute(String sql) throws SQLException {
// check if closed
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
}
// execute query
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (this.connection.getConnector().isUpdateQuery(pSql)) {
this.affectedRows = this.connection.getConnector().getAffectedRows(pSql);
this.connection.getConnector().freeResultSet(pSql);
return false;
synchronized (this) {
// check if closed
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
}
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
// execute query
long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL
if (this.connection.getConnector().isUpdateQuery(pSql)) {
this.affectedRows = this.connection.getConnector().getAffectedRows(pSql);
this.connection.getConnector().freeResultSet(pSql);
return false;
}
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
this.resultSet = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision);
this.resultSet.setBatchFetch(this.connection.getBatchFetch());
return true;
}
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
this.resultSet = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision);
this.resultSet.setBatchFetch(this.connection.getBatchFetch());
return true;
}
public ResultSet getResultSet() throws SQLException {
......
......@@ -71,18 +71,16 @@ public class NanoSecondTimestampJNITest {
long ns = ms * 1000_000L + random.nextInt(1000_000);
// when
ResultSet rs = null;
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)");
rs = stmt.executeQuery("select * from weather");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
// then
long actual = rs.getLong(1);
Assert.assertEquals(ns, actual);
actual = rs.getLong("ts");
Assert.assertEquals(ns, actual);
}
// then
long actual = rs.getLong(1);
Assert.assertEquals(ns, actual);
actual = rs.getLong("ts");
Assert.assertEquals(ns, actual);
}
@Test
......@@ -91,18 +89,16 @@ public class NanoSecondTimestampJNITest {
String timestampStr = "2021-01-01 12:00:00.123456789";
// when
ResultSet rs;
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)");
rs = stmt.executeQuery("select * from weather");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
// then
String actual = rs.getString(1);
Assert.assertEquals(timestampStr, actual);
actual = rs.getString("ts");
Assert.assertEquals(timestampStr, actual);
}
// then
String actual = rs.getString(1);
Assert.assertEquals(timestampStr, actual);
actual = rs.getString("ts");
Assert.assertEquals(timestampStr, actual);
}
@Test
......@@ -123,19 +119,17 @@ public class NanoSecondTimestampJNITest {
}
// when
ResultSet rs = null;
try (Statement stmt = conn.createStatement()) {
rs = stmt.executeQuery("select * from weather");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
// then
Timestamp actual = rs.getTimestamp(1);
Assert.assertEquals(ts, actual);
actual = rs.getTimestamp("ts");
Assert.assertEquals(ts, actual);
Assert.assertEquals(timeMillis, actual.getTime());
Assert.assertEquals(nanoAdjustment, actual.getNanos());
}
// then
Timestamp actual = rs.getTimestamp(1);
Assert.assertEquals(ts, actual);
actual = rs.getTimestamp("ts");
Assert.assertEquals(ts, actual);
Assert.assertEquals(timeMillis, actual.getTime());
Assert.assertEquals(nanoAdjustment, actual.getNanos());
}
@Before
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册