select count optimization...
[mir.git] / source / mir / storage / Database.java
index 575d374..5c40ac2 100755 (executable)
@@ -8,10 +8,11 @@ import  java.lang.*;
 import  java.io.*;
 import  java.util.*;
 import  freemarker.template.*;
-import  com.javaexchange.dbConnectionBroker.*;
 import  mir.storage.StorageObject;
 import  mir.entity.*;
 import  mir.misc.*;
+import com.codestudio.sql.*;
+import com.codestudio.util.*;
 
 
 /**
@@ -27,13 +28,13 @@ import  mir.misc.*;
  */
 public class Database implements StorageObject {
 
-  protected DbConnectionBroker        myBroker;
   protected String                    theTable;
   protected String                    theCoreTable=null;
   protected String                    thePKeyName="id";
   protected int                       thePKeyType;
   protected boolean                   evaluatedMetaData=false;
-  protected ArrayList                 metadataFields,metadataLabels,metadataNotNullFields;
+  protected ArrayList                 metadataFields,metadataLabels,
+                                      metadataNotNullFields;
   protected int[]                     metadataTypes;
   protected Class                     theEntityClass;
   protected StorageObject             myselfDatabase;
@@ -59,25 +60,31 @@ public class Database implements StorageObject {
    * @param   String confFilename Dateiname der Konfigurationsdatei
    */
   public Database() throws StorageObjectException {
-    theLog = Logfile.getInstance(MirConfig.getProp("Home") + MirConfig.getProp("Database.Logfile"));
-    String database_username=MirConfig.getProp("Database.Username");
-    String database_password=MirConfig.getProp("Database.Password");
-    String database_host=MirConfig.getProp("Database.Host");
+    theLog = Logfile.getInstance(MirConfig.getProp("Home")+
+                                MirConfig.getProp("Database.Logfile"));
     String theAdaptorName=MirConfig.getProp("Database.Adaptor");
+    defaultLimit = Integer.parseInt(MirConfig.getProp("Database.Limit"));
     try {
       theEntityClass = Class.forName("mir.entity.GenericEntity");
       theAdaptor = (DatabaseAdaptor)Class.forName(theAdaptorName).newInstance();
-      defaultLimit = Integer.parseInt(MirConfig.getProp("Database.Limit"));
+    } catch (Exception e){
+      theLog.printError("Error in Database() constructor with "+
+                        theAdaptorName + " -- " +e.toString());
+      throw new StorageObjectException("Error in Database() constructor with "
+                                       +e.toString());
+    }
+    /*String database_username=MirConfig.getProp("Database.Username");
+    String database_password=MirConfig.getProp("Database.Password");
+    String database_host=MirConfig.getProp("Database.Host");
+    try {
       database_driver=theAdaptor.getDriver();
-      database_url=theAdaptor.getURL(database_username,database_password,database_host);
-      theLog.printDebugInfo("adding Broker with: " +database_driver+":"+database_url  );
+      database_url=theAdaptor.getURL(database_username,database_password,
+                                    database_host);
+      theLog.printDebugInfo("adding Broker with: " +database_driver+":"+
+                            database_url  );
       MirConfig.addBroker(database_driver,database_url);
-      myBroker=MirConfig.getBroker();
-    }
-    catch (Exception e){
-      theLog.printError("Bei Konstruktion von Database() with " + theAdaptorName + " -- " +e.toString());
-      throw new StorageObjectException(e.toString());
-    }
+      //myBroker=MirConfig.getBroker();
+    }*/
   }
 
   /**
@@ -121,7 +128,8 @@ public class Database implements StorageObject {
 
   /*
    *   Dient dazu vererbte Tabellen bei objectrelationalen DBMS
-   *   zu speichern, wenn die id einer Tabelle in der parenttabelle verwaltet wird.
+   *   zu speichern, wenn die id einer Tabelle in der parenttabelle verwaltet
+   *   wird.
    *   @return liefert theCoreTabel als String zurueck, wenn gesetzt, sonst
    *    the Table
    */
@@ -427,20 +435,22 @@ public class Database implements StorageObject {
       con = getPooledCon();
       stmt = con.createStatement();
       // counting rows
-      if (theAdaptor.hasLimit()) {
-        rs = executeSql(stmt, countSql.toString());
-        if (rs != null) {
-          if (rs.next())
-            count = rs.getInt(1);
-          rs.close();
-        } else {
-          theLog.printError("Mh. Konnte nicht zaehlen: " + countSql);
-        }
-      }
-      //nothing in the table: return null
-      if(count<=0){
-        return null;
-      }
+
+      /** @todo select count(*) should be optimized:
+       *  1. it should take place after select statement because in some
+       *     cases it is not necessary anymore.
+       *  2. it is only needed if entitylist needs information about how
+       *     many datasets there are overall
+       *
+       *  optimization:
+       *
+       *  if we manage to have the full information about allData already
+       *  with the select statement, then we set it in entitylist, other
+       *  wise we fetch it.  /rk
+       *  */
+
+
+
       // hier select
       rs = executeSql(stmt, selectSql.toString());
       if (rs != null) {
@@ -456,11 +466,26 @@ public class Database implements StorageObject {
         }
         rs.close();
       }
-      // making entitylist
-      if (!(theAdaptor.hasLimit()))
-        count = offsetCount;
+
+      // making entitylist infos
+      if (!(theAdaptor.hasLimit())) count = offsetCount;
+
       if (theReturnList != null) {
+        // now we decide if we have to know an overall count...
+        count=offsetCount;
+        if (limit > -1 && offset > -1) {
+          if (offsetCount==limit) {
+            rs = executeSql(stmt, countSql.toString());
+            if (rs != null) {
+              if ( rs.next() ) count = rs.getInt(1);
+              rs.close();
+            }
+            else theLog.printError("Could not count: " + countSql);
+          }
+        }
+
         theReturnList.setCount(count);
+
         theReturnList.setOffset(offset);
         theReturnList.setWhere(wc);
         theReturnList.setOrder(ob);
@@ -470,6 +495,9 @@ public class Database implements StorageObject {
         if (offset + offsetCount < count) {
           theReturnList.setNextBatch(offset + limit);
         }
+
+
+
       }
     } catch (SQLException sqe) {
       throwSQLException(sqe, "selectByWhereClause");
@@ -479,6 +507,7 @@ public class Database implements StorageObject {
     return  theReturnList;
   }
 
+
   /**
    *  Bastelt aus einer Zeile der Datenbank ein EntityObjekt.
    *
@@ -486,7 +515,7 @@ public class Database implements StorageObject {
    *  @return Entity Die Entity.
    */
 
-  public Entity makeEntityFromResultSet (ResultSet rs) throws StorageObjectException {
+  private Entity makeEntityFromResultSet (ResultSet rs) throws StorageObjectException {
     HashMap theResultHash = new HashMap();
     String theResult = null;
     int theType;
@@ -521,11 +550,9 @@ public class Database implements StorageObject {
         }
       }
       if (cache != null && theResultHash.containsKey(thePKeyName) &&
-            (cache.containsKey((String)theResultHash.get(thePKeyName)) > -1)) {
-        //theLog.printDebugInfo("CACHE: (out) "+ theResultHash.get(thePKeyName)+ " :"+theTable);
+          (cache.containsKey((String)theResultHash.get(thePKeyName)) > -1)) {
         returnEntity = (Entity)cache.get((String)theResultHash.get(thePKeyName));
-      }
-      else {
+      } else {
         if (theEntityClass != null) {
           returnEntity = (Entity)theEntityClass.newInstance();
           returnEntity.setValues(theResultHash);
@@ -534,13 +561,11 @@ public class Database implements StorageObject {
             //theLog.printDebugInfo("CACHE: ( in) " + returnEntity.getId() + " :"+theTable);
             cache.put(returnEntity.getId(), returnEntity);
           }
-        }
-        else {
+        } else {
           throwStorageObjectException("Interner Fehler theEntityClass nicht gesetzt!");
         }
       }
-    }           // try
-    catch (IllegalAccessException e) {
+    } catch (IllegalAccessException e) {
       throwStorageObjectException("Kein Zugriff! -- " + e.toString());
     } catch (IOException e) {
       throwStorageObjectException("IOException! -- " + e.toString());
@@ -797,7 +822,9 @@ public class Database implements StorageObject {
     Connection con = null;
     Statement stmt = null;
     // build sql
-    StringBuffer sql = new StringBuffer("select ").append(thePKeyName).append(",").append(name).append(" from ").append(theTable);
+    StringBuffer sql = new StringBuffer("select ").append(thePKeyName)
+                                        .append(",").append(name).append(" from ")
+                                        .append(theTable);
     if (where != null && !(where.length() == 0))
       sql.append(" where ").append(where);
     sql.append(" order by ");
@@ -808,6 +835,10 @@ public class Database implements StorageObject {
     // execute sql
     try {
       con = getPooledCon();
+    } catch (Exception e) {
+      throw new StorageObjectException(e.toString());
+    }
+    try {
       stmt = con.createStatement();
       ResultSet rs = executeSql(stmt, sql.toString());
       if (rs != null) {
@@ -830,7 +861,7 @@ public class Database implements StorageObject {
         rs.close();
       }
     } catch (Exception e) {
-      theLog.printDebugInfo(e.toString());
+      theLog.printError("getPopupData: "+e.toString());
       throw new StorageObjectException(e.toString());
     } finally {
       freeConnection(con, stmt);
@@ -887,8 +918,8 @@ public class Database implements StorageObject {
     }
     catch (SQLException e)
     {
-      theLog.printDebugInfo("Failed: " + (new java.util.Date().getTime() - startTime) + "ms. for: "
-        + sql);
+      theLog.printDebugInfo("Failed: " + (new java.util.Date().getTime()
+                            - startTime) + "ms. for: "+ sql);
       throw e;
     }
 
@@ -902,8 +933,8 @@ public class Database implements StorageObject {
    * @return Liefert ResultSet des Statements zurueck.
    * @exception StorageObjectException, SQLException
    */
-  public ResultSet executeSql (PreparedStatement stmt) throws StorageObjectException,
-      SQLException {
+  public ResultSet executeSql (PreparedStatement stmt)
+    throws StorageObjectException, SQLException {
 
     long startTime = (new java.util.Date()).getTime();
     ResultSet rs = stmt.executeQuery();
@@ -937,7 +968,8 @@ public class Database implements StorageObject {
       freeConnection(con,stmt);
     }
     theLog.printInfo(theTable + " has "+ result +" rows where " + where);
-    theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: " + sql);
+    theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: "
+                    + sql);
     return result;
   }
 
@@ -949,12 +981,13 @@ public class Database implements StorageObject {
     try
     {
       rs = stmt.executeUpdate(sql);
-      theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: " + sql);
+      theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: "
+                        + sql);
     }
     catch (SQLException e)
     {
-      theLog.printDebugInfo("Failed: " + (new java.util.Date().getTime() - startTime) + "ms. for: "
-        + sql);
+      theLog.printDebugInfo("Failed: " + (new java.util.Date().getTime()
+                            - startTime) + "ms. for: "+ sql);
       throw e;
     }
     return rs;
@@ -976,7 +1009,8 @@ public class Database implements StorageObject {
       throw new StorageObjectException("executeUpdate failed: "+e.toString());
     }
     finally { freeConnection(con,pstmt); }
-    theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: " + sql);
+    theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: "
+                    + sql);
     return result;
   }
 
@@ -985,7 +1019,9 @@ public class Database implements StorageObject {
    * @param md ResultSetMetaData
    * @exception StorageObjectException
    */
-  private void evalMetaData (ResultSetMetaData md) throws StorageObjectException {
+  private void evalMetaData (ResultSetMetaData md)
+    throws StorageObjectException {
+
     this.evaluatedMetaData = true;
     this.metadataFields = new ArrayList();
     this.metadataLabels = new ArrayList();
@@ -1035,52 +1071,31 @@ public class Database implements StorageObject {
     }
   }
 
-  /**
-   * Datenbankverbindung wird geschlossen
-   */
-  public void disconnectPool () throws StorageObjectException {
-    try {
-      myBroker.destroy(100);
-    } catch (SQLException sqe) {
-      throwSQLException(sqe, "disconnectPool");
-    }
-  }
 
-  /**
-   * Returns Connection-Object out of the PoolBroker.
-   *
-   * @return Connection Object.
-   */
-  public Connection getPooledCon () throws StorageObjectException {
-    if (myBroker != null) {
-      Connection con = myBroker.getConnection();
-      if (con != null)
-        return  con;
+  public Connection getPooledCon() throws StorageObjectException {
+    /* @todo , doublecheck but I'm pretty sure that this is unnecessary. -mh
+      try{
+      Class.forName("com.codestudio.sql.PoolMan").newInstance();
+    } catch (Exception e){
+      throw new StorageObjectException("Could not find the PoolMan Driver"
+                                        +e.toString());
+    }*/
+    Connection con = null;
+    try{
+      con = SQLManager.getInstance().requestConnection();
+    } catch(SQLException e){
+      theLog.printError("could not connect to the database "+e.toString());
+      System.err.println("could not connect to the database "+e.toString());
+      throw new StorageObjectException("Could not connect to the database"+
+                                        e.toString());
     }
-    throw  new StorageObjectException("No connection to database!");
+    return con;
   }
 
-  /**
-   * Connection und StatementObjekt werden geschlossen und an den Connectionpool
-   * zurückgeben
-   * @param con Connection zur Datenbank
-   * @param stmt Statement-Objekt
-   */
   public void freeConnection (Connection con, Statement stmt)
     throws StorageObjectException {
-    try {
-      if (stmt != null)
-        stmt.close();
-    } catch (SQLException e1) {
-      theLog.printDebugInfo(e1.toString());
-      throw new StorageObjectException("DB, in freeConnection: "+e1.toString());
-    }
-    if (con != null)
-      myBroker.freeConnection(con);
-    else {
-      theLog.printDebugInfo("Con was null!");
-      throw new StorageObjectException("Con was null!");
-    }
+    SQLManager.getInstance().closeStatement(stmt);
+    SQLManager.getInstance().returnConnection(con);
   }
 
   /**
@@ -1089,7 +1104,8 @@ public class Database implements StorageObject {
    * @param wo Funktonsname, in der die SQLException geworfen wurde
    * @exception StorageObjectException
    */
-  protected void throwSQLException (SQLException sqe, String wo) throws StorageObjectException {
+  protected void throwSQLException (SQLException sqe, String wo)
+    throws StorageObjectException {
     String state = "";
     String message = "";
     int vendor = 0;
@@ -1104,7 +1120,8 @@ public class Database implements StorageObject {
         sqe.toString());
   }
 
-  protected void _throwStorageObjectException (Exception e, String wo) throws StorageObjectException {
+  protected void _throwStorageObjectException (Exception e, String wo)
+    throws StorageObjectException {
     if (e != null) {
         theLog.printError(e.toString()+ wo);
         throw  new StorageObjectException(wo + e.toString());
@@ -1116,14 +1133,16 @@ public class Database implements StorageObject {
   }
 
   /**
-   * Loggt Fehlermeldung mit dem Parameter Message und wirft dannach eine StorageObjectException
+   * Loggt Fehlermeldung mit dem Parameter Message und wirft dannach
+   * eine StorageObjectException
    * @param message Nachricht mit dem Fehler
    * @exception StorageObjectException
    */
-  void throwStorageObjectException (String message) throws StorageObjectException {
+  void throwStorageObjectException (String message)
+    throws StorageObjectException {
     _throwStorageObjectException(null, message);
   }
-  
+
 }