未验证 提交 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; package com.taosdata.jdbc;
import java.sql.*; import java.sql.*;
import java.util.Properties; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class TSDBConnection extends AbstractConnection { public class TSDBConnection extends AbstractConnection {
private TSDBJNIConnector connector; private TSDBJNIConnector connector;
private final TSDBDatabaseMetaData databaseMetaData; private final TSDBDatabaseMetaData databaseMetaData;
private boolean batchFetch; private boolean batchFetch;
private CopyOnWriteArrayList<Statement> statements = new CopyOnWriteArrayList<>();
public Boolean getBatchFetch() { public Boolean getBatchFetch() {
return this.batchFetch; return this.batchFetch;
...@@ -67,12 +69,26 @@ public class TSDBConnection extends AbstractConnection { ...@@ -67,12 +69,26 @@ public class TSDBConnection extends AbstractConnection {
} }
public void close() throws SQLException { public void close() throws SQLException {
if (isClosed)
return;
synchronized (this) {
if (isClosed) { if (isClosed) {
return; return;
} }
for (Statement statement : statements) {
statement.close();
}
this.connector.closeConnection(); this.connector.closeConnection();
this.isClosed = true; 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 { public boolean isClosed() throws SQLException {
return this.connector != null && this.connector.isClosed(); return this.connector != null && this.connector.isClosed();
......
...@@ -28,12 +28,16 @@ public class TSDBStatement extends AbstractStatement { ...@@ -28,12 +28,16 @@ public class TSDBStatement extends AbstractStatement {
TSDBStatement(TSDBConnection connection) { TSDBStatement(TSDBConnection connection) {
this.connection = connection; this.connection = connection;
connection.registerStatement(this);
} }
public ResultSet executeQuery(String sql) throws SQLException { public ResultSet executeQuery(String sql) throws SQLException {
synchronized (this) {
if (isClosed()) { if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} }
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
//TODO: //TODO:
// this is an unreasonable implementation, if the paratemer is a insert statement, // 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, // the JNI connector will execute the sql at first and return a pointer: pSql,
...@@ -47,14 +51,18 @@ public class TSDBStatement extends AbstractStatement { ...@@ -47,14 +51,18 @@ public class TSDBStatement extends AbstractStatement {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
} }
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql); int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
TSDBResultSet res = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision); resultSet = new TSDBResultSet(this, this.connection.getConnector(), pSql, timestampPrecision);
res.setBatchFetch(this.connection.getBatchFetch()); resultSet.setBatchFetch(this.connection.getBatchFetch());
return res; return resultSet;
}
} }
public int executeUpdate(String sql) throws SQLException { public int executeUpdate(String sql) throws SQLException {
synchronized (this) {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
long pSql = this.connection.getConnector().executeQuery(sql); long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL // if pSql is create/insert/update/delete/alter SQL
...@@ -66,20 +74,25 @@ public class TSDBStatement extends AbstractStatement { ...@@ -66,20 +74,25 @@ public class TSDBStatement extends AbstractStatement {
this.connection.getConnector().freeResultSet(pSql); this.connection.getConnector().freeResultSet(pSql);
return affectedRows; return affectedRows;
} }
}
public void close() throws SQLException { public void close() throws SQLException {
if (isClosed) if (isClosed)
return; return;
connection.unregisterStatement(this);
if (this.resultSet != null && !this.resultSet.isClosed()) if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close(); this.resultSet.close();
isClosed = true; isClosed = true;
} }
public boolean execute(String sql) throws SQLException { public boolean execute(String sql) throws SQLException {
synchronized (this) {
// check if closed // check if closed
if (isClosed()) { if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} }
if (this.resultSet != null && !this.resultSet.isClosed())
this.resultSet.close();
// execute query // execute query
long pSql = this.connection.getConnector().executeQuery(sql); long pSql = this.connection.getConnector().executeQuery(sql);
...@@ -95,6 +108,7 @@ public class TSDBStatement extends AbstractStatement { ...@@ -95,6 +108,7 @@ public class TSDBStatement extends AbstractStatement {
this.resultSet.setBatchFetch(this.connection.getBatchFetch()); this.resultSet.setBatchFetch(this.connection.getBatchFetch());
return true; return true;
} }
}
public ResultSet getResultSet() throws SQLException { public ResultSet getResultSet() throws SQLException {
if (isClosed()) { if (isClosed()) {
......
...@@ -71,19 +71,17 @@ public class NanoSecondTimestampJNITest { ...@@ -71,19 +71,17 @@ public class NanoSecondTimestampJNITest {
long ns = ms * 1000_000L + random.nextInt(1000_000); long ns = ms * 1000_000L + random.nextInt(1000_000);
// when // when
ResultSet rs = null;
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)"); 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(); rs.next();
}
// then // then
long actual = rs.getLong(1); long actual = rs.getLong(1);
Assert.assertEquals(ns, actual); Assert.assertEquals(ns, actual);
actual = rs.getLong("ts"); actual = rs.getLong("ts");
Assert.assertEquals(ns, actual); Assert.assertEquals(ns, actual);
} }
}
@Test @Test
public void selectUsingStringValue() throws SQLException { public void selectUsingStringValue() throws SQLException {
...@@ -91,19 +89,17 @@ public class NanoSecondTimestampJNITest { ...@@ -91,19 +89,17 @@ public class NanoSecondTimestampJNITest {
String timestampStr = "2021-01-01 12:00:00.123456789"; String timestampStr = "2021-01-01 12:00:00.123456789";
// when // when
ResultSet rs;
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)"); 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(); rs.next();
}
// then // then
String actual = rs.getString(1); String actual = rs.getString(1);
Assert.assertEquals(timestampStr, actual); Assert.assertEquals(timestampStr, actual);
actual = rs.getString("ts"); actual = rs.getString("ts");
Assert.assertEquals(timestampStr, actual); Assert.assertEquals(timestampStr, actual);
} }
}
@Test @Test
public void selectUsingTimestampValue() throws SQLException { public void selectUsingTimestampValue() throws SQLException {
...@@ -123,12 +119,9 @@ public class NanoSecondTimestampJNITest { ...@@ -123,12 +119,9 @@ public class NanoSecondTimestampJNITest {
} }
// when // when
ResultSet rs = null;
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
rs = stmt.executeQuery("select * from weather"); ResultSet rs = stmt.executeQuery("select * from weather");
rs.next(); rs.next();
}
// then // then
Timestamp actual = rs.getTimestamp(1); Timestamp actual = rs.getTimestamp(1);
Assert.assertEquals(ts, actual); Assert.assertEquals(ts, actual);
...@@ -137,6 +130,7 @@ public class NanoSecondTimestampJNITest { ...@@ -137,6 +130,7 @@ public class NanoSecondTimestampJNITest {
Assert.assertEquals(timeMillis, actual.getTime()); Assert.assertEquals(timeMillis, actual.getTime());
Assert.assertEquals(nanoAdjustment, actual.getNanos()); Assert.assertEquals(nanoAdjustment, actual.getNanos());
} }
}
@Before @Before
public void before() throws SQLException { public void before() throws SQLException {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册