Coverage Report - org.melati.poem.dbms.Oracle
 
Classes in this File Line Coverage Branch Coverage Complexity
Oracle
43%
29/66
44%
26/58
3.143
Oracle$OracleBooleanPoemType
0%
0/9
0%
0/6
3.143
Oracle$OracleStringPoemType
0%
0/9
0%
0/16
3.143
 
 1  
 /*
 2  
  * $Source$
 3  
  * $Revision$
 4  
  *
 5  
  * Copyright (C) 2004 Tim Pizey
 6  
  * 
 7  
  * Part of Melati (http://melati.org), a framework for the rapid
 8  
  * development of clean, maintainable web applications.
 9  
  *
 10  
  * Melati is free software; Permission is granted to copy, distribute
 11  
  * and/or modify this software under the terms either:
 12  
  *
 13  
  * a) the GNU General Public License as published by the Free Software
 14  
  *    Foundation; either version 2 of the License, or (at your option)
 15  
  *    any later version,
 16  
  *
 17  
  *    or
 18  
  *
 19  
  * b) any version of the Melati Software License, as published
 20  
  *    at http://melati.org
 21  
  *
 22  
  * You should have received a copy of the GNU General Public License and
 23  
  * the Melati Software License along with this program;
 24  
  * if not, write to the Free Software Foundation, Inc.,
 25  
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
 26  
  * GNU General Public License and visit http://melati.org to obtain the
 27  
  * Melati Software License.
 28  
  *
 29  
  * Feel free to contact the Developers of Melati (http://melati.org),
 30  
  * if you would like to work out a different arrangement than the options
 31  
  * outlined here.  It is our intention to allow Melati to be used by as
 32  
  * wide an audience as possible.
 33  
  *
 34  
  * This program is distributed in the hope that it will be useful,
 35  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 36  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 37  
  * GNU General Public License for more details.
 38  
  *
 39  
  * Contact details for copyright holder:
 40  
  *
 41  
  *     Tim Pizey (timp At paneris.org)
 42  
  *
 43  
  */
 44  
 
 45  
 package org.melati.poem.dbms;
 46  
 
 47  
 import java.sql.DatabaseMetaData;
 48  
 import java.sql.PreparedStatement;
 49  
 import java.sql.ResultSet;
 50  
 import java.sql.SQLException;
 51  
 
 52  
 import org.melati.poem.BigDecimalPoemType;
 53  
 import org.melati.poem.BinaryPoemType;
 54  
 import org.melati.poem.BooleanPoemType;
 55  
 import org.melati.poem.Column;
 56  
 import org.melati.poem.DoublePoemType;
 57  
 import org.melati.poem.IntegerPoemType;
 58  
 import org.melati.poem.LongPoemType;
 59  
 import org.melati.poem.PoemType;
 60  
 import org.melati.poem.SQLPoemType;
 61  
 import org.melati.poem.SQLType;
 62  
 import org.melati.poem.StringPoemType;
 63  
 
 64  
 /**
 65  
  * A Driver for Oracle (http://www.oracle.com/).
 66  
  * 
 67  
  * TODO Testing required, code has been added to keep up with the interface
 68  
  * without testing.
 69  
  * 
 70  
  **/
 71  
 public class Oracle extends AnsiStandard {
 72  
 
 73  
   /**
 74  
    * Oracle does not have a pleasant <code>TEXT</code> 
 75  
    * datatype, so we use an arbetary value in a 
 76  
    * <code>VARCHAR</code>.
 77  
    */
 78  0
   public static int oracleTextHack = 266;
 79  
 
 80  
   /**
 81  
    * Constructor.
 82  
    */
 83  1
   public Oracle() {
 84  1
     setDriverClassName("oracle.jdbc.OracleDriver");
 85  1
   }
 86  
 
 87  
   /**
 88  
    *  Get the user we are connected as and return that as the schema.
 89  
    * 
 90  
    * {@inheritDoc}
 91  
    * @see org.melati.poem.dbms.AnsiStandard#getSchema()
 92  
    * @see org.melati.poem.dbms.Dbms#getSchema()
 93  
    */
 94  
   public String getSchema() {
 95  1
     return schema;
 96  
   }
 97  
   
 98  
   /*
 99  
 
 100  
   public String preparedStatementPlaceholder(PoemType type) {
 101  
     if (type instanceof IntegerPoemType)
 102  
       return "CAST(? AS INT4)";
 103  
     else if (type instanceof LongPoemType)
 104  
       return "CAST(? AS INT8)";
 105  
     else if (type instanceof DoublePoemType)
 106  
       return "CAST(? AS FLOAT8)";
 107  
     else 
 108  
       return "?";
 109  
   }
 110  
 */
 111  
   
 112  
   /**
 113  
    * {@inheritDoc}
 114  
    * @see org.melati.poem.dbms.AnsiStandard#getStringSqlDefinition(int)
 115  
    */
 116  
   public String getStringSqlDefinition(int size) throws SQLException {
 117  2
     if (size < 0) { 
 118  1
        return "VARCHAR(" + oracleTextHack + ")";
 119  
     }
 120  1
        return super.getStringSqlDefinition(size);
 121  
   }
 122  
 
 123  
 
 124  
   /**
 125  
    * {@inheritDoc}
 126  
    * @see org.melati.poem.dbms.AnsiStandard#getLongSqlDefinition()
 127  
    */
 128  
   public String getLongSqlDefinition() {
 129  1
     return "NUMBER";
 130  
   }
 131  
 
 132  
   /**
 133  
    * {@inheritDoc}
 134  
    * @see org.melati.poem.dbms.AnsiStandard#getSqlDefinition(java.lang.String)
 135  
    */
 136  
   public String getSqlDefinition(String sqlTypeName) {
 137  4
     if (sqlTypeName.equals("BOOLEAN")) {
 138  1
       return ("CHAR(1)");
 139  
     }
 140  3
     return super.getSqlDefinition(sqlTypeName);
 141  
   }
 142  
 
 143  
   /**
 144  
    * {@inheritDoc}
 145  
    * @see org.melati.poem.dbms.AnsiStandard#sqlBooleanValueOfRaw(java.lang.Object)
 146  
    */
 147  
   public String sqlBooleanValueOfRaw(Object raw) {
 148  2
     if (((Boolean)raw).booleanValue()) 
 149  1
       return "1";
 150  
     else 
 151  1
       return "0";
 152  
   }
 153  
 
 154  
   /**
 155  
    * Translates an Oracle Boolean into a Poem <code>BooleanPoemType</code>.
 156  
    */
 157  0
   public static class OracleBooleanPoemType extends BooleanPoemType {
 158  
 
 159  
     /**
 160  
      * Constructor.
 161  
      * @param nullable nullability
 162  
      */
 163  
     public OracleBooleanPoemType(boolean nullable) {
 164  0
        super(nullable);
 165  0
      }
 166  
      
 167  
      protected Boolean _getRaw(ResultSet rs, int col) throws SQLException {
 168  0
        synchronized (rs) {
 169  0
          boolean v = rs.getBoolean(col);
 170  0
          return rs.wasNull() ? null : (v ? Boolean.TRUE : Boolean.FALSE);
 171  0
        }
 172  
      }
 173  
 
 174  
      protected void _setRaw(PreparedStatement ps, int col, Object bool) 
 175  
          throws SQLException {
 176  0
        ps.setInt(col, ((Boolean) bool).booleanValue() ? 1 : 0);
 177  0
      }
 178  
 
 179  
    }
 180  
 
 181  
    /**
 182  
     * Translates a Oracle String into a Poem <code>StringPoemType</code>.
 183  
     */ 
 184  
   public static class OracleStringPoemType extends StringPoemType {
 185  
 
 186  
     /**
 187  
      * Constructor.
 188  
      * @param nullable nullability
 189  
      * @param size size
 190  
      */
 191  
       public OracleStringPoemType(boolean nullable, int size) {
 192  0
         super(nullable, size);
 193  0
       }
 194  
 
 195  
       protected boolean _canRepresent(SQLPoemType<?> other) {
 196  0
         return sqlTypeCode() == other.sqlTypeCode() &&
 197  0
                (getSize() == oracleTextHack && 
 198  0
                ((StringPoemType)other).getSize() == -1)
 199  
                ||
 200  0
                (getSize() >= ((StringPoemType)other).getSize());
 201  
       }
 202  
 
 203  
       /**
 204  
        * {@inheritDoc}
 205  
        * @see org.melati.poem.BasePoemType#canRepresent(PoemType)
 206  
        */
 207  
       public <O>PoemType<O> canRepresent(PoemType<O> other) {
 208  0
         return other instanceof StringPoemType &&
 209  0
                _canRepresent((StringPoemType)other) &&
 210  0
                !(!getNullable() && ((StringPoemType)other).getNullable()) ?
 211  
                  other : null;
 212  
       }
 213  
 
 214  
     }
 215  
 
 216  
   /**
 217  
    * {@inheritDoc}
 218  
    * @see org.melati.poem.dbms.AnsiStandard#getBinarySqlDefinition(int)
 219  
    */
 220  
   public String getBinarySqlDefinition(int size) throws SQLException {
 221  1
     return "BLOB";
 222  
   }
 223  
 
 224  
   /**
 225  
    * {@inheritDoc}
 226  
    * @see org.melati.poem.dbms.AnsiStandard#unreservedName(java.lang.String)
 227  
    */
 228  
   public String unreservedName(String name) {
 229  28
     if(name.equalsIgnoreCase("user")) name = "melati_" + name;
 230  28
     if(name.equalsIgnoreCase("group")) name = "melati_" + name;
 231  28
     return name.toUpperCase();
 232  
   }
 233  
 
 234  
   /**
 235  
    * {@inheritDoc}
 236  
    * @see org.melati.poem.dbms.AnsiStandard#melatiName(java.lang.String)
 237  
    */
 238  
   public String melatiName(String name) {
 239  3
     if (name == null) return name;
 240  2
     if(name.equalsIgnoreCase("melati_user")) name = "user";
 241  2
     if(name.equalsIgnoreCase("melati_group")) name = "group";
 242  2
     return name.toLowerCase();
 243  
   }
 244  
 
 245  
   /**
 246  
    * An Object Id <code>PoemType</code>.
 247  
    */
 248  
   /*
 249  
 
 250  
   public static class BlobPoemType extends IntegerPoemType {
 251  
       public BlobPoemType(boolean nullable) {
 252  
           super(Types.INTEGER, "BLOB", nullable);
 253  
       }
 254  
 
 255  
       protected boolean _canRepresent(SQLPoemType other) {
 256  
           return other instanceof BinaryPoemType;
 257  
       }
 258  
 
 259  
       public PoemType canRepresent(PoemType other) {
 260  
           return other instanceof BinaryPoemType &&
 261  
                  !(!getNullable() && 
 262  
        ((BinaryPoemType)other).getNullable()) ? other : null;
 263  
       }
 264  
   }
 265  
 */
 266  
 
 267  
   /**
 268  
    * {@inheritDoc}
 269  
    * @see org.melati.poem.dbms.AnsiStandard#canRepresent
 270  
    *          (org.melati.poem.PoemType, org.melati.poem.PoemType)
 271  
    */
 272  
   public <S,O>PoemType<O> canRepresent(PoemType<S> storage, PoemType<O> type) {
 273  17
     if ((storage instanceof IntegerPoemType &&
 274  
         type instanceof BigDecimalPoemType) && 
 275  1
         !(!storage.getNullable() && type.getNullable())){
 276  1
       return type;
 277  
     }
 278  16
     if ((storage instanceof IntegerPoemType &&
 279  
           type instanceof LongPoemType) && 
 280  2
           !(!storage.getNullable() && type.getNullable())) {
 281  1
         return type;
 282  
     } else {
 283  15
       return storage.canRepresent(type);
 284  
     }
 285  
   }
 286  
 
 287  
   /**
 288  
    * {@inheritDoc}
 289  
    * @see org.melati.poem.dbms.AnsiStandard#defaultPoemTypeOfColumnMetaData
 290  
    */
 291  
   public SQLPoemType<?> defaultPoemTypeOfColumnMetaData(ResultSet md)
 292  
       throws SQLException {
 293  
 
 294  
     //ResultSetMetaData rsmd = md.getMetaData();
 295  
     //int cols = rsmd.getColumnCount();
 296  
     //for (int i = 1; i <= cols; i++) {
 297  
       //String table = rsmd.getTableName(i);
 298  
       //System.err.println("table name: " + table);
 299  
       //String column = rsmd.getColumnName(i);
 300  
       //System.err.println("column name: " + column);
 301  
       //int type = rsmd.getColumnType(i);
 302  
       //System.err.println("type: " + type);
 303  
       //String typeName = rsmd.getColumnTypeName(i);
 304  
       //System.err.println("type Name: " + typeName);
 305  
       //String className = rsmd.getColumnClassName(i);
 306  
       //System.err.println("class Name: " + className);
 307  
       //System.err.println("String val: " + md.getString(i));
 308  
       //System.err.println("");
 309  
     //}
 310  
 
 311  0
     if(md.getString("TYPE_NAME").equals("VARCHAR2"))
 312  0
       return 
 313  0
           new OracleStringPoemType(md.getInt("NULLABLE")==
 314  
                                       DatabaseMetaData.columnNullable, 
 315  0
                                   md.getInt("COLUMN_SIZE"));
 316  0
     if(md.getString("TYPE_NAME").equals("CHAR"))
 317  0
       return 
 318  0
           new OracleBooleanPoemType(md.getInt("NULLABLE")==
 319  
                                       DatabaseMetaData.columnNullable);
 320  0
     if(md.getString("TYPE_NAME").equals("BLOB"))
 321  0
       return new BinaryPoemType(
 322  0
                     md.getInt("NULLABLE") == DatabaseMetaData.columnNullable,
 323  0
                     md.getInt("COLUMN_SIZE"));
 324  0
     if(md.getString("TYPE_NAME").equals("FLOAT"))
 325  0
       return new DoublePoemType(
 326  0
                     md.getInt("NULLABLE") == DatabaseMetaData.columnNullable);
 327  0
     SQLPoemType<?> t = 
 328  0
       md.getString("TYPE_NAME").equals("NUMBER") ?
 329  0
           new IntegerPoemType(md.getInt("NULLABLE") ==
 330  
                               DatabaseMetaData.columnNullable) :
 331  0
           super.defaultPoemTypeOfColumnMetaData(md);
 332  
     //System.err.println("SQLType:"+t);
 333  0
     return t;
 334  
   }
 335  
   
 336  
   /**
 337  
    * {@inheritDoc}
 338  
    * @see org.melati.poem.dbms.AnsiStandard#getForeignKeyDefinition
 339  
    */
 340  
   public String getForeignKeyDefinition(String tableName, String fieldName, 
 341  
       String targetTableName, String targetTableFieldName, String fixName) {
 342  0
     StringBuffer sb = new StringBuffer();
 343  0
     sb.append(" ADD (CONSTRAINT FK_" + tableName + "_" + fieldName + 
 344  0
         ") FOREIGN KEY (" + getQuotedName(fieldName) + ") REFERENCES " + 
 345  0
         getQuotedName(targetTableName) + "(" + getQuotedName(targetTableFieldName) + ")");
 346  
     // Not currently implemented by Oracle, 
 347  
     // another reason for not using the DB to control these things
 348  
     //if (fixName.equals("prevent"))
 349  
     //  sb.append(" ON DELETE NO ACTION");
 350  0
     if (fixName.equals("delete"))
 351  0
       sb.append(" ON DELETE CASCADE");      
 352  0
     if (fixName.equals("clear"))
 353  0
       sb.append(" ON DELETE SET NULL");      
 354  0
     return sb.toString();
 355  
   }
 356  
 
 357  
   /**
 358  
    * {@inheritDoc}
 359  
    * @see org.melati.poem.dbms.AnsiStandard#getPrimaryKeyDefinition(java.lang.String)
 360  
    */
 361  
   public String getPrimaryKeyDefinition(String fieldName) {
 362  0
     StringBuffer sb = new StringBuffer();
 363  0
     sb.append(" ADD (CONSTRAINT PK_" + fieldName + 
 364  0
         " PRIMARY KEY(" + getQuotedName(fieldName) + "))");
 365  0
     return sb.toString();
 366  
   }
 367  
   
 368  
   /**
 369  
    * {@inheritDoc}
 370  
    * @see org.melati.poem.dbms.Dbms#booleanTrueExpression(org.melati.poem.Column)
 371  
    */
 372  
   public String booleanTrueExpression(Column<Boolean> booleanColumn) {
 373  0
     return booleanColumn.fullQuotedName() + "=1";
 374  
   }
 375  
 
 376  
   /**
 377  
    * {@inheritDoc}
 378  
    * @see org.melati.poem.dbms.AnsiStandard#getSqlDefaultValue(org.melati.poem.SQLType)
 379  
    */
 380  
   public String getSqlDefaultValue(SQLType<?> sqlType) {
 381  0
     if (sqlType instanceof BooleanPoemType) {
 382  0
       return ("0");
 383  
     }
 384  0
     return super.getSqlDefaultValue(sqlType);
 385  
   }
 386  
 
 387  
 }