1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools.sql;
24  
25  import com.liferay.portal.kernel.dao.jdbc.DataAccess;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.util.FileUtil;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.StringPool;
31  import com.liferay.portal.kernel.util.StringUtil;
32  import com.liferay.portal.util.PropsValues;
33  import com.liferay.portal.velocity.VelocityUtil;
34  import com.liferay.util.SimpleCounter;
35  
36  import java.io.BufferedReader;
37  import java.io.File;
38  import java.io.FileReader;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.io.StringReader;
42  
43  import java.sql.Connection;
44  import java.sql.SQLException;
45  import java.sql.Statement;
46  
47  import java.util.HashMap;
48  import java.util.Map;
49  
50  import javax.naming.NamingException;
51  
52  import org.hibernate.dialect.DB2Dialect;
53  import org.hibernate.dialect.DerbyDialect;
54  import org.hibernate.dialect.Dialect;
55  import org.hibernate.dialect.FirebirdDialect;
56  import org.hibernate.dialect.HSQLDialect;
57  import org.hibernate.dialect.InformixDialect;
58  import org.hibernate.dialect.IngresDialect;
59  import org.hibernate.dialect.InterbaseDialect;
60  import org.hibernate.dialect.JDataStoreDialect;
61  import org.hibernate.dialect.MySQLDialect;
62  import org.hibernate.dialect.Oracle10gDialect;
63  import org.hibernate.dialect.Oracle8iDialect;
64  import org.hibernate.dialect.Oracle9Dialect;
65  import org.hibernate.dialect.Oracle9iDialect;
66  import org.hibernate.dialect.OracleDialect;
67  import org.hibernate.dialect.PostgreSQLDialect;
68  import org.hibernate.dialect.SAPDBDialect;
69  import org.hibernate.dialect.SQLServerDialect;
70  import org.hibernate.dialect.SybaseDialect;
71  
72  /**
73   * <a href="DBUtil.java.html"><b><i>View Source</i></b></a>
74   *
75   * @author Alexander Chow
76   * @author Ganesh Ram
77   */
78  public abstract class DBUtil implements DB {
79  
80      public static final int MINIMAL = 1;
81  
82      public static final int POPULATED = 0;
83  
84      public static final int SHARDED = 2;
85  
86      public static final String TYPE_DB2 = "db2";
87  
88      public static final String TYPE_DERBY = "derby";
89  
90      public static final String TYPE_FIREBIRD = "firebird";
91  
92      public static final String TYPE_HYPERSONIC = "hypersonic";
93  
94      public static final String TYPE_INFORMIX = "informix";
95  
96      public static final String TYPE_INGRES = "ingres";
97  
98      public static final String TYPE_INTERBASE = "interbase";
99  
100     public static final String TYPE_JDATASTORE = "jdatastore";
101 
102     public static final String TYPE_MYSQL = "mysql";
103 
104     public static final String TYPE_ORACLE = "oracle";
105 
106     public static final String TYPE_POSTGRESQL = "postgresql";
107 
108     public static final String TYPE_SAP = "sap";
109 
110     public static final String TYPE_SQLSERVER = "sqlserver";
111 
112     public static final String TYPE_SYBASE = "sybase";
113 
114     public static final String[] TYPE_ALL = {
115         TYPE_DB2, TYPE_DERBY, TYPE_FIREBIRD, TYPE_HYPERSONIC, TYPE_INFORMIX,
116         TYPE_INGRES, TYPE_INTERBASE, TYPE_JDATASTORE, TYPE_MYSQL, TYPE_ORACLE,
117         TYPE_POSTGRESQL, TYPE_SAP, TYPE_SQLSERVER, TYPE_SYBASE
118     };
119 
120     public static DBUtil getInstance() {
121         if (_dbUtil == null) {
122             try {
123                 if (_log.isInfoEnabled()) {
124                     _log.info("Using dialect " + PropsValues.HIBERNATE_DIALECT);
125                 }
126 
127                 Dialect dialect = (Dialect)Class.forName(
128                     PropsValues.HIBERNATE_DIALECT).newInstance();
129 
130                 setInstance(dialect);
131             }
132             catch (Exception e) {
133                 _log.error(e, e);
134             }
135         }
136 
137         return _dbUtil;
138     }
139 
140     public static DBUtil getInstance(String type) {
141         DBUtil dbUtil = null;
142 
143         if (type.equals(TYPE_DB2)) {
144             dbUtil = DB2Util.getInstance();
145         }
146         else if (type.equals(TYPE_DERBY)) {
147             dbUtil = DerbyUtil.getInstance();
148         }
149         else if (type.equals(TYPE_FIREBIRD)) {
150             dbUtil = FirebirdUtil.getInstance();
151         }
152         else if (type.equals(TYPE_HYPERSONIC)) {
153             dbUtil = HypersonicUtil.getInstance();
154         }
155         else if (type.equals(TYPE_INFORMIX)) {
156             dbUtil = InformixUtil.getInstance();
157         }
158         else if (type.equals(TYPE_INGRES)) {
159             dbUtil = IngresUtil.getInstance();
160         }
161         else if (type.equals(TYPE_INTERBASE)) {
162             dbUtil = InterBaseUtil.getInstance();
163         }
164         else if (type.equals(TYPE_JDATASTORE)) {
165             dbUtil = JDataStoreUtil.getInstance();
166         }
167         else if (type.equals(TYPE_MYSQL)) {
168             dbUtil = MySQLUtil.getInstance();
169         }
170         else if (type.equals(TYPE_ORACLE)) {
171             dbUtil = OracleUtil.getInstance();
172         }
173         else if (type.equals(TYPE_POSTGRESQL)) {
174             dbUtil = PostgreSQLUtil.getInstance();
175         }
176         else if (type.equals(TYPE_SAP)) {
177             dbUtil = SAPUtil.getInstance();
178         }
179         else if (type.equals(TYPE_SQLSERVER)) {
180             dbUtil = SQLServerUtil.getInstance();
181         }
182         else if (type.equals(TYPE_SYBASE)) {
183             dbUtil = SybaseUtil.getInstance();
184         }
185 
186         return dbUtil;
187     }
188 
189     public static void setInstance(Dialect dialect) {
190         if (_dbUtil != null) {
191             return;
192         }
193 
194         if (dialect instanceof DB2Dialect) {
195             if (dialect instanceof DerbyDialect) {
196                 _dbUtil = DerbyUtil.getInstance();
197             }
198             else {
199                 _dbUtil = DB2Util.getInstance();
200             }
201         }
202         else if (dialect instanceof HSQLDialect) {
203             _dbUtil = HypersonicUtil.getInstance();
204         }
205         else if (dialect instanceof InformixDialect) {
206             _dbUtil = InformixUtil.getInstance();
207         }
208         else if (dialect instanceof IngresDialect) {
209             _dbUtil = IngresUtil.getInstance();
210         }
211         else if (dialect instanceof InterbaseDialect) {
212             if (dialect instanceof FirebirdDialect) {
213                 _dbUtil = FirebirdUtil.getInstance();
214             }
215             else {
216                 _dbUtil = InterBaseUtil.getInstance();
217             }
218         }
219         else if (dialect instanceof JDataStoreDialect) {
220             _dbUtil = JDataStoreUtil.getInstance();
221         }
222         else if (dialect instanceof MySQLDialect) {
223             _dbUtil = MySQLUtil.getInstance();
224         }
225         else if (dialect instanceof OracleDialect ||
226                  dialect instanceof Oracle8iDialect ||
227                  dialect instanceof Oracle9Dialect ||
228                  dialect instanceof Oracle9iDialect ||
229                  dialect instanceof Oracle10gDialect) {
230 
231             _dbUtil = OracleUtil.getInstance();
232         }
233         else if (dialect instanceof PostgreSQLDialect) {
234             _dbUtil = PostgreSQLUtil.getInstance();
235         }
236         else if (dialect instanceof SAPDBDialect) {
237             _dbUtil = SAPUtil.getInstance();
238         }
239         else if (dialect instanceof SybaseDialect) {
240             if (dialect instanceof SQLServerDialect) {
241                 _dbUtil = SQLServerUtil.getInstance();
242             }
243             else {
244                 _dbUtil = SybaseUtil.getInstance();
245             }
246         }
247     }
248 
249     public void buildCreateFile(String databaseName) throws IOException {
250         buildCreateFile(databaseName, POPULATED);
251         buildCreateFile(databaseName, MINIMAL);
252         buildCreateFile(databaseName, SHARDED);
253     }
254 
255     public void buildCreateFile(String databaseName, int population)
256         throws IOException {
257 
258         String suffix = getSuffix(population);
259 
260         File file = new File(
261             "../sql/create" + suffix + "/create" + suffix + "-" +
262                 getServerName() + ".sql");
263 
264         if (population != SHARDED) {
265             String content = buildCreateFileContent(databaseName, population);
266 
267             if (content != null) {
268                 FileUtil.write(file, content);
269             }
270         }
271         else {
272             String content = buildCreateFileContent(databaseName, MINIMAL);
273 
274             if (content != null) {
275                 FileUtil.write(file, content);
276             }
277 
278             content = buildCreateFileContent(databaseName + "1", MINIMAL);
279 
280             if (content != null) {
281                 FileUtil.write(file, content, false, true);
282             }
283 
284             content = buildCreateFileContent(databaseName + "2", MINIMAL);
285 
286             if (content != null) {
287                 FileUtil.write(file, content, false, true);
288             }
289         }
290     }
291 
292     public abstract String buildSQL(String template) throws IOException;
293 
294     public void buildSQLFile(String fileName) throws IOException {
295         String template = buildTemplate(fileName);
296 
297         template = buildSQL(template);
298 
299         FileUtil.write(
300             "../sql/" + fileName + "/" + fileName + "-" + getServerName() +
301                 ".sql",
302             template);
303     }
304 
305     public String getTemplateFalse() {
306         return getTemplate()[2];
307     }
308 
309     public String getTemplateTrue() {
310         return getTemplate()[1];
311     }
312 
313     public String getType() {
314         return _type;
315     }
316 
317     public boolean isSupportsAlterColumnName() {
318         return _SUPPORTS_ALTER_COLUMN_NAME;
319     }
320 
321     public boolean isSupportsAlterColumnType() {
322         return _SUPPORTS_ALTER_COLUMN_TYPE;
323     }
324 
325     public boolean isSupportsDateMilliseconds() {
326         return _SUPPORTS_DATE_MILLISECONDS;
327     }
328 
329     public boolean isSupportsStringCaseSensitiveQuery() {
330         return _supportsStringCaseSensitiveQuery;
331     }
332 
333     public boolean isSupportsUpdateWithInnerJoin() {
334         return _SUPPORTS_UPDATE_WITH_INNER_JOIN;
335     }
336 
337     public void runSQL(String sql) throws IOException, SQLException {
338         runSQL(new String[] {sql});
339     }
340 
341     public void runSQL(Connection con, String sql)
342         throws IOException, SQLException {
343 
344         runSQL(con, new String[] {sql});
345     }
346 
347     public void runSQL(String[] sqls) throws IOException, SQLException {
348         Connection con = DataAccess.getConnection();
349 
350         try {
351             runSQL(con, sqls);
352         }
353         finally {
354             DataAccess.cleanUp(con);
355         }
356     }
357 
358     public void runSQL(Connection con, String[] sqls)
359         throws IOException, SQLException {
360 
361         Statement s = null;
362 
363         try {
364             s = con.createStatement();
365 
366             for (int i = 0; i < sqls.length; i++) {
367                 String sql = buildSQL(sqls[i]);
368 
369                 sql = sql.trim();
370 
371                 if (sql.endsWith(";")) {
372                     sql = sql.substring(0, sql.length() - 1);
373                 }
374 
375                 if (sql.endsWith("go")) {
376                     sql = sql.substring(0, sql.length() - 2);
377                 }
378 
379                 if (_log.isDebugEnabled()) {
380                     _log.debug(sql);
381                 }
382 
383                 try {
384                     s.executeUpdate(sql);
385                 }
386                 catch (SQLException sqle) {
387                     throw sqle;
388                 }
389             }
390         }
391         finally {
392             DataAccess.cleanUp(s);
393         }
394     }
395 
396     public void runSQLTemplate(String path)
397         throws IOException, NamingException, SQLException {
398 
399         runSQLTemplate(path, true);
400     }
401 
402     public void runSQLTemplate(String path, boolean failOnError)
403         throws IOException, NamingException, SQLException {
404 
405         Thread currentThread = Thread.currentThread();
406 
407         ClassLoader classLoader = currentThread.getContextClassLoader();
408 
409         InputStream is = classLoader.getResourceAsStream(
410             "com/liferay/portal/tools/sql/dependencies/" + path);
411 
412         if (is == null) {
413             is = classLoader.getResourceAsStream(path);
414         }
415 
416         if (is == null) {
417             _log.error("Invalid path " + path);
418         }
419 
420         String template = StringUtil.read(is);
421 
422         is.close();
423 
424         boolean evaluate = path.endsWith(".vm");
425 
426         runSQLTemplateString(template, evaluate, failOnError);
427     }
428 
429     public void runSQLTemplateString(
430             String template, boolean evaluate, boolean failOnError)
431         throws IOException, NamingException, SQLException {
432 
433         if (evaluate) {
434             try {
435                 template = evaluateVM(template);
436             }
437             catch (Exception e) {
438                 _log.error(e, e);
439             }
440         }
441 
442         StringBuilder sb = new StringBuilder();
443 
444         BufferedReader br = new BufferedReader(new StringReader(template));
445 
446         String line = null;
447 
448         while ((line = br.readLine()) != null) {
449             if (!line.startsWith("##")) {
450                 if (line.startsWith("@include ")) {
451                     int pos = line.indexOf(" ");
452 
453                     String includeFileName = line.substring(pos + 1);
454 
455                     Thread currentThread = Thread.currentThread();
456 
457                     ClassLoader classLoader =
458                         currentThread.getContextClassLoader();
459 
460                     InputStream is = classLoader.getResourceAsStream(
461                         "com/liferay/portal/tools/sql/dependencies/" +
462                             includeFileName);
463 
464                     if (is == null) {
465                         is = classLoader.getResourceAsStream(includeFileName);
466                     }
467 
468                     String include = StringUtil.read(is);
469 
470                     is.close();
471 
472                     if (includeFileName.endsWith(".vm")) {
473                         try {
474                             include = evaluateVM(include);
475                         }
476                         catch (Exception e) {
477                             _log.error(e, e);
478                         }
479                     }
480 
481                     include = convertTimestamp(include);
482                     include = replaceTemplate(include, getTemplate());
483 
484                     runSQLTemplateString(include, false, true);
485                 }
486                 else{
487                     sb.append(line);
488 
489                     if (line.endsWith(";")) {
490                         String sql = sb.toString();
491 
492                         sb = new StringBuilder();
493 
494                         try {
495                             if (!sql.equals("COMMIT_TRANSACTION;")) {
496                                 runSQL(sql);
497                             }
498                             else {
499                                 if (_log.isDebugEnabled()) {
500                                     _log.debug("Skip commit sql");
501                                 }
502                             }
503                         }
504                         catch (IOException ioe) {
505                             if (failOnError) {
506                                 throw ioe;
507                             }
508                             else if (_log.isWarnEnabled()) {
509                                 _log.warn(ioe.getMessage());
510                             }
511                         }
512                         catch (SQLException sqle) {
513                             if (failOnError) {
514                                 throw sqle;
515                             }
516                             else if (_log.isWarnEnabled()) {
517                                 String message = GetterUtil.getString(
518                                     sqle.getMessage());
519 
520                                 if (!message.startsWith("Duplicate key name")) {
521                                     _log.warn(message + ": " + sql);
522                                 }
523 
524                                 if (message.startsWith("Duplicate entry") ||
525                                     message.startsWith(
526                                         "Specified key was too long")) {
527 
528                                     _log.error(line);
529                                 }
530                             }
531                         }
532                     }
533                 }
534             }
535         }
536 
537         br.close();
538     }
539 
540     public void setSupportsStringCaseSensitiveQuery(
541         boolean supportsStringCaseSensitiveQuery) {
542 
543         if (_log.isInfoEnabled()) {
544             if (supportsStringCaseSensitiveQuery) {
545                 _log.info("Database supports case sensitive queries");
546             }
547             else {
548                 _log.info("Database does not support case sensitive queries");
549             }
550         }
551 
552         _supportsStringCaseSensitiveQuery = supportsStringCaseSensitiveQuery;
553     }
554 
555     protected DBUtil(String type) {
556         _type = type;
557     }
558 
559     protected abstract String buildCreateFileContent(
560             String databaseName, int population)
561         throws IOException;
562 
563     protected String[] buildColumnNameTokens(String line) {
564         String[] words = StringUtil.split(line, " ");
565 
566         if (words.length == 7) {
567             words[5] = "not null;";
568         }
569 
570         String[] template = {
571             words[1], words[2], words[3], words[4], words[5]
572         };
573 
574         return template;
575     }
576 
577     protected String[] buildColumnTypeTokens(String line) {
578         String[] words = StringUtil.split(line, " ");
579 
580         String nullable = "";
581 
582         if (words.length == 6) {
583             nullable = "not null;";
584         }
585         else if (words.length == 5) {
586             nullable = words[4];
587         }
588         else if (words.length == 4) {
589             nullable = "not null;";
590 
591             if (words[3].endsWith(";")) {
592                 words[3] = words[3].substring(0, words[3].length() - 1);
593             }
594         }
595 
596         String[] template = {
597             words[1], words[2], "", words[3], nullable
598         };
599 
600         return template;
601     }
602 
603     protected String buildTemplate(String fileName) throws IOException {
604         File file = new File("../sql/" + fileName + ".sql");
605 
606         String template = FileUtil.read(file);
607 
608         if (fileName.equals("portal") || fileName.equals("portal-minimal") ||
609             fileName.equals("update-5.0.1-5.1.0")) {
610 
611             BufferedReader br = new BufferedReader(new StringReader(template));
612 
613             StringBuilder sb = new StringBuilder();
614 
615             String line = null;
616 
617             while ((line = br.readLine()) != null) {
618                 if (line.startsWith("@include ")) {
619                     int pos = line.indexOf(" ");
620 
621                     String includeFileName = line.substring(pos + 1);
622 
623                     File includeFile = new File("../sql/" + includeFileName);
624 
625                     if (!includeFile.exists()) {
626                         continue;
627                     }
628 
629                     String include = FileUtil.read(includeFile);
630 
631                     if (includeFileName.endsWith(".vm")) {
632                         try {
633                             include = evaluateVM(include);
634                         }
635                         catch (Exception e) {
636                             _log.error(e, e);
637                         }
638                     }
639 
640                     include = convertTimestamp(include);
641                     include = replaceTemplate(include, getTemplate());
642 
643                     sb.append(include);
644                     sb.append("\n\n");
645                 }
646                 else {
647                     sb.append(line);
648                     sb.append("\n");
649                 }
650             }
651 
652             br.close();
653 
654             template = sb.toString();
655         }
656 
657         if (fileName.equals("indexes") && (this instanceof SybaseUtil)) {
658             template = removeBooleanIndexes(template);
659         }
660 
661         return template;
662     }
663 
664     protected String convertTimestamp(String data) {
665         String s = null;
666 
667         if (this instanceof MySQLUtil) {
668             s = StringUtil.replace(data, "SPECIFIC_TIMESTAMP_", "");
669         }
670         else {
671             s = data.replaceAll(
672                 "SPECIFIC_TIMESTAMP_" + "\\d+", "CURRENT_TIMESTAMP");
673         }
674 
675         return s;
676     }
677 
678     protected String evaluateVM(String template) throws Exception {
679         Map<String, Object> variables = new HashMap<String, Object>();
680 
681         variables.put("counter", new SimpleCounter());
682 
683         template = VelocityUtil.evaluate(template, variables);
684 
685         // Trim insert statements because it breaks MySQL Query Browser
686 
687         BufferedReader br = new BufferedReader(new StringReader(template));
688 
689         StringBuilder sb = new StringBuilder();
690 
691         String line = null;
692 
693         while ((line = br.readLine()) != null) {
694             line = line.trim();
695 
696             sb.append(line);
697             sb.append("\n");
698         }
699 
700         br.close();
701 
702         template = sb.toString();
703         template = StringUtil.replace(template, "\n\n\n", "\n\n");
704 
705         return template;
706     }
707 
708     protected abstract String getServerName();
709 
710     protected String getSuffix(int type) {
711         if (type == MINIMAL) {
712             return "-minimal";
713         }
714         else if (type == SHARDED) {
715             return "-sharded";
716         }
717         else {
718             return StringPool.BLANK;
719         }
720     }
721 
722     protected abstract String[] getTemplate();
723 
724     protected String readSQL(String fileName, String comments, String eol)
725         throws IOException {
726 
727         BufferedReader br = new BufferedReader(
728             new FileReader(new File(fileName)));
729 
730         StringBuilder sb = new StringBuilder();
731 
732         String line = null;
733 
734         while ((line = br.readLine()) != null) {
735             if (!line.startsWith(comments)) {
736                 line = StringUtil.replace(
737                     line,
738                     new String[] {"\n", "\t"},
739                     new String[] {"", ""});
740 
741                 if (line.endsWith(";")) {
742                     sb.append(line.substring(0, line.length() - 1));
743                     sb.append(eol);
744                 }
745                 else {
746                     sb.append(line);
747                 }
748             }
749         }
750 
751         br.close();
752 
753         return sb.toString();
754     }
755 
756     protected String removeBooleanIndexes(String data) throws IOException {
757         String portalData = FileUtil.read("../sql/portal-tables.sql");
758 
759         BufferedReader br = new BufferedReader(new StringReader(data));
760 
761         StringBuilder sb = new StringBuilder();
762 
763         String line = null;
764 
765         while ((line = br.readLine()) != null) {
766             boolean append = true;
767 
768             int x = line.indexOf(" on ");
769 
770             if (x != -1) {
771                 int y = line.indexOf(" (", x);
772 
773                 String table = line.substring(x + 4, y);
774 
775                 x = y + 2;
776                 y = line.indexOf(")", x);
777 
778                 String[] columns = StringUtil.split(line.substring(x, y));
779 
780                 x = portalData.indexOf("create table " + table + " (");
781                 y = portalData.indexOf(");", x);
782 
783                 String portalTableData = portalData.substring(x, y);
784 
785                 for (int i = 0; i < columns.length; i++) {
786                     if (portalTableData.indexOf(
787                             columns[i].trim() + " BOOLEAN") != -1) {
788 
789                         append = false;
790 
791                         break;
792                     }
793                 }
794             }
795 
796             if (append) {
797                 sb.append(line);
798                 sb.append("\n");
799             }
800         }
801 
802         br.close();
803 
804         return sb.toString();
805     }
806 
807     protected String removeInserts(String data) throws IOException {
808         BufferedReader br = new BufferedReader(new StringReader(data));
809 
810         StringBuilder sb = new StringBuilder();
811 
812         String line = null;
813 
814         while ((line = br.readLine()) != null) {
815             if (!line.startsWith("insert into ") &&
816                 !line.startsWith("update ")) {
817 
818                 sb.append(line);
819                 sb.append("\n");
820             }
821         }
822 
823         br.close();
824 
825         return sb.toString();
826     }
827 
828     protected String removeLongInserts(String data) throws IOException {
829         BufferedReader br = new BufferedReader(new StringReader(data));
830 
831         StringBuilder sb = new StringBuilder();
832 
833         String line = null;
834 
835         while ((line = br.readLine()) != null) {
836             if (!line.startsWith("insert into Image (") &&
837                 !line.startsWith("insert into JournalArticle (") &&
838                 !line.startsWith("insert into JournalStructure (") &&
839                 !line.startsWith("insert into JournalTemplate (")) {
840 
841                 sb.append(line);
842                 sb.append("\n");
843             }
844         }
845 
846         br.close();
847 
848         return sb.toString();
849     }
850 
851     protected String removeNull(String content) {
852         content = StringUtil.replace(content, " not null", " not_null");
853         content = StringUtil.replace(content, " null", "");
854         content = StringUtil.replace(content, " not_null", " not null");
855 
856         return content;
857     }
858 
859     protected String replaceTemplate(String template, String[] actual) {
860         if ((template == null) || (TEMPLATE == null) || (actual == null)) {
861             return null;
862         }
863 
864         if (TEMPLATE.length != actual.length) {
865             return template;
866         }
867 
868         for (int i = 0; i < TEMPLATE.length; i++) {
869             if (TEMPLATE[i].equals("##") ||
870                 TEMPLATE[i].equals("'01/01/1970'")) {
871 
872                 template = template.replaceAll(TEMPLATE[i], actual[i]);
873             }
874             else {
875                 template = template.replaceAll(
876                     "\\b" + TEMPLATE[i] + "\\b", actual[i]);
877             }
878         }
879 
880         return template;
881     }
882 
883     protected abstract String reword(String data) throws IOException;
884 
885     protected static String ALTER_COLUMN_TYPE = "alter_column_type ";
886 
887     protected static String ALTER_COLUMN_NAME = "alter_column_name ";
888 
889     protected static String DROP_PRIMARY_KEY = "drop primary key";
890 
891     protected static String[] REWORD_TEMPLATE = {
892         "@table@", "@old-column@", "@new-column@", "@type@", "@nullable@"
893     };
894 
895     protected static String[] TEMPLATE = {
896         "##", "TRUE", "FALSE",
897         "'01/01/1970'", "CURRENT_TIMESTAMP",
898         " BLOB", " BOOLEAN", " DATE",
899         " DOUBLE", " INTEGER", " LONG",
900         " STRING", " TEXT", " VARCHAR",
901         " IDENTITY", "COMMIT_TRANSACTION"
902     };
903 
904     private static boolean _SUPPORTS_ALTER_COLUMN_NAME = true;
905 
906     private static boolean _SUPPORTS_ALTER_COLUMN_TYPE = true;
907 
908     private static boolean _SUPPORTS_DATE_MILLISECONDS = true;
909 
910     private static boolean _SUPPORTS_UPDATE_WITH_INNER_JOIN;
911 
912     private static Log _log = LogFactoryUtil.getLog(DBUtil.class);
913 
914     private static DBUtil _dbUtil;
915 
916     private String _type;
917     private boolean _supportsStringCaseSensitiveQuery;
918 
919 }