Coverage Report - org.melati.poem.dbms.Hsqldb
 
Classes in this File Line Coverage Branch Coverage Complexity
Hsqldb
88%
56/63
62%
34/54
3.692
 
 1  
 /*
 2  
  * $Source$
 3  
  * $Revision$
 4  
  *
 5  
  * Copyright (C) 2002 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.Connection;
 48  
 import java.sql.Statement;
 49  
 import java.sql.SQLException;
 50  
 
 51  
 import org.melati.poem.BinaryPoemType;
 52  
 import org.melati.poem.Column;
 53  
 import org.melati.poem.PoemType;
 54  
 import org.melati.poem.StringPoemType;
 55  
 import org.melati.poem.Table;
 56  
 import org.melati.poem.util.StringUtils;
 57  
 
 58  
 /**
 59  
  * A Driver for HSQLDB (http://www.hsqldb.org/).
 60  
  *
 61  
  * Note that HSQLDB uppercases any name that isn't quoted. 
 62  
  *
 63  
  **/
 64  
 
 65  
 public class Hsqldb extends AnsiStandard {
 66  
 
 67  
   // 2010/10/25 Have experienced issues with records no being committed
 68  
   //       st.execute("SET WRITE_DELAY FALSE");
 69  
   // had no effect
 70  
 
 71  
   /**
 72  
    * HSQLDB does not have a pleasant <code>TEXT</code> 
 73  
    * datatype, so we use an arbitrary value in a 
 74  
    * <code>VARCHAR</code>.
 75  
    */
 76  1
   public static int hsqldbTextHack = 266;
 77  
   // Version 2.2.8 introduces a text field
 78  1
   public static int hsqldbTextSize1 = 1048576;
 79  1
   public static int hsqldbTextSize2 = 16777216;
 80  
 
 81  
   /**
 82  
    * Constructor.
 83  
    */
 84  4
   public Hsqldb() {
 85  4
     setDriverClassName("org.hsqldb.jdbcDriver");
 86  4
   }
 87  
 
 88  
   /**
 89  
    * Shut the db down nicely.
 90  
    */
 91  
   @Override
 92  
   public void shutdown(Connection connection)  throws SQLException { 
 93  18
     if (!connection.isClosed()) {
 94  18
       Statement st = connection.createStatement();
 95  
       try { 
 96  18
         st.execute("SHUTDOWN SCRIPT");
 97  0
       } catch (SQLException e) { 
 98  
         // This seems to be caused by a shutdownhook race
 99  0
         if (!e.getMessage().equals("Access is denied: Session is closed")) 
 100  0
           throw e;
 101  
       } finally { 
 102  18
         st.close();
 103  18
       }
 104  
     }
 105  18
   }
 106  
 
 107  
   /** 
 108  
    * The default is to keep everything in memory,
 109  
    * this allows for the db to be written to the disk.
 110  
    * 
 111  
    */
 112  
   @Override
 113  
   public String createTableTypeQualifierSql(Table<?> table) {
 114  
     String tableType;
 115  294
     if (table == null || table.getDbmsTableType() == null)
 116  294
       tableType = "CACHED ";
 117  
     else
 118  0
       tableType = table.getDbmsTableType() + " "; 
 119  
       
 120  294
     return tableType;
 121  
   }
 122  
 
 123  
   /*
 124  
    *  0.7.2 and earlier did not have a Boolean type; 
 125  
    *  there is one in 0.7.3 onwards. 
 126  
    *   
 127  
    * @see org.melati.poem.dbms.Dbms#getSqlDefinition(java.lang.String)
 128  
    */
 129  
 
 130  
   /*
 131  
    public String getSqlDefinition(String sqlTypeName) {
 132  
     if (sqlTypeName.equals("BOOLEAN")) {
 133  
       return ("BIT");
 134  
     }
 135  
     return super.getSqlDefinition(sqlTypeName);
 136  
   }
 137  
   */
 138  
   /**
 139  
    * @see org.melati.poem.dbms.AnsiStandard#getStringSqlDefinition(int)
 140  
    */
 141  
   @Override
 142  
   public String getStringSqlDefinition(int size) {
 143  701
     if (size < 0)
 144  346
       return "LONGVARCHAR";
 145  
       //return "VARCHAR(" + hsqldbTextHack + ")";
 146  355
     return "VARCHAR(" + size + ")";
 147  
   }
 148  
 
 149  
   /**
 150  
    * {@inheritDoc}
 151  
    * @see org.melati.poem.dbms.AnsiStandard#getLongSqlDefinition()
 152  
    */
 153  
   @Override
 154  
   public String getLongSqlDefinition() {
 155  17
     return "BIGINT";
 156  
   }
 157  
 
 158  
   /**
 159  
    * {@inheritDoc}
 160  
    * @see org.melati.poem.dbms.AnsiStandard#getBinarySqlDefinition(int)
 161  
    */
 162  
   @Override
 163  
   public String getBinarySqlDefinition(int size) throws SQLException {
 164  13
     return "LONGVARBINARY";
 165  
   }
 166  
 
 167  
   /**
 168  
    * Accommodate our String size hack. 
 169  
    * {@inheritDoc}
 170  
    * @see org.melati.poem.dbms.AnsiStandard#canRepresent
 171  
    */
 172  
   @Override
 173  
   public <S,O>PoemType<O> canRepresent(PoemType<S> storage, PoemType<O> type) {
 174  4254
     if (storage instanceof StringPoemType && type instanceof StringPoemType) {
 175  1058
       if (
 176  1058
           (((StringPoemType)storage).getSize() == hsqldbTextHack
 177  
           || 
 178  1058
           ((StringPoemType)storage).getSize() == hsqldbTextSize1
 179  
           || 
 180  1058
           ((StringPoemType)storage).getSize() == hsqldbTextSize2
 181  
           )
 182  0
               && ((StringPoemType)type).getSize() == -1
 183  0
               && !(!storage.getNullable() && type.getNullable())  // Nullable may represent not nullable
 184  
       ) {
 185  0
         return type;
 186  
       } else {
 187  1058
         return storage.canRepresent(type);
 188  
       }
 189  3196
     } else if (storage instanceof BinaryPoemType && type instanceof BinaryPoemType) {
 190  142
       if (
 191  
            (
 192  142
              (((BinaryPoemType)storage).getSize() == 0)
 193  
              || 
 194  2
              (((BinaryPoemType)storage).getSize() > ((BinaryPoemType)type).getSize())
 195  
            )
 196  
            && 
 197  140
            !(!storage.getNullable() && type.getNullable())  // Nullable may represent not nullable
 198  
       ) {
 199  140
         return type;
 200  
       } else {
 201  2
         return storage.canRepresent(type);
 202  
       }
 203  
     } else {
 204  3054
       return super.canRepresent(storage, type);
 205  
     }
 206  
   }
 207  
 
 208  
   /**
 209  
    * {@inheritDoc}
 210  
    * @see org.melati.poem.dbms.AnsiStandard#unreservedName(java.lang.String)
 211  
    */
 212  
   @Override
 213  
   public String unreservedName(String name) {
 214  13543
     if(name.equalsIgnoreCase("UNIQUE")) name = "MELATI_" + name.toUpperCase();
 215  13543
     if(name.equalsIgnoreCase("CONSTRAINT")) name = "MELATI_" + name.toUpperCase();
 216  
     //if(name.equalsIgnoreCase("USERS")) name = "MELATI_" + name.toUpperCase();
 217  13543
     return name.toUpperCase();
 218  
   }
 219  
 
 220  
   /**
 221  
    * {@inheritDoc}
 222  
    * @see org.melati.poem.dbms.AnsiStandard#melatiName(java.lang.String)
 223  
    */
 224  
   @Override
 225  
   public String melatiName(String name) {
 226  5418
     if (name == null) return name;
 227  5416
     if(name.equalsIgnoreCase("MELATI_UNIQUE")) name = "UNIQUE";
 228  5416
     if(name.equalsIgnoreCase("MELATI_CONSTRAINT")) name = "CONSTRAINT";
 229  
     //if(name.equalsIgnoreCase("MELATI_USERS")) name = "USERS";
 230  5416
     return name.toLowerCase();
 231  
   }
 232  
   
 233  
   /** 
 234  
    * Note that this is NOT case insensitive.
 235  
    * 
 236  
    * {@inheritDoc}
 237  
    * 
 238  
    * @see org.melati.poem.dbms.Dbms#caseInsensitiveRegExpSQL
 239  
    */
 240  
   @Override
 241  
   public String caseInsensitiveRegExpSQL(String term1, String term2) {
 242  33
     if (StringUtils.isQuoted(term2)) {
 243  23
       term2 = term2.substring(1, term2.length() - 1);
 244  
     } 
 245  33
     term2 = StringUtils.quoted(StringUtils.quoted(term2, '%'), '\'');
 246  
     
 247  33
     return term1 + " LIKE " + term2;
 248  
   }
 249  
   
 250  
   /**
 251  
    * {@inheritDoc}
 252  
    * @see org.melati.poem.dbms.AnsiStandard#getForeignKeyDefinition
 253  
    */
 254  
   @Override
 255  
   public String getForeignKeyDefinition(String tableName, String fieldName, 
 256  
                                         String targetTableName, 
 257  
                                         String targetTableFieldName, 
 258  
                                         String fixName) {
 259  176
     StringBuffer sb = new StringBuffer();
 260  352
     sb.append(" ADD FOREIGN KEY (" + getQuotedName(fieldName) + ") REFERENCES " + 
 261  176
               getQuotedName(targetTableName) + 
 262  176
               "(" + getQuotedName(targetTableFieldName) + ")");
 263  
     // Not currently implemented by hsqldb, 
 264  
     //another reason for not using the DB to control these things
 265  
     //if (fixName.equals("prevent"))
 266  
     //  sb.append(" ON DELETE NO ACTION");
 267  
     // There is an "ON DELETE SET DEFAULT" 
 268  
     
 269  176
     if (fixName.equals("delete"))
 270  19
       sb.append(" ON DELETE CASCADE");      
 271  176
     if (fixName.equals("clear"))
 272  70
       sb.append(" ON DELETE SET NULL");
 273  
     
 274  176
     return sb.toString();
 275  
   }
 276  
 
 277  
   /**
 278  
    * Bad smell.
 279  
    * {@inheritDoc}
 280  
    * @see org.melati.poem.dbms.AnsiStandard#getJdbcMetadataName(java.lang.String)
 281  
    */
 282  
   @Override
 283  
   public String getJdbcMetadataName(String name) {
 284  731
     return name.toUpperCase();
 285  
   }
 286  
   /**
 287  
    * Our current version does not honour COMMENT. 
 288  
    */
 289  
    @Override
 290  
    public String alterColumnAddCommentSQL(Column<?> column, String comment) {
 291  2808
      return null;
 292  
    }
 293  
 
 294  
 }