Coverage Report - org.apache.ojb.broker.platforms.PlatformDefaultImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PlatformDefaultImpl
N/A
N/A
2.517
 
 1  
 package org.apache.ojb.broker.platforms;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.io.StringReader;
 19  
 import java.sql.CallableStatement;
 20  
 import java.sql.Connection;
 21  
 import java.sql.DatabaseMetaData;
 22  
 import java.sql.PreparedStatement;
 23  
 import java.sql.ResultSet;
 24  
 import java.sql.SQLException;
 25  
 import java.sql.Statement;
 26  
 import java.sql.Types;
 27  
 import java.util.Properties;
 28  
 
 29  
 import org.apache.ojb.broker.PersistenceBrokerException;
 30  
 import org.apache.ojb.broker.accesslayer.JoinSyntaxTypes;
 31  
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 32  
 import org.apache.ojb.broker.query.LikeCriteria;
 33  
 import org.apache.ojb.broker.util.logging.Logger;
 34  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 35  
 
 36  
 /**
 37  
  * This class is a concrete implementation of <code>Platform</code>. Provides default implementations for all
 38  
  * methods declared in <code>Platform</code>.
 39  
  * It is intended as a vanilla implementation and as baseclass for
 40  
  * platform specific implementations.
 41  
  *
 42  
  * @version $Id: PlatformDefaultImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
 43  
  * @author                Thomas Mahler
 44  
  */
 45  
 public class PlatformDefaultImpl implements Platform, JoinSyntaxTypes
 46  
 {
 47  
     protected Logger log = LoggerFactory.getLogger(PlatformDefaultImpl.class);
 48  
     private static final String INITIALIZATION_CHECK_AUTOCOMMIT = "initializationCheck";
 49  
     private static final String FALSE_STR = "false";
 50  
 
 51  
     protected boolean m_batchUpdatesChecked = false;
 52  
     protected boolean m_supportsBatchUpdates = false;
 53  
 
 54  
     public boolean supportsBatchOperations()
 55  
     {
 56  
         return m_supportsBatchUpdates;
 57  
     }
 58  
 
 59  
     /**
 60  
      * Sets platform information for if the jdbc driver/db combo support
 61  
      * batch operations. Will only be checked once, then have same batch
 62  
      * support setting for the entire session.
 63  
      *
 64  
      * @param conn
 65  
      */
 66  
     protected void checkForBatchSupport(Connection conn)
 67  
     {
 68  
         if (!m_batchUpdatesChecked)
 69  
         {
 70  
             DatabaseMetaData meta;
 71  
             try
 72  
             {
 73  
                 meta = conn.getMetaData();
 74  
                 m_supportsBatchUpdates = meta.supportsBatchUpdates();
 75  
             }
 76  
             catch (Throwable th)
 77  
             {
 78  
                 log.info("Batch support check failed", th);
 79  
                 m_supportsBatchUpdates = false;
 80  
             }
 81  
             finally
 82  
             {
 83  
                 m_batchUpdatesChecked = true;
 84  
             }
 85  
         }
 86  
     }
 87  
 
 88  
     public void afterStatementCreate(Statement stmt) throws PlatformException
 89  
     {
 90  
         //noop
 91  
     }
 92  
 
 93  
     public void beforeStatementClose(Statement stmt, ResultSet rs) throws PlatformException
 94  
     {
 95  
         if (rs != null)
 96  
         {
 97  
             try
 98  
             {
 99  
                 rs.close();
 100  
             }
 101  
             catch (SQLException e)
 102  
             {
 103  
                 throw new PlatformException("Resultset closing failed", e);
 104  
             }
 105  
         }
 106  
     }
 107  
 
 108  
     public void afterStatementClose(Statement stmt, ResultSet rs) throws PlatformException
 109  
     {
 110  
         //nothing
 111  
     }
 112  
 
 113  
     public void beforeBatch(PreparedStatement stmt) throws PlatformException
 114  
     {
 115  
         // nothing
 116  
     }
 117  
 
 118  
     public void addBatch(PreparedStatement stmt) throws PlatformException
 119  
     {
 120  
         try
 121  
         {
 122  
             stmt.addBatch();
 123  
         }
 124  
         catch (SQLException e)
 125  
         {
 126  
             throw new PlatformException("Failure while calling 'addBatch' on given Statement object", e);
 127  
         }
 128  
     }
 129  
 
 130  
     public int[] executeBatch(PreparedStatement stmt) throws PlatformException
 131  
     {
 132  
         try
 133  
         {
 134  
             return stmt.executeBatch();
 135  
         }
 136  
         catch (SQLException e)
 137  
         {
 138  
             throw new PlatformException("Failure while calling 'executeBatch' on given Statement object", e);
 139  
         }
 140  
     }
 141  
 
 142  
 
 143  
     /**
 144  
      * @see Platform#initializeJdbcConnection
 145  
      */
 146  
     public void initializeJdbcConnection(JdbcConnectionDescriptor jcd, Connection conn) throws PlatformException
 147  
     {
 148  
         if (jcd.getBatchMode()) checkForBatchSupport(conn);
 149  
 
 150  
         switch (jcd.getUseAutoCommit())
 151  
         {
 152  
             case JdbcConnectionDescriptor.AUTO_COMMIT_IGNORE_STATE:
 153  
                 // nothing to do
 154  
                 break;
 155  
             case JdbcConnectionDescriptor.AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE:
 156  
                 try
 157  
                 {
 158  
                     /*
 159  
                     arminw:
 160  
                     workaround to be backward compatible. In future releases we shouldn't change the autocommit
 161  
                     state of a connection at initializing by the ConnectionFactory. The autocommit state should
 162  
                     only be changed by the ConnectionManager. We have to separate this stuff.
 163  
                     */
 164  
                     if (!jcd.getAttribute(INITIALIZATION_CHECK_AUTOCOMMIT, FALSE_STR).equalsIgnoreCase(FALSE_STR)
 165  
                             && !conn.getAutoCommit())
 166  
                     {
 167  
                         conn.setAutoCommit(true);
 168  
                     }
 169  
                 }
 170  
                 catch (SQLException e)
 171  
                 {
 172  
                     if (!jcd.isIgnoreAutoCommitExceptions())
 173  
                     {
 174  
                         throw new PlatformException("Connection initializing: setAutoCommit(true) failed", e);
 175  
                     }
 176  
                     else
 177  
                     {
 178  
                         log.info("Connection initializing: setAutoCommit jdbc-driver problems. " + e.getMessage());
 179  
                     }
 180  
                 }
 181  
                 break;
 182  
             case JdbcConnectionDescriptor.AUTO_COMMIT_SET_FALSE:
 183  
                 try
 184  
                 {
 185  
                     if (conn.getAutoCommit()) conn.setAutoCommit(false);
 186  
                 }
 187  
                 catch (SQLException e)
 188  
                 {
 189  
                     if (!jcd.isIgnoreAutoCommitExceptions())
 190  
                     {
 191  
                         throw new PlatformException("Connection initializing: setAutoCommit(false) failed", e);
 192  
                     }
 193  
                     else
 194  
                     {
 195  
                         log.info("Connection initializing: setAutoCommit jdbc-driver problems. " + e.getMessage());
 196  
                     }
 197  
                 }
 198  
                 break;
 199  
         }
 200  
     }
 201  
 
 202  
     public void changeAutoCommitState(JdbcConnectionDescriptor jcd, Connection con, boolean newState)
 203  
     {
 204  
         if (con == null)
 205  
         {
 206  
             log.error("Given m_connection was null, cannot prepare autoCommit state");
 207  
             return;
 208  
         }
 209  
         if (JdbcConnectionDescriptor.AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE == jcd.getUseAutoCommit())
 210  
         {
 211  
             try
 212  
             {
 213  
                 con.setAutoCommit(newState);
 214  
             }
 215  
             catch (SQLException e)
 216  
             {
 217  
                 if (jcd.isIgnoreAutoCommitExceptions())
 218  
                 {
 219  
                     log.info("Set autoCommit(" + newState + ") failed: " + e.getMessage());
 220  
                 }
 221  
                 else
 222  
                 {
 223  
                     log.error("Set autoCommit(" + newState + ") failed", e);
 224  
                     throw new PersistenceBrokerException("Set autoCommit(false) failed", e);
 225  
                 }
 226  
             }
 227  
         }
 228  
     }
 229  
 
 230  
     /*
 231  
      * @see Platform#setObject(PreparedStatement, int, Object, int)
 232  
      */
 233  
     public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType)
 234  
             throws SQLException
 235  
     {
 236  
         if ((sqlType == Types.LONGVARCHAR) && (value instanceof String))
 237  
         {
 238  
             String s = (String) value;
 239  
             ps.setCharacterStream(index, new StringReader(s), s.length());
 240  
         }
 241  
         /*
 242  
         PATCH for BigDecimal truncation problem. Seems that several databases (e.g. DB2, Sybase)
 243  
         has problem with BigDecimal fields if the sql-type was set. The problem was discussed here
 244  
         http://nagoya.apache.org/eyebrowse/ReadMsg?listName=ojb-user@db.apache.org&msgNo=14113
 245  
         A better option will be
 246  
         <snip>
 247  
         else if ((value instanceof BigDecimal) && (sqlType == Types.DECIMAL
 248  
                  || sqlType == Types.NUMERIC))
 249  
          {
 250  
              ps.setObject(index, value, sqlType,
 251  
                      ((BigDecimal) value).scale());
 252  
          }
 253  
          </snip>
 254  
         But this way maxDB/sapDB does not work correct, so we use the most flexible solution
 255  
         and let the jdbc-driver handle BigDecimal objects by itself.
 256  
         */
 257  
         else if(sqlType == Types.DECIMAL || sqlType == Types.NUMERIC)
 258  
         {
 259  
             ps.setObject(index, value);
 260  
         }
 261  
         else
 262  
         {
 263  
 // arminw: this method call is done very, very often, so we can improve performance
 264  
 // by comment out this section
 265  
 //            if (log.isDebugEnabled()) {
 266  
 //                log.debug("Default setObjectForStatement, sqlType=" + sqlType +
 267  
 //                          ", value class=" + (value == null ? "NULL!" : value.getClass().getName())
 268  
 //                            + ", value=" + value);
 269  
 //            }
 270  
             ps.setObject(index, value, sqlType);
 271  
         }
 272  
     }
 273  
 
 274  
     /*
 275  
      * @see Platform#setNullForStatement(PreparedStatement, int, int)
 276  
      */
 277  
     public void setNullForStatement(PreparedStatement ps, int index, int sqlType) throws SQLException
 278  
     {
 279  
         ps.setNull(index, sqlType);
 280  
     }
 281  
 
 282  
     /**
 283  
      * Get join syntax type for this RDBMS - one on of the constants from JoinSyntaxType interface
 284  
      *
 285  
      * @see Platform#getJoinSyntaxType
 286  
      */
 287  
     public byte getJoinSyntaxType()
 288  
     {
 289  
         return SQL92_JOIN_SYNTAX;
 290  
     }
 291  
 
 292  
     /**
 293  
      * Override default ResultSet size determination (rs.last();rs.getRow())
 294  
      * with select count(*) operation
 295  
      *
 296  
      * @see Platform#useCountForResultsetSize()
 297  
      */
 298  
     public boolean useCountForResultsetSize()
 299  
     {
 300  
         return false;
 301  
     }
 302  
 
 303  
     public String createSequenceQuery(String sequenceName, Properties prop)
 304  
     {
 305  
         return createSequenceQuery(sequenceName);
 306  
     }
 307  
 
 308  
     /**
 309  
      * Override this method to enable database based sequence generation
 310  
      */
 311  
     public String createSequenceQuery(String sequenceName)
 312  
     {
 313  
         /*default implementation does not support this*/
 314  
         throw new UnsupportedOperationException("This feature is not supported by this implementation");
 315  
     }
 316  
 
 317  
     /**
 318  
      * Override this method to enable database based sequence generation
 319  
      */
 320  
     public String nextSequenceQuery(String sequenceName)
 321  
     {
 322  
         /*default implementation does not support this*/
 323  
         throw new UnsupportedOperationException("This feature is not supported by this implementation");
 324  
     }
 325  
 
 326  
     /**
 327  
      * Override this method to enable database based sequence generation
 328  
      */
 329  
     public String dropSequenceQuery(String sequenceName)
 330  
     {
 331  
         /*default implementation does not support this*/
 332  
         throw new UnsupportedOperationException("This feature is not supported by this implementation");
 333  
     }
 334  
 
 335  
     public CallableStatement prepareNextValProcedureStatement(Connection con, String procedureName,
 336  
                                                               String sequenceName) throws PlatformException
 337  
     {
 338  
         /*@todo implementation*/
 339  
         throw new UnsupportedOperationException("Not supported by this implementation");
 340  
     }
 341  
 
 342  
     public String getLastInsertIdentityQuery(String tableName)
 343  
     {
 344  
         /*@todo implementation*/
 345  
         throw new UnsupportedOperationException("This feature is not supported by this implementation");
 346  
     }
 347  
 
 348  
     /**
 349  
      * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
 350  
      */
 351  
     public void addPagingSql(StringBuffer anSqlString)
 352  
     {
 353  
         // do nothing
 354  
     }
 355  
 
 356  
     /**
 357  
      * @see org.apache.ojb.broker.platforms.Platform#bindPagingParametersFirst()
 358  
      */
 359  
     public boolean bindPagingParametersFirst()
 360  
     {
 361  
         return false;
 362  
     }
 363  
 
 364  
     /**
 365  
      * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
 366  
      */
 367  
     public boolean supportsPaging()
 368  
     {
 369  
         return false;
 370  
     }
 371  
 
 372  
     /**
 373  
      * @see org.apache.ojb.broker.platforms.Platform#bindPagingParameters(java.sql.PreparedStatement, int, int, int)
 374  
      */
 375  
     public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException
 376  
     {
 377  
         ps.setInt(index, startAt - 1);              // zero based start
 378  
         index++;
 379  
         ps.setInt(index, endAt - (startAt - 1));    // number of rows to fetch
 380  
         index++;
 381  
         return index;
 382  
     }
 383  
 
 384  
     /**
 385  
      * Answer the Character for Concatenation
 386  
      */
 387  
     protected String getConcatenationCharacter()
 388  
     {
 389  
         return "||";
 390  
     }
 391  
 
 392  
     /**
 393  
      * {@inheritDoc}
 394  
      */
 395  
     public boolean supportsMultiColumnCountDistinct()
 396  
     {
 397  
         return true;
 398  
     }
 399  
 
 400  
     /**
 401  
      * @see org.apache.ojb.broker.platforms.Platform#concatenate(java.lang.String[])
 402  
      */
 403  
     public String concatenate(String[] theColumns)
 404  
     {
 405  
         if (theColumns.length == 1)
 406  
         {
 407  
             return theColumns[0];
 408  
         }
 409  
 
 410  
         StringBuffer buf = new StringBuffer();
 411  
         String concatChar = getConcatenationCharacter();
 412  
 
 413  
         for (int i = 0; i < theColumns.length; i++)
 414  
         {
 415  
             if (i > 0)
 416  
             {
 417  
                 buf.append(" ").append(concatChar).append(" ");
 418  
             }
 419  
             buf.append(theColumns[i]);
 420  
         }
 421  
 
 422  
         return buf.toString();
 423  
     }
 424  
 
 425  
     /**
 426  
      * @see org.apache.ojb.broker.platforms.Platform#getEscapeClause(org.apache.ojb.broker.query.LikeCriteria)
 427  
      */
 428  
     public String getEscapeClause(LikeCriteria aCriteria)
 429  
     {
 430  
         String value = (String) aCriteria.getValue();
 431  
         char escapeChar = LikeCriteria.getEscapeCharacter();
 432  
 
 433  
         if (value.indexOf(escapeChar) >= 0)
 434  
         {
 435  
             return " ESCAPE '" + escapeChar + "'";
 436  
         }
 437  
         else
 438  
         {
 439  
             return "";
 440  
         }
 441  
     }
 442  
 
 443  
     /**
 444  
      * @see org.apache.ojb.broker.platforms.Platform#registerOutResultSet(java.sql.CallableStatement, int)
 445  
      */
 446  
     public void registerOutResultSet(CallableStatement stmt, int position)
 447  
             throws SQLException
 448  
     {
 449  
         stmt.registerOutParameter(position, Types.OTHER);
 450  
     }
 451  
 }