tags:

views:

64

answers:

3

I am trying to run multiple MySQL queries which build up on each other: i.e field value of one element in each row is used as input for another query.

I end up getting the following error:

java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@174cc1f is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:914)
    at com.mysql.jdbc.MysqlIO.checkForOutstandingStreamingData(MysqlIO.java:2074)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1484)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
    at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
    at com.mysql.jdbc.Connection.execSQL(Connection.java:3099)
    at com.mysql.jdbc.Statement.executeQuery(Statement.java:1169)
    at Stats.readInterfaces(Stats.java:105)
    at Stats.connect(Stats.java:63)
    at automateExport.main(automateExport.java:15)

I have called .close() after every ResultSet and Statement of the query. I guess we cannot have multiple resultsets open at one time. Is there any way to get around this problem?

Here is the relevant code:

public class Stats {
    public static int UTC = 0;
    public String interfaceId = "no value";
    public String rId = "no value";
    public String NL = System.getProperty("line.separator");
    public String CSV = ",";
    public static String startTime,endTime,performanceTable =null;
    public static int outputType = 1;
    public String pTable = "('2010-7-13 00:00')";
    public String start = "('2010-7-13 09:00')";
    public String end = "('2010-7-13 17:00')";
    Connection conn;
    Statement stmtRouter, stmtInterface, stmtTime, stmtD;
    String query;
    ResultSet rsRouter, rsInterface, rsD, rsTime;
    public Connection connect(String db_connect_str,String db_userid, String db_password) {
      String routerName,routerId = null, routerNetwork = null;
     // inputfile - csv

        try {
         // to bifurcate heap memory error   
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(db_connect_str,db_userid, db_password);
            stmtRouter = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  
                    java.sql.ResultSet.CONCUR_READ_ONLY);
            stmtRouter.setFetchSize(Integer.MIN_VALUE); 

            query = "Select r.name,r.rid,r.network FROM router AS r Where r.network = 'ITPN'";



            String append = null;
            // writing to file
            performanceTable = readTime(pTable);
            startTime = readTime(start);
            endTime = readTime(end);
            rsRouter = stmtRouter.executeQuery(query); 
            while (rsRouter.next()) {
                routerName = rsRouter.getString(1);
                System.out.println(routerName);
           //   routerId = rsRouter.getString("rid");
           //   routerNetwork = rsRouter.getString("network");
                append = routerName+CSV+routerId+CSV+routerNetwork;
                readInterfaces(routerId,startTime,endTime,performanceTable, append);

            }

            stmtRouter.close() ;
            rsRouter.close();
            //      output(2,input);
    //              output(outputType , input);
        } catch(Exception e) {
            e.printStackTrace();
            conn = null;
        }
        return conn;
    }
    private String readTime(String time) throws SQLException {
        stmtTime = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  
                java.sql.ResultSet.CONCUR_READ_ONLY);
        stmtTime.setFetchSize(Integer.MIN_VALUE); 
        query = "Select unix_timestamp"+time;
        rsTime = stmtTime.executeQuery(query); 
        String unixTime = null;
        while(rsTime.next()){
            unixTime = rsTime.getString(1);
            System.out.println(unixTime);
        }

        rsTime.close();
        stmtTime.close();
        return unixTime;
    }

    private void readInterfaces(String routerId, String startTime, String endTime, String performanceTable, String append) throws SQLException, IOException {
        String interfaceId, iDescp, iStatus = null;
        String dtime, ingress, egress = null;
        stmtInterface = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  
                java.sql.ResultSet.CONCUR_READ_ONLY);
        stmtInterface.setFetchSize(Integer.MIN_VALUE); 
        stmtD = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,  
                java.sql.ResultSet.CONCUR_READ_ONLY);
        stmtD.setFetchSize(Integer.MIN_VALUE); 

        query = " Select i.id,i.description, i.status from interface as i Where i.rid = " + routerId +" And i.status = 'active'";
        rsInterface = stmtInterface.executeQuery(query);
        String input = "inputData.txt";
        BufferedWriter fw = new BufferedWriter(new FileWriter(input));  
        stmtInterface.close();
        while(rsInterface.next()){
            interfaceId = rsInterface.getString("id");
            iDescp = rsInterface.getString("description");
            iStatus = rsInterface.getString("status");

            if(!iStatus.equals("active")){
                /* performance table query*/
                query = " Select d.dtime,d.ifInOctets, d.ifOutOctets from "+performanceTable+"_1_60" +" AS d Where d.id = " +
                interfaceId + "AND dtime BETWEEN " +startTime+ " AND "+ endTime + " Order By d.id";
                rsD = stmtD.executeQuery(query); 

                while(rsD.next()){
                    dtime = rsD.getString("dtime");
                    ingress = rsD.getString("ifInOctets");
                    egress = rsD.getString("ifOutOctets");
                    fw.write(append + CSV + interfaceId+CSV+iDescp+CSV+dtime+CSV+ingress+CSV+egress+NL);
                }// end of while
                rsD.close();
                stmtD.close();

            }
        }
        fw.close();
    //    rsInterface.close() ; 
       // stmtInterface.close();

    }

}
A: 

You definitely shouldn't close Statement object before you end working with ResultSet (function readInterfaces).

rsInterface = stmtInterface.executeQuery(query);
String input = "inputData.txt";
BufferedWriter fw = new BufferedWriter(new FileWriter(input));  

stmtInterface.close(); // Don't do this!!! It should be when you are done with rsInterface)
while(rsInterface.next()){
a1ex07
tried this. same error :(
jillika iyer
A: 

You cannot have more than one result set being open per connection. I believe here is the reason for the failure:

You call readInterfaces(routerId,startTime,endTime,performanceTable, append) (where you open new resultset) before you close Router resultset:

  readInterfaces(routerId,startTime,endTime,performanceTable, append);
}
stmtRouter.close() ;
rsRouter.close();

I would move close statements before the call to readInterfaces(...). I would also close the result set and statement in opposite order (resultset first).

spbfox
but i need the router resultset open for processing all the data. how can i close it before itself? it will not work then
jillika iyer
I can propose 2 solutions:1. Open separate connection inside readInterfaces to conform to the 1resultset-per-connection restriction.2. Grab the data from rsRouter to a collection, close the resultset and then call readInterfaces with the results from the collection.
spbfox
hi , thanks. is there any way to optimize the query execution. even after breaking it into 3 queries I end up getting a very bad working time of 20 mins:P ( the file i generate is like a 200 + MB text file. Still 20 mins is like way too much!
jillika iyer
+2  A: 

Exactly, as the error says, you cannot issue additional queries over the same connection when you have a streaming result set open. Relevant documentation is here.

So, the obvious solution would be not to use a streaming result set for the driving query. The downside of this is that it will use more memory. The rather obscure comment at the top of your code implies that maybe someone tried this already and had memory issues.

Anyway, there is a better solution. This is a classic example of over-proceduralization. You are doing work in your code that could be better handled by the database engine. Instead of executing single-table queries that drive each other, you can combine those into one query using a join:

Select r.name,r.rid,r.network,i.id,i.description, i.status
FROM router AS r JOIN interface as i ON i.rid = r.rid
Where r.network = 'ITPN'
  AND i.status='active'

Then, you have a third "nested" query, which you can incorporate with an additional join. I think it would be:

Select r.name,r.rid,r.network,i.id,i.description, i.status,d.dtime,d.ifInOctets, d.ifOutOctets
FROM router AS r JOIN interface as i ON i.rid = r.rid
  JOIN <performanceTable>_1_60 as d ON d.id = i.id
Where r.network = 'ITPN'
  AND i.status='active'
  AND dtime BETWEEN <startTime> AND <endTime>
Order By d.id

You probably don't need all those columns in the final select list, but I haven't pored through your code to see what is really being used.

Dave Costa
hi.. this is what i had done first. but resultset is super huge. so broke down the query to multiple queries. :)but that seems to have issues which i mentioned above :P
jillika iyer
If you use a streaming result set, what problem is actually caused by a "super huge" result set? It seems to me you are processing the same amount of data either way, and if you can stream it, memory shouldn't be an issue.
Dave Costa