View Javadoc

1   /*
2    * org.riverock.dbrevision - Database revision engine
3    * For more information about DbRevision, please visit project site
4    * http://www.riverock.org
5    *
6    * Copyright (C) 2006-2006, Riverock Software, All Rights Reserved.
7    *
8    * Riverock - The Open-source Java Development Community
9    * http://www.riverock.org
10   *
11   *
12   * This library is free software; you can redistribute it and/or
13   * modify it under the terms of the GNU Lesser General Public
14   * License as published by the Free Software Foundation; either
15   * version 2.1 of the License, or (at your option) any later version.
16   *
17   * This library is distributed in the hope that it will be useful,
18   * but WITHOUT ANY WARRANTY; without even the implied warranty of
19   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20   * Lesser General Public License for more details.
21   *
22   * You should have received a copy of the GNU Lesser General Public
23   * License along with this library; if not, write to the Free Software
24   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25   */
26  package org.riverock.dbrevision.db.impl;
27  
28  import java.io.ByteArrayOutputStream;
29  import java.io.InputStream;
30  import java.sql.Blob;
31  import java.sql.Connection;
32  import java.sql.DatabaseMetaData;
33  import java.sql.PreparedStatement;
34  import java.sql.ResultSet;
35  import java.sql.SQLException;
36  import java.sql.Statement;
37  import java.sql.Types;
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  import org.apache.commons.lang.StringUtils;
42  import org.apache.log4j.Logger;
43  
44  import org.riverock.dbrevision.annotation.schema.db.DbDataFieldData;
45  import org.riverock.dbrevision.annotation.schema.db.DbField;
46  import org.riverock.dbrevision.annotation.schema.db.DbForeignKey;
47  import org.riverock.dbrevision.annotation.schema.db.DbPrimaryKey;
48  import org.riverock.dbrevision.annotation.schema.db.DbPrimaryKeyColumn;
49  import org.riverock.dbrevision.annotation.schema.db.DbSequence;
50  import org.riverock.dbrevision.annotation.schema.db.DbTable;
51  import org.riverock.dbrevision.annotation.schema.db.DbView;
52  import org.riverock.dbrevision.db.Database;
53  import org.riverock.dbrevision.db.DatabaseManager;
54  import org.riverock.dbrevision.exception.DbRevisionException;
55  import org.riverock.dbrevision.utils.DbUtils;
56  
57  /**
58   *
59   * $Author: serg_main $
60   *
61   * $Id: HyperSonicDatabase.java 1141 2006-12-14 14:43:29Z serg_main $
62   *
63   */
64  @SuppressWarnings({"UnusedAssignment"})
65  public class HyperSonicDatabase extends Database {
66      private static Logger log = Logger.getLogger( HyperSonicDatabase.class );
67  
68      /**
69       * get family for this adapter
70       * @return family
71       */
72      public Family getFamily() {
73          return Family.HYPERSONIC;
74      }
75  
76      public void setBlobField(String tableName, String fieldName, byte[] bytes, String whereQuery, Object[] objects, int[] fieldTyped) {
77      }
78  
79      public HyperSonicDatabase(Connection conn) {
80          super(conn);
81      }
82  
83      public int getMaxLengthStringField() {
84          return 1000000;
85      }
86  
87      public boolean isBatchUpdate() {
88          return false;
89      }
90  
91      public boolean isNeedUpdateBracket() {
92          return true;
93      }
94  
95      public boolean isByteArrayInUtf8() {
96          return false;
97      }
98  
99      public boolean isSchemaSupports() {
100         return false;
101     }
102 
103     public String getDefaultSchemaName(DatabaseMetaData databaseMetaData) {
104         // hypersonic 1.8.x correctly work only with default schema 'PUBLIC'
105         return "PUBLIC";
106     }
107 
108     public String getClobField(ResultSet rs, String nameField) {
109         return getClobField(rs, nameField, 20000);
110     }
111 
112     public byte[] getBlobField(ResultSet rs, String nameField, int maxLength) {
113         try {
114             Blob blob = rs.getBlob(nameField);
115             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
116             int count;
117             byte buffer[] = new byte[1024];
118 
119             InputStream inputStream = blob.getBinaryStream();
120             while ((count = inputStream.read(buffer)) >= 0) {
121                 outputStream.write(buffer, 0, count);
122                 outputStream.flush();
123             }
124             outputStream.close();
125             return outputStream.toByteArray();
126         }
127         catch (Exception e) {
128             throw new DbRevisionException(e);
129         }
130     }
131 
132     public void createTable(DbTable table) {
133         if (table == null || table.getFields().isEmpty()) {
134             return;
135         }
136 
137         String sql = "create table \"" + table.getName() + "\"\n" +
138             "(";
139 
140         try {
141         boolean isFirst = true;
142 
143         for (DbField field : table.getFields()) {
144             if (!isFirst) {
145                 sql += ",";
146             }
147             else {
148                 isFirst = !isFirst;
149             }
150 
151             sql += "\n" + field.getName() + "";
152             int fieldType = field.getJavaType();
153             switch (fieldType) {
154 
155                 case Types.NUMERIC:
156                 case Types.DECIMAL:
157                     sql += " DECIMAL";
158                     break;
159 
160                 case Types.INTEGER:
161                     sql += " INTEGER";
162                     break;
163 
164                 case Types.DOUBLE:
165                     sql += " DOUBLE";
166                     break;
167 
168                 case Types.CHAR:
169                 case Types.VARCHAR:
170                     sql += " VARCHAR";
171                     break;
172 
173                 case Types.DATE:
174                 case Types.TIMESTAMP:
175                     sql += " TIMESTAMP";
176                     break;
177 
178                 case Types.LONGVARCHAR:
179                     // Oracle 'long' fields type
180                     sql += " LONGVARCHAR";
181                     break;
182 
183                 case Types.LONGVARBINARY:
184                 case Types.BLOB:
185                     // Oracle 'long raw' fields type
186                     sql += " LONGVARBINARY";
187                     break;
188 
189                 case Types.CLOB:
190                     sql += " LONGVARCHAR";
191                     break;
192 
193                 default:
194                     field.setJavaStringType("unknown field type field - " + field.getName() + " javaType - " + field.getJavaType());
195                     System.out.println("unknown field type field - " + field.getName() + " javaType - " + field.getJavaType());
196             }
197 
198             if (field.getDefaultValue() != null) {
199                 String val = field.getDefaultValue().trim();
200 
201                 if (StringUtils.isNotBlank(val)) {
202                     switch (fieldType) {
203                         case Types.CHAR:
204                         case Types.VARCHAR:
205                             val = "'" + val + "'";
206                             break;
207                         case Types.TIMESTAMP:
208                         case Types.DATE:
209                             if (DatabaseManager.checkDefaultTimestamp(val)) {
210                                 val = "'CURRENT_TIMESTAMP'";
211                             }
212 
213                             break;
214                         default:
215                     }
216                     sql += (" DEFAULT " + val);
217                 }
218             }
219 
220             if (field.getNullable() == DatabaseMetaData.columnNoNulls) {
221                 sql += " NOT NULL ";
222             }
223         }
224         if (table.getPrimaryKey() != null && table.getPrimaryKey().getColumns().size() > 0) {
225             DbPrimaryKey pk = table.getPrimaryKey();
226 
227             //            constraintDefinition:
228 //            [ CONSTRAINT name ]
229 //            UNIQUE ( column [,column...] ) |
230 //            PRIMARY KEY ( column [,column...] ) |
231 
232             sql += ",\nCONSTRAINT " + pk.getPkName() + " PRIMARY KEY (\n";
233 
234             int seq = Integer.MIN_VALUE;
235             isFirst = true;
236             for (DbPrimaryKeyColumn column : pk.getColumns()) {
237                 int seqTemp = Integer.MAX_VALUE;
238                 for (DbPrimaryKeyColumn columnTemp : pk.getColumns()) {
239                     if (seq < columnTemp.getKeySeq() && columnTemp.getKeySeq() < seqTemp) {
240                         seqTemp = columnTemp.getKeySeq();
241                         column = columnTemp;
242                     }
243                 }
244                 seq = column.getKeySeq();
245 
246                 if (!isFirst) {
247                     sql += ",";
248                 }
249                 else {
250                     isFirst = !isFirst;
251                 }
252 
253                 sql += column.getColumnName();
254             }
255             sql += "\n)";
256         }
257         sql += "\n)";
258 
259         Statement ps = null;
260             try {
261                 ps = this.getConnection().createStatement();
262                 ps.execute(sql);
263             }
264             finally {
265                 DbUtils.close(ps);
266                 ps = null;
267             }
268         }
269         catch (Exception e) {
270             log.error("sql: " + sql);
271             throw new DbRevisionException(e);
272         }
273 
274     }
275 
276     public void createForeignKey(DbTable view) {
277     }
278 
279     public void dropTable(DbTable table) {
280         dropTable(table.getName());
281     }
282 
283     public void dropTable(String nameTable) {
284         if (nameTable == null) {
285             return;
286         }
287         String sql = "drop table \"" + nameTable + "\"\n";
288         PreparedStatement ps = null;
289         try {
290             ps = this.getConnection().prepareStatement(sql);
291             ps.executeUpdate();
292         }
293         catch (SQLException e) {
294             throw new DbRevisionException(e);
295         }
296         finally {
297             DbUtils.close(ps);
298             ps = null;
299         }
300     }
301 
302     public void dropSequence(String nameSequence) {
303     }
304 
305     public void dropConstraint(DbForeignKey impPk) {
306         if (impPk == null)
307             return;
308 
309         String sql = "ALTER TABLE " + impPk.getPkTableName() + " DROP CONSTRAINT " + impPk.getPkName();
310 
311         PreparedStatement ps = null;
312         try {
313             ps = this.getConnection().prepareStatement(sql);
314             ps.executeUpdate();
315         }
316         catch (SQLException e) {
317             throw new DbRevisionException(e);
318         }
319         finally {
320             DbUtils.close(ps);
321             ps = null;
322         }
323     }
324 
325     public void addColumn(DbTable table, DbField field) {
326         String sql = "alter table \"" + table.getName() + "\" add column " + field.getName() + " ";
327 
328         int fieldType = field.getJavaType();
329         switch (fieldType) {
330 
331             case Types.NUMERIC:
332             case Types.DECIMAL:
333                 sql += " DECIMAL";
334                 break;
335 
336             case Types.INTEGER:
337                 sql += " INTEGER";
338                 break;
339 
340             case Types.DOUBLE:
341                 sql += " DOUBLE";
342                 break;
343 
344             case Types.CHAR:
345             case Types.VARCHAR:
346                 sql += " VARCHAR";
347                 break;
348 
349             case Types.TIMESTAMP:
350             case Types.DATE:
351                 sql += " TIMESTAMP";
352                 break;
353 
354             case Types.LONGVARCHAR:
355                 // Oracle 'long' fields type
356                 sql += " LONGVARCHAR";
357                 break;
358 
359             case Types.LONGVARBINARY:
360                 // Oracle 'long raw' fields type
361                 sql += " LONGVARBINARY";
362                 break;
363 
364             default:
365                 String errorString = "unknown field type field - " + field.getName() + " javaType - " + field.getJavaType();
366                 log.error(errorString);
367                 throw new DbRevisionException(errorString);
368         }
369 
370         if (field.getDefaultValue() != null) {
371             String val = field.getDefaultValue().trim();
372 
373             if (StringUtils.isNotBlank(val)) {
374                 switch (fieldType) {
375                     case Types.CHAR:
376                     case Types.VARCHAR:
377                         val = "'" + val + "'";
378                         break;
379                     case Types.TIMESTAMP:
380                     case Types.DATE:
381 //                            if (DatabaseManager.checkDefaultTimestamp(val))
382 //                                val = "'CURRENT_TIMESTAMP'";
383 
384                         break;
385                     default:
386                 }
387                 sql += (" DEFAULT " + val);
388             }
389         }
390 
391         if (field.getNullable() == DatabaseMetaData.columnNoNulls) {
392             sql += " NOT NULL ";
393         }
394 
395 
396         if (log.isDebugEnabled())
397             log.debug("addColumn sql - \n" + sql);
398 
399         PreparedStatement ps = null;
400         try {
401             ps = this.getConnection().prepareStatement(sql);
402             ps.executeUpdate();
403         }
404         catch (SQLException e) {
405             throw new DbRevisionException(e);
406         }
407         finally {
408             DbUtils.close(ps);
409             ps = null;
410         }
411     }
412 
413     public String getOnDeleteSetNull() {
414         return "";
415     }
416 
417     public String getDefaultTimestampValue() {
418         return "current_timestamp";
419     }
420 
421     public List<DbView> getViewList(String schemaPattern, String tablePattern) {
422         return DatabaseManager.getViewList(getConnection(), schemaPattern, tablePattern);
423     }
424 
425     public List<DbSequence> getSequnceList(String schemaPattern) {
426         return new ArrayList<DbSequence>();
427     }
428 
429     public String getViewText(DbView view) {
430         return null;
431     }
432 
433     public void createView(DbView view) {
434         if (view == null ||
435             view.getName() == null || view.getName().length() == 0 ||
436             view.getText() == null || view.getText().length() == 0
437         )
438             return;
439 
440         String sql_ = "create VIEW " + view.getName() + " as " + view.getText();
441         PreparedStatement ps = null;
442         try {
443             ps = this.getConnection().prepareStatement(sql_);
444             ps.executeUpdate();
445         }
446         catch (SQLException e) {
447             throw new DbRevisionException(e);
448         } finally {
449             DbUtils.close(ps);
450             ps = null;
451         }
452     }
453 
454     public void createSequence(DbSequence seq) {
455     }
456 
457     public void setLongVarbinary(PreparedStatement ps, int index, DbDataFieldData fieldData) {
458         try {
459             ps.setNull(index, Types.LONGVARBINARY);
460         }
461         catch (SQLException e) {
462             throw new DbRevisionException(e);
463         }
464     }
465 
466     public void setLongVarchar(PreparedStatement ps, int index, DbDataFieldData fieldData) {
467         try {
468             ps.setNull(index, Types.LONGVARCHAR);
469         }
470         catch (SQLException e) {
471             throw new DbRevisionException(e);
472         }
473     }
474 
475     public String getClobField(ResultSet rs, String nameField, int maxLength) {
476         return null;
477     }
478 /*
479             CLOB clob = ((OracleResultSet) rs).getCLOB(nameField);
480 
481             if (clob == null)
482                 return null;
483 
484             return clob.getSubString(1, maxLength);
485         }
486 */
487 
488     public boolean testExceptionTableNotFound(Exception e) {
489         if (e == null)
490             return false;
491 
492         if (e instanceof SQLException) {
493             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.TABLE_NOT_FOUND))
494                 return true;
495         }
496         return false;
497     }
498 
499     public boolean testExceptionIndexUniqueKey(Exception e, String index) {
500         if (e == null)
501             return false;
502 
503         if (e instanceof SQLException) {
504             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.VIOLATION_OF_UNIQUE_INDEX) &&
505                 (e.toString().indexOf(index) != -1))
506                 return true;
507         }
508         return false;
509     }
510 
511     public boolean testExceptionIndexUniqueKey(Exception e) {
512         if (e == null)
513             return false;
514 
515         if (e instanceof SQLException) {
516             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.VIOLATION_OF_UNIQUE_INDEX))
517                 return true;
518         }
519         return false;
520     }
521 
522     public boolean testExceptionTableExists(Exception e) {
523         if (e == null)
524             return false;
525 
526         if (e instanceof SQLException) {
527             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.TABLE_ALREADY_EXISTS))
528                 return true;
529         }
530         return false;
531     }
532 
533     public boolean testExceptionViewExists(Exception e) {
534         if (e == null)
535             return false;
536 
537         if (e instanceof SQLException) {
538             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.VIEW_ALREADY_EXISTS))
539                 return true;
540         }
541         return false;
542     }
543 
544     public boolean testExceptionSequenceExists(Exception e) {
545         return false;
546     }
547 
548     public boolean testExceptionConstraintExists(Exception e) {
549         if (e == null)
550             return false;
551 
552         if (e instanceof SQLException) {
553             if (((SQLException) e).getErrorCode() == -(org.hsqldb.Trace.CONSTRAINT_ALREADY_EXISTS))
554                 return true;
555         }
556         return false;
557     }
558 }