22import java .sql .SQLException ;
33
44import java .util .concurrent .ConcurrentHashMap ;
5+ import java .util .concurrent .atomic .AtomicLong ;
56import java .util .concurrent .atomic .AtomicBoolean ;
67import java .util .ArrayList ;
78import java .util .HashMap ;
@@ -74,6 +75,12 @@ public class Recordset implements AutoCloseable {
7475 new ConcurrentHashMap <>();
7576
7677
78+ // private static final AtomicLong openStatements = new AtomicLong(0);
79+ // private static final AtomicLong openRecordsets = new AtomicLong(0);
80+ // private static final AtomicLong openCalls = new AtomicLong(0);
81+ // private static final AtomicLong closeCalls = new AtomicLong(0);
82+
83+
7784 //**************************************************************************
7885 //** Constructor
7986 //**************************************************************************
@@ -178,6 +185,7 @@ public java.sql.ResultSet open(String sqlString, Connection connection, boolean
178185 if (shuttingDown .get ()) throw new IllegalStateException ("JVM shutting down" );
179186 if (connection ==null ) throw new SQLException ("Connection is null." );
180187 if (connection .isClosed ()) throw new SQLException ("Connection is closed." );
188+ //openCalls.incrementAndGet();
181189
182190 rs = null ;
183191 stmt = null ;
@@ -245,9 +253,11 @@ else if (driver.equals("PostgreSQL")){
245253 stmt = Conn .createStatement ();
246254 }
247255 }
256+ //openStatements.incrementAndGet();
248257
249258 if (fetchSize !=null ) stmt .setFetchSize (fetchSize );
250259 rs = stmt .executeQuery (sqlString );
260+ //openRecordsets.incrementAndGet();
251261 State = 1 ;
252262 }
253263 catch (SQLException e ){
@@ -261,6 +271,14 @@ else if (driver.equals("PostgreSQL")){
261271
262272 //Read-Write Connection
263273 else {
274+
275+ /* Note that we don't actually use the rs and stmt objects when
276+ inserting or updating records anymore. We can probably remove
277+ all this code and simply use the ReadOnly code block above.
278+ In read/write mode, it seems we only use the rs and stmt
279+ objects to get field metadata via the init() method.
280+ */
281+
264282 try {
265283
266284 //SYBASE Connection
@@ -325,6 +343,9 @@ else if (driver.equals("DB2")){
325343 }
326344
327345
346+ //if (stmt!=null) openStatements.incrementAndGet();
347+ //if (rs!=null) openRecordsets.incrementAndGet();
348+
328349 }
329350 catch (SQLException e ){
330351 //System.out.println("ERROR Open RecordSet (RW): " + e.toString());
@@ -354,6 +375,7 @@ else if (driver.equals("DB2")){
354375 */
355376 public void open (java .sql .ResultSet resultSet ){
356377 if (shuttingDown .get ()) throw new IllegalStateException ("JVM shutting down" );
378+ //openCalls.incrementAndGet();
357379 startTime = System .currentTimeMillis ();
358380 queryResponseTime = ellapsedTime = metadataQueryTime = endTime = 0 ;
359381 EOF = true ;
@@ -421,13 +443,16 @@ private void init(){
421443 /** Closes the Recordset freeing up database and jdbc resources.
422444 */
423445 public void close (){
424-
446+ //closeCalls.incrementAndGet();
425447
426448 //Close recordset
427449 try {
428450 if (State ==1 ) executeBatch ();
429451 if (!isReadOnly ) commit ();
430- if (rs !=null ) rs .close ();
452+ if (rs !=null ){
453+ rs .close ();
454+ //openRecordsets.decrementAndGet();
455+ }
431456 if (stmt !=null ){
432457
433458 //Some databases (e.g. PostgreSQL) will continue executing a long
@@ -441,8 +466,13 @@ public void close(){
441466 catch (Exception e ){}
442467 }
443468
444- try { stmt .close (); }
445- catch (Exception e ){}
469+ try {
470+ stmt .close ();
471+ //openStatements.decrementAndGet();
472+ }
473+ catch (Exception e ){
474+ //e.printStackTrace();
475+ }
446476 }
447477 }
448478 catch (SQLException e ){
@@ -478,6 +508,9 @@ record = null;
478508
479509 endTime = System .currentTimeMillis ();
480510 ellapsedTime = endTime -startTime ;
511+
512+ //javaxt.utils.Console.console.log(openRecordsets + " openRecordsets, " + openStatements + " openStatements, " + (openCalls.get()-closeCalls.get()));
513+
481514 }
482515
483516
@@ -694,20 +727,21 @@ public void update() throws SQLException {
694727
695728 //Find how many records will be affected by this update
696729 int numRecords ;
697- java .sql .ResultSet r2 = stmt .executeQuery ("SELECT COUNT(*) FROM " + tableName + (where ==null ? "" : " WHERE " + where ));
698- try {
699- numRecords = r2 .getInt (1 );
700- }
701- catch (Exception e ){
730+ try (java .sql .ResultSet r2 = stmt .executeQuery (
731+ "SELECT COUNT(*) FROM " + tableName + (where ==null ? "" : " WHERE " + where ))){
702732 try {
703- r2 .first (); //SQLServer needs this!
704733 numRecords = r2 .getInt (1 );
705734 }
706- catch (Exception ex ){
707- numRecords = Integer .MAX_VALUE ;
735+ catch (Exception e ){
736+ try {
737+ r2 .first (); //SQLServer needs this!
738+ numRecords = r2 .getInt (1 );
739+ }
740+ catch (Exception ex ){
741+ numRecords = Integer .MAX_VALUE ;
742+ }
708743 }
709744 }
710- r2 .close ();
711745
712746
713747 //Warn user that there might be a problem with the update
@@ -766,8 +800,10 @@ public void update() throws SQLException {
766800 if (batchSize ==1 ){
767801 try {
768802 stmt .executeUpdate ();
803+ stmt .close ();
769804 }
770805 catch (SQLException e ){
806+ try {stmt .close ();}catch (Exception ex ){}
771807
772808 StringBuilder err = new StringBuilder ();
773809 err .append ("Error executing update:\n " );
@@ -798,6 +834,9 @@ public void update() throws SQLException {
798834 catch (Exception e ){
799835 //not all databases support auto generated keys
800836 }
837+ finally {
838+ stmt .close ();
839+ }
801840 InsertOnUpdate = false ;
802841 }
803842
@@ -1009,17 +1048,18 @@ protected static String getSTGeomFromText(Field field, Connection conn){
10091048 String geo = field .getClassName ().toLowerCase ();
10101049 if (!geo .equals ("geometry" ) && !geo .equals ("geography" )){
10111050 geo = null ;
1012- try {
1013- Recordset rs = new Recordset ();
1051+
1052+ try ( Recordset rs = new Recordset ()) {
10141053 rs .open ("SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS " +
10151054 "WHERE TABLE_NAME='" + field .getTableName () + "' AND COLUMN_NAME='" + field .getName () + "'" ,
10161055 conn );
10171056 geo = rs .getValue (0 ).toString ();
1018- rs .close ();
10191057 }
10201058 catch (SQLException e ){
10211059 //e.printStackTrace();
10221060 }
1061+
1062+
10231063 if (geo ==null ) geo = "geometry" ;
10241064 else geo = geo .toLowerCase ();
10251065 }
@@ -1113,20 +1153,38 @@ public void setUpdateKey(Object key){
11131153 private int executeBatch () throws SQLException {
11141154 if (batchedStatements ==null ) return 0 ;
11151155 int ttl = 0 ;
1116- java .util .Iterator <String > it = batchedStatements .keySet ().iterator ();
1117- while (it .hasNext ()){
1118- java .sql .PreparedStatement stmt = batchedStatements .get (it .next ());
11191156
1120- int [] rowsUpdated = stmt .executeBatch ();
1121- if (rowsUpdated .length >0 ) ttl +=rowsUpdated .length ;
1157+ try {
1158+ java .util .Iterator <String > it = batchedStatements .keySet ().iterator ();
1159+ while (it .hasNext ()){
1160+ try (java .sql .PreparedStatement stmt = batchedStatements .get (it .next ())){
1161+
1162+ int [] rowsUpdated = stmt .executeBatch ();
1163+ if (rowsUpdated .length >0 ) ttl +=rowsUpdated .length ;
1164+
1165+ java .sql .Connection Conn = connection .getConnection ();
1166+ if (Conn .getAutoCommit ()==false ){
1167+ Conn .commit ();
1168+ }
11221169
1123- java .sql .Connection Conn = connection .getConnection ();
1124- if (Conn .getAutoCommit ()==false ){
1125- Conn .commit ();
1170+ }
11261171 }
1172+
11271173 }
1128- batchedStatements .clear ();
1129- numBatches = 0 ;
1174+ catch (Exception e ){
1175+ throw e ;
1176+ }
1177+ finally {
1178+ java .util .Iterator <String > it = batchedStatements .keySet ().iterator ();
1179+ while (it .hasNext ()){
1180+ try { batchedStatements .get (it .next ()).close ();}
1181+ catch (Exception e ){}
1182+ }
1183+ batchedStatements .clear ();
1184+ numBatches = 0 ;
1185+ }
1186+
1187+
11301188 return ttl ;
11311189 }
11321190
@@ -1677,14 +1735,12 @@ public long getRecordCount(){
16771735 Long numRecords = null ;
16781736
16791737 String sql = new Parser (sqlString ).setSelect ("count(*)" );
1680- Recordset rs = new Recordset ();
1681- try {
1738+
1739+ try ( Recordset rs = new Recordset ()) {
16821740 rs .open (sql , connection );
16831741 numRecords = rs .getValue (0 ).toLong ();
1684- rs .close ();
16851742 }
16861743 catch (SQLException ex ){
1687- rs .close ();
16881744 }
16891745
16901746 if (numRecords !=null ) return numRecords ;
0 commit comments