// this module takes as input a query, executes it, and returns its result import java.sql.*; import oracle.jdbc.pool.OracleDataSource; import oracle.jdbc.driver.OracleResultSet; import oracle.sql.ROWID; public class ExecutionModule { private ResultSet result; private Statement stmt, tempStmt; private PreparedStatement pstmt; private Connection conn; private EstabConn localdb; private static int TIDStart=0; private static int TIDCount=0; public static int QIDStart=0; public static int distinctRows=0; public ExecutionModule() { // establish connection to the database try { localdb = new EstabConn(); conn = localdb.connectdb(new String("orcl")); stmt = conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); tempStmt = conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); result = null; } catch(SQLException ex) { ex.printStackTrace(); System.out.println("Error in establishing connection with the database: in class ExecutionModule"); System.exit(0); } // we may want to read the properties file here... } public ResultSet execute(String sSql) { try { result = stmt.executeQuery (sSql); } catch (SQLException ex) { ex.printStackTrace(); System.out.println("Error in executing query: " + sSql + " in class ExecutionModule"); System.exit(0); } return result; } // this method will execute the query and update all related data structures public void executeUpdate(String sSql) throws SQLException { try { result = stmt.executeQuery (sSql); } catch (SQLException ex) { ex.printStackTrace(); System.out.println("Error in executing query: " + sSql + " in class ExecutionModule"); System.exit(0); } // compare query results with those already present in cache: table CT populate(result,sSql); update_InfoStruct(sSql); //rowCount = ResultSetProcessing.getRowCount(result); //System.out.println(rowCount); // update cacheInfo table } public void populate(ResultSet result, String sqlQuery) throws SQLException { if( result==null || result.next()==false ) { System.out.println("Empty resultset : nothing to be stored : in class ExecutionModule "); saveSequenceNumbers(); // we will still advance the QID sequence number return; } else { saveSequenceNumbers(); ResultSet rsetCache = null; do { // first column has to be rowid String rowid = (( (OracleResultSet) result).getROWID(1)).stringValue(); //String rowid = rset.getString(1); //System.out.println(rowid + " rowid string"); String str = "select rowid from CT where RID = '" + rowid + "'"; rsetCache = tempStmt.executeQuery(str); if (rsetCache.next() == false ) { // data is not in cache System.out.println ("inserting into cachetable for the first time....query ID: " + QIDStart); // call populate... something str = "insert into CT (RID,QID) values('" + rowid + "'," + QIDStart + ")" ; tempStmt.executeUpdate(str); } else { System.out.println ("Data already present in cache "); // save some info about the query id and tid.... str = "insert into DT (RID,QID) values('" + rowid + "'," + QIDStart + ")" ; tempStmt.executeUpdate(str); // NOTE: even if data is repeated, it will be stored in CT also // for exact cache size, we use distinct(RID) in CT str = "insert into CT (RID,QID) values('" + rowid + "'," + QIDStart + ")" ; tempStmt.executeUpdate(str); } } while (result.next ()); } // end of else } public void saveSequenceNumbers() { try { // Execute the query tempStmt.executeQuery ("select TID.nextval, QID.nextval from dual"); ResultSet t1 = tempStmt.executeQuery ("select TID.currval, QID.currval from dual"); t1.next(); TIDStart = t1.getInt(1); QIDStart = t1.getInt(2); t1.close(); } catch (SQLException se) { System.out.println("oops! a problem in executing tempStmt in saveSequencenumbers : in class ExecutionModule"); se.printStackTrace(); } } public void update_InfoStruct(String sSql) throws SQLException { // here we are only interested in that part of the query that is executed remotely // a decision to include this query will be made on the basis of its size by the replacement module // locally executed part will not add to the cache size. // however, it will be used to update the freshness count of the queries already in cache String s; ResultSet t1; int DTCount, CTCount, iQSize; // partial query that was already present in cache. // this will be used to calculate the improve in hit rate and other benefits. s = "select count(*) from DT where QID = " + QIDStart ; t1 = tempStmt.executeQuery(s); t1.next(); DTCount = t1.getInt(1); s = "select count(*) from CT where QID = " + QIDStart ; t1 = tempStmt.executeQuery(s); t1.next(); CTCount = t1.getInt(1); // total query result size iQSize = CTCount; // this is so becuase we store in CT all tuples, irrespective of // whether they are being repeated or not. t1.close(); // if rowCount is 0, it means that the query is new. if(DTCount==0) { // do nothing. } else { // we will have to change the fressness of the queries that are affected by these Tids } // here we update queryInfoStruct // later modules will decide whether to store this query in cache or not queryInfoStruct.currQueryString = sSql; queryInfoStruct.id = QIDStart; queryInfoStruct.freshness = 0; queryInfoStruct.currQuerySize = CTCount - DTCount; // (all - repeat) queryInfoStruct.repQuerySize = DTCount; queryInfoStruct.totalQuerySize = iQSize; queryInfoStruct.currX = 0; queryInfoStruct.currY = 0; System.out.println(DTCount + " DT"); } public void close() { try { stmt.close(); tempStmt.close(); conn.close(); localdb.close(); } catch(SQLException ex) { ex.printStackTrace(); System.out.println("Error in closing connection to the database: in class ExecutionModule "); System.exit(0); } } // end of class ExecutionModule }