001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.dao.db;
016    
017    import com.liferay.counter.service.CounterLocalServiceUtil;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.db.Index;
021    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
024    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.PropertiesUtil;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.velocity.VelocityUtil;
035    import com.liferay.util.SimpleCounter;
036    
037    import java.io.File;
038    import java.io.FileReader;
039    import java.io.IOException;
040    import java.io.InputStream;
041    
042    import java.sql.Connection;
043    import java.sql.SQLException;
044    import java.sql.Statement;
045    
046    import java.util.Collections;
047    import java.util.Enumeration;
048    import java.util.HashMap;
049    import java.util.HashSet;
050    import java.util.List;
051    import java.util.Map;
052    import java.util.Properties;
053    import java.util.Set;
054    
055    import javax.naming.NamingException;
056    
057    /**
058     * @author Alexander Chow
059     * @author Ganesh Ram
060     * @author Brian Wing Shun Chan
061     */
062    public abstract class BaseDB implements DB {
063    
064            public void buildCreateFile(String sqlDir, String databaseName)
065                    throws IOException {
066    
067                    buildCreateFile(sqlDir, databaseName, POPULATED);
068                    buildCreateFile(sqlDir, databaseName, MINIMAL);
069                    buildCreateFile(sqlDir, databaseName, SHARDED);
070            }
071    
072            public void buildCreateFile(
073                            String sqlDir, String databaseName, int population)
074                    throws IOException {
075    
076                    String suffix = getSuffix(population);
077    
078                    File file = new File(
079                            sqlDir + "/create" + suffix + "/create" + suffix + "-" +
080                                    getServerName() + ".sql");
081    
082                    if (population != SHARDED) {
083                            String content = buildCreateFileContent(
084                                    sqlDir, databaseName, population);
085    
086                            if (content != null) {
087                                    FileUtil.write(file, content);
088                            }
089                    }
090                    else {
091                            String content = buildCreateFileContent(
092                                    sqlDir, databaseName, MINIMAL);
093    
094                            if (content != null) {
095                                    FileUtil.write(file, content);
096                            }
097    
098                            content = buildCreateFileContent(
099                                    sqlDir, databaseName + "1", MINIMAL);
100    
101                            if (content != null) {
102                                    FileUtil.write(file, content, false, true);
103                            }
104    
105                            content = buildCreateFileContent(
106                                    sqlDir, databaseName + "2", MINIMAL);
107    
108                            if (content != null) {
109                                    FileUtil.write(file, content, false, true);
110                            }
111                    }
112            }
113    
114            public abstract String buildSQL(String template) throws IOException;
115    
116            public void buildSQLFile(String sqlDir, String fileName)
117                    throws IOException {
118    
119                    String template = buildTemplate(sqlDir, fileName);
120    
121                    if (Validator.isNull(template)) {
122                            return;
123                    }
124    
125                    template = buildSQL(template);
126    
127                    FileUtil.write(
128                            sqlDir + "/" + fileName + "/" + fileName + "-" + getServerName() +
129                                    ".sql",
130                            template);
131            }
132    
133            /**
134             * @throws SQLException
135             */
136            public List<Index> getIndexes() throws SQLException {
137                    return Collections.EMPTY_LIST;
138            }
139    
140            public String getTemplateFalse() {
141                    return getTemplate()[2];
142            }
143    
144            public String getTemplateTrue() {
145                    return getTemplate()[1];
146            }
147    
148            public String getType() {
149                    return _type;
150            }
151    
152            public long increment() throws SystemException {
153                    return CounterLocalServiceUtil.increment();
154            }
155    
156            public boolean isSupportsAlterColumnName() {
157                    return _SUPPORTS_ALTER_COLUMN_NAME;
158            }
159    
160            public boolean isSupportsAlterColumnType() {
161                    return _SUPPORTS_ALTER_COLUMN_TYPE;
162            }
163    
164            public boolean isSupportsDateMilliseconds() {
165                    return _SUPPORTS_DATE_MILLISECONDS;
166            }
167    
168            public boolean isSupportsInlineDistinct() {
169                    return _SUPPORTS_INLINE_DISTINCT;
170            }
171    
172            public boolean isSupportsScrollableResults() {
173                    return _SUPPORTS_SCROLLABLE_RESULTS;
174            }
175    
176            public boolean isSupportsStringCaseSensitiveQuery() {
177                    return _supportsStringCaseSensitiveQuery;
178            }
179    
180            public boolean isSupportsUpdateWithInnerJoin() {
181                    return _SUPPORTS_UPDATE_WITH_INNER_JOIN;
182            }
183    
184            public void runSQL(String sql) throws IOException, SQLException {
185                    runSQL(new String[] {sql});
186            }
187    
188            public void runSQL(Connection con, String sql)
189                    throws IOException, SQLException {
190    
191                    runSQL(con, new String[] {sql});
192            }
193    
194            public void runSQL(String[] sqls) throws IOException, SQLException {
195                    Connection con = DataAccess.getConnection();
196    
197                    try {
198                            runSQL(con, sqls);
199                    }
200                    finally {
201                            DataAccess.cleanUp(con);
202                    }
203            }
204    
205            public void runSQL(Connection con, String[] sqls)
206                    throws IOException, SQLException {
207    
208                    Statement s = null;
209    
210                    try {
211                            s = con.createStatement();
212    
213                            for (int i = 0; i < sqls.length; i++) {
214                                    String sql = buildSQL(sqls[i]);
215    
216                                    sql = sql.trim();
217    
218                                    if (sql.endsWith(";")) {
219                                            sql = sql.substring(0, sql.length() - 1);
220                                    }
221    
222                                    if (sql.endsWith("go")) {
223                                            sql = sql.substring(0, sql.length() - 2);
224                                    }
225    
226                                    if (_log.isDebugEnabled()) {
227                                            _log.debug(sql);
228                                    }
229    
230                                    try {
231                                            s.executeUpdate(sql);
232                                    }
233                                    catch (SQLException sqle) {
234                                            throw sqle;
235                                    }
236                            }
237                    }
238                    finally {
239                            DataAccess.cleanUp(s);
240                    }
241            }
242    
243            public void runSQLTemplate(String path)
244                    throws IOException, NamingException, SQLException {
245    
246                    runSQLTemplate(path, true);
247            }
248    
249            public void runSQLTemplate(String path, boolean failOnError)
250                    throws IOException, NamingException, SQLException {
251    
252                    Thread currentThread = Thread.currentThread();
253    
254                    ClassLoader classLoader = currentThread.getContextClassLoader();
255    
256                    InputStream is = classLoader.getResourceAsStream(
257                            "com/liferay/portal/tools/sql/dependencies/" + path);
258    
259                    if (is == null) {
260                            is = classLoader.getResourceAsStream(path);
261                    }
262    
263                    if (is == null) {
264                            _log.error("Invalid path " + path);
265    
266                            if (failOnError) {
267                                    throw new IOException("Invalid path " + path);
268                            }
269                            else {
270                                    return;
271                            }
272                    }
273    
274                    String template = StringUtil.read(is);
275    
276                    is.close();
277    
278                    boolean evaluate = path.endsWith(".vm");
279    
280                    runSQLTemplateString(template, evaluate, failOnError);
281            }
282    
283            public void runSQLTemplateString(
284                            String template, boolean evaluate, boolean failOnError)
285                    throws IOException, NamingException, SQLException {
286    
287                    if (evaluate) {
288                            try {
289                                    template = evaluateVM(template);
290                            }
291                            catch (Exception e) {
292                                    _log.error(e, e);
293                            }
294                    }
295    
296                    StringBundler sb = new StringBundler();
297    
298                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
299                            new UnsyncStringReader(template));
300    
301                    String line = null;
302    
303                    while ((line = unsyncBufferedReader.readLine()) != null) {
304                            if (!line.startsWith("##")) {
305                                    if (line.startsWith("@include ")) {
306                                            int pos = line.indexOf(" ");
307    
308                                            String includeFileName = line.substring(pos + 1);
309    
310                                            Thread currentThread = Thread.currentThread();
311    
312                                            ClassLoader classLoader =
313                                                    currentThread.getContextClassLoader();
314    
315                                            InputStream is = classLoader.getResourceAsStream(
316                                                    "com/liferay/portal/tools/sql/dependencies/" +
317                                                            includeFileName);
318    
319                                            if (is == null) {
320                                                    is = classLoader.getResourceAsStream(includeFileName);
321                                            }
322    
323                                            String include = StringUtil.read(is);
324    
325                                            is.close();
326    
327                                            if (includeFileName.endsWith(".vm")) {
328                                                    try {
329                                                            include = evaluateVM(include);
330                                                    }
331                                                    catch (Exception e) {
332                                                            _log.error(e, e);
333                                                    }
334                                            }
335    
336                                            include = convertTimestamp(include);
337                                            include = replaceTemplate(include, getTemplate());
338    
339                                            runSQLTemplateString(include, false, true);
340                                    }
341                                    else{
342                                            sb.append(line);
343    
344                                            if (line.endsWith(";")) {
345                                                    String sql = sb.toString();
346    
347                                                    sb.setIndex(0);
348    
349                                                    try {
350                                                            if (!sql.equals("COMMIT_TRANSACTION;")) {
351                                                                    runSQL(sql);
352                                                            }
353                                                            else {
354                                                                    if (_log.isDebugEnabled()) {
355                                                                            _log.debug("Skip commit sql");
356                                                                    }
357                                                            }
358                                                    }
359                                                    catch (IOException ioe) {
360                                                            if (failOnError) {
361                                                                    throw ioe;
362                                                            }
363                                                            else if (_log.isWarnEnabled()) {
364                                                                    _log.warn(ioe.getMessage());
365                                                            }
366                                                    }
367                                                    catch (SQLException sqle) {
368                                                            if (failOnError) {
369                                                                    throw sqle;
370                                                            }
371                                                            else if (_log.isWarnEnabled()) {
372                                                                    String message = GetterUtil.getString(
373                                                                            sqle.getMessage());
374    
375                                                                    if (!message.startsWith("Duplicate key name")) {
376                                                                            _log.warn(message + ": " + sql);
377                                                                    }
378    
379                                                                    if (message.startsWith("Duplicate entry") ||
380                                                                            message.startsWith(
381                                                                                    "Specified key was too long")) {
382    
383                                                                            _log.error(line);
384                                                                    }
385                                                            }
386                                                    }
387                                            }
388                                    }
389                            }
390                    }
391    
392                    unsyncBufferedReader.close();
393            }
394    
395            public void setSupportsStringCaseSensitiveQuery(
396                    boolean supportsStringCaseSensitiveQuery) {
397    
398                    if (_log.isInfoEnabled()) {
399                            if (supportsStringCaseSensitiveQuery) {
400                                    _log.info("Database supports case sensitive queries");
401                            }
402                            else {
403                                    _log.info("Database does not support case sensitive queries");
404                            }
405                    }
406    
407                    _supportsStringCaseSensitiveQuery = supportsStringCaseSensitiveQuery;
408            }
409    
410            public void updateIndexes(
411                            String tablesSQL, String indexesSQL, String indexesProperties,
412                            boolean dropIndexes)
413                    throws IOException, SQLException {
414    
415                    List<Index> indexes = getIndexes();
416    
417                    Set<String> validIndexNames = null;
418    
419                    if (dropIndexes) {
420                            validIndexNames = dropIndexes(
421                                    tablesSQL, indexesSQL, indexesProperties, indexes);
422                    }
423                    else {
424                            validIndexNames = new HashSet<String>();
425    
426                            for (Index index : indexes) {
427                                    String indexName = index.getIndexName().toUpperCase();
428    
429                                    validIndexNames.add(indexName);
430                            }
431                    }
432    
433                    addIndexes(indexesSQL, validIndexNames);
434            }
435    
436            protected BaseDB(String type) {
437                    _type = type;
438            }
439    
440            protected void addIndexes(String indexesSQL, Set<String> validIndexNames)
441                    throws IOException {
442    
443                    if (_log.isInfoEnabled()) {
444                            _log.info("Adding indexes");
445                    }
446    
447                    DB db = DBFactoryUtil.getDB();
448    
449                    UnsyncBufferedReader bufferedReader = new UnsyncBufferedReader(
450                            new UnsyncStringReader(indexesSQL));
451    
452                    String sql = null;
453    
454                    while ((sql = bufferedReader.readLine()) != null) {
455                            if (Validator.isNull(sql)) {
456                                    continue;
457                            }
458    
459                            int y = sql.indexOf(" on ");
460                            int x = sql.lastIndexOf(" ", y - 1);
461    
462                            String indexName = sql.substring(x + 1, y);
463    
464                            if (validIndexNames.contains(indexName)) {
465                                    continue;
466                            }
467    
468                            if (_log.isInfoEnabled()) {
469                                    _log.info(sql);
470                            }
471    
472                            try {
473                                    db.runSQL(sql);
474                            }
475                            catch (Exception e) {
476                                    if (_log.isWarnEnabled()) {
477                                            _log.warn(e.getMessage());
478                                    }
479                            }
480                    }
481            }
482    
483            protected abstract String buildCreateFileContent(
484                            String sqlDir, String databaseName, int population)
485                    throws IOException;
486    
487            protected String[] buildColumnNameTokens(String line) {
488                    String[] words = StringUtil.split(line, " ");
489    
490                    if (words.length == 7) {
491                            words[5] = "not null;";
492                    }
493    
494                    String[] template = {
495                            words[1], words[2], words[3], words[4], words[5]
496                    };
497    
498                    return template;
499            }
500    
501            protected String[] buildColumnTypeTokens(String line) {
502                    String[] words = StringUtil.split(line, " ");
503    
504                    String nullable = "";
505    
506                    if (words.length == 6) {
507                            nullable = "not null;";
508                    }
509                    else if (words.length == 5) {
510                            nullable = words[4];
511                    }
512                    else if (words.length == 4) {
513                            nullable = "not null;";
514    
515                            if (words[3].endsWith(";")) {
516                                    words[3] = words[3].substring(0, words[3].length() - 1);
517                            }
518                    }
519    
520                    String[] template = {
521                            words[1], words[2], "", words[3], nullable
522                    };
523    
524                    return template;
525            }
526    
527            protected String buildTemplate(String sqlDir, String fileName)
528                    throws IOException {
529    
530                    String template = readFile(sqlDir + "/" + fileName + ".sql");
531    
532                    if (fileName.equals("portal") || fileName.equals("portal-minimal") ||
533                            fileName.equals("update-5.0.1-5.1.0")) {
534    
535                            UnsyncBufferedReader unsyncBufferedReader =
536                                    new UnsyncBufferedReader(new UnsyncStringReader(template));
537    
538                            StringBundler sb = new StringBundler();
539    
540                            String line = null;
541    
542                            while ((line = unsyncBufferedReader.readLine()) != null) {
543                                    if (line.startsWith("@include ")) {
544                                            int pos = line.indexOf(" ");
545    
546                                            String includeFileName = line.substring(pos + 1);
547    
548                                            File includeFile = new File(
549                                                    sqlDir + "/" + includeFileName);
550    
551                                            if (!includeFile.exists()) {
552                                                    continue;
553                                            }
554    
555                                            String include = FileUtil.read(includeFile);
556    
557                                            if (includeFileName.endsWith(".vm")) {
558                                                    try {
559                                                            include = evaluateVM(include);
560                                                    }
561                                                    catch (Exception e) {
562                                                            _log.error(e, e);
563                                                    }
564                                            }
565    
566                                            include = convertTimestamp(include);
567                                            include = replaceTemplate(include, getTemplate());
568    
569                                            sb.append(include);
570                                            sb.append("\n\n");
571                                    }
572                                    else {
573                                            sb.append(line);
574                                            sb.append("\n");
575                                    }
576                            }
577    
578                            unsyncBufferedReader.close();
579    
580                            template = sb.toString();
581                    }
582    
583                    if (fileName.equals("indexes") && (this instanceof SybaseDB)) {
584                            template = removeBooleanIndexes(sqlDir, template);
585                    }
586    
587                    return template;
588            }
589    
590            protected String convertTimestamp(String data) {
591                    String s = null;
592    
593                    if (this instanceof MySQLDB) {
594                            s = StringUtil.replace(data, "SPECIFIC_TIMESTAMP_", "");
595                    }
596                    else {
597                            s = data.replaceAll(
598                                    "SPECIFIC_TIMESTAMP_" + "\\d+", "CURRENT_TIMESTAMP");
599                    }
600    
601                    return s;
602            }
603    
604            protected Set<String> dropIndexes(
605                            String tablesSQL, String indexesSQL, String indexesProperties,
606                            List<Index> indexes)
607                    throws IOException, SQLException {
608    
609                    if (_log.isInfoEnabled()) {
610                            _log.info("Dropping stale indexes");
611                    }
612    
613                    Set<String> validIndexNames = new HashSet<String>();
614    
615                    if (indexes.isEmpty()) {
616                            return validIndexNames;
617                    }
618    
619                    DB db = DBFactoryUtil.getDB();
620    
621                    String tablesSQLLowerCase = tablesSQL.toLowerCase();
622                    String indexesSQLLowerCase = indexesSQL.toLowerCase();
623    
624                    Properties indexesPropertiesObj = PropertiesUtil.load(
625                            indexesProperties);
626    
627                    Enumeration<String> enu =
628                            (Enumeration<String>)indexesPropertiesObj.propertyNames();
629    
630                    while (enu.hasMoreElements()) {
631                            String key = enu.nextElement();
632    
633                            String value = indexesPropertiesObj.getProperty(key);
634    
635                            indexesPropertiesObj.setProperty(key.toLowerCase(), value);
636                    }
637    
638                    for (Index index : indexes) {
639                            String indexNameUpperCase = index.getIndexName().toUpperCase();
640                            String indexNameLowerCase = indexNameUpperCase.toLowerCase();
641                            String tableName = index.getTableName();
642                            String tableNameLowerCase = tableName.toLowerCase();
643                            boolean unique = index.isUnique();
644    
645                            validIndexNames.add(indexNameUpperCase);
646    
647                            if (indexesPropertiesObj.containsKey(indexNameLowerCase)) {
648                                    if (unique &&
649                                            indexesSQLLowerCase.contains(
650                                                    "create unique index " + indexNameLowerCase + " ")) {
651    
652                                            continue;
653                                    }
654    
655                                    if (!unique &&
656                                            indexesSQLLowerCase.contains(
657                                                    "create index " + indexNameLowerCase + " ")) {
658    
659                                            continue;
660                                    }
661                            }
662                            else {
663                                    if (!tablesSQLLowerCase.contains(
664                                                    "create table " + tableNameLowerCase + " (")) {
665    
666                                            continue;
667                                    }
668                            }
669    
670                            validIndexNames.remove(indexNameUpperCase);
671    
672                            db.runSQL("drop index " + indexNameUpperCase + " on " + tableName);
673                    }
674    
675                    return validIndexNames;
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                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
688                            new UnsyncStringReader(template));
689    
690                    StringBundler sb = new StringBundler();
691    
692                    String line = null;
693    
694                    while ((line = unsyncBufferedReader.readLine()) != null) {
695                            line = line.trim();
696    
697                            sb.append(line);
698                            sb.append("\n");
699                    }
700    
701                    unsyncBufferedReader.close();
702    
703                    template = sb.toString();
704                    template = StringUtil.replace(template, "\n\n\n", "\n\n");
705    
706                    return template;
707            }
708    
709            protected abstract String getServerName();
710    
711            protected String getSuffix(int type) {
712                    if (type == MINIMAL) {
713                            return "-minimal";
714                    }
715                    else if (type == SHARDED) {
716                            return "-sharded";
717                    }
718                    else {
719                            return StringPool.BLANK;
720                    }
721            }
722    
723            protected abstract String[] getTemplate();
724    
725            protected String readFile(String fileName) throws IOException {
726                    if (FileUtil.exists(fileName)) {
727                            return FileUtil.read(fileName);
728                    }
729                    else {
730                            return StringPool.BLANK;
731                    }
732            }
733    
734            protected String readSQL(String fileName, String comments, String eol)
735                    throws IOException {
736    
737                    if (!FileUtil.exists(fileName)) {
738                            return StringPool.BLANK;
739                    }
740    
741                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
742                            new FileReader(new File(fileName)));
743    
744                    StringBundler sb = new StringBundler();
745    
746                    String line = null;
747    
748                    while ((line = unsyncBufferedReader.readLine()) != null) {
749                            if (!line.startsWith(comments)) {
750                                    line = StringUtil.replace(
751                                            line,
752                                            new String[] {"\n", "\t"},
753                                            new String[] {"", ""});
754    
755                                    if (line.endsWith(";")) {
756                                            sb.append(line.substring(0, line.length() - 1));
757                                            sb.append(eol);
758                                    }
759                                    else {
760                                            sb.append(line);
761                                    }
762                            }
763                    }
764    
765                    unsyncBufferedReader.close();
766    
767                    return sb.toString();
768            }
769    
770            protected String removeBooleanIndexes(String sqlDir, String data)
771                    throws IOException {
772    
773                    String portalData = readFile(sqlDir + "/portal-tables.sql");
774    
775                    if (Validator.isNull(portalData)) {
776                            return StringPool.BLANK;
777                    }
778    
779                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
780                            new UnsyncStringReader(data));
781    
782                    StringBundler sb = new StringBundler();
783    
784                    String line = null;
785    
786                    while ((line = unsyncBufferedReader.readLine()) != null) {
787                            boolean append = true;
788    
789                            int x = line.indexOf(" on ");
790    
791                            if (x != -1) {
792                                    int y = line.indexOf(" (", x);
793    
794                                    String table = line.substring(x + 4, y);
795    
796                                    x = y + 2;
797                                    y = line.indexOf(")", x);
798    
799                                    String[] columns = StringUtil.split(line.substring(x, y));
800    
801                                    x = portalData.indexOf("create table " + table + " (");
802                                    y = portalData.indexOf(");", x);
803    
804                                    String portalTableData = portalData.substring(x, y);
805    
806                                    for (int i = 0; i < columns.length; i++) {
807                                            if (portalTableData.indexOf(
808                                                            columns[i].trim() + " BOOLEAN") != -1) {
809    
810                                                    append = false;
811    
812                                                    break;
813                                            }
814                                    }
815                            }
816    
817                            if (append) {
818                                    sb.append(line);
819                                    sb.append("\n");
820                            }
821                    }
822    
823                    unsyncBufferedReader.close();
824    
825                    return sb.toString();
826            }
827    
828            protected String removeInserts(String data) throws IOException {
829                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
830                            new UnsyncStringReader(data));
831    
832                    StringBundler sb = new StringBundler();
833    
834                    String line = null;
835    
836                    while ((line = unsyncBufferedReader.readLine()) != null) {
837                            if (!line.startsWith("insert into ") &&
838                                    !line.startsWith("update ")) {
839    
840                                    sb.append(line);
841                                    sb.append("\n");
842                            }
843                    }
844    
845                    unsyncBufferedReader.close();
846    
847                    return sb.toString();
848            }
849    
850            protected String removeLongInserts(String data) throws IOException {
851                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
852                            new UnsyncStringReader(data));
853    
854                    StringBundler sb = new StringBundler();
855    
856                    String line = null;
857    
858                    while ((line = unsyncBufferedReader.readLine()) != null) {
859                            if (!line.startsWith("insert into Image (") &&
860                                    !line.startsWith("insert into JournalArticle (") &&
861                                    !line.startsWith("insert into JournalStructure (") &&
862                                    !line.startsWith("insert into JournalTemplate (")) {
863    
864                                    sb.append(line);
865                                    sb.append("\n");
866                            }
867                    }
868    
869                    unsyncBufferedReader.close();
870    
871                    return sb.toString();
872            }
873    
874            protected String removeNull(String content) {
875                    content = StringUtil.replace(content, " is null", " IS NULL");
876                    content = StringUtil.replace(content, " not null", " not_null");
877                    content = StringUtil.replace(content, " null", "");
878                    content = StringUtil.replace(content, " not_null", " not null");
879    
880                    return content;
881            }
882    
883            protected String replaceTemplate(String template, String[] actual) {
884                    if ((template == null) || (TEMPLATE == null) || (actual == null)) {
885                            return null;
886                    }
887    
888                    if (TEMPLATE.length != actual.length) {
889                            return template;
890                    }
891    
892                    for (int i = 0; i < TEMPLATE.length; i++) {
893                            if (TEMPLATE[i].equals("##") ||
894                                    TEMPLATE[i].equals("'01/01/1970'")) {
895    
896                                    template = template.replaceAll(TEMPLATE[i], actual[i]);
897                            }
898                            else {
899                                    template = template.replaceAll(
900                                            "\\b" + TEMPLATE[i] + "\\b", actual[i]);
901                            }
902                    }
903    
904                    return template;
905            }
906    
907            protected abstract String reword(String data) throws IOException;
908    
909            protected static String ALTER_COLUMN_TYPE = "alter_column_type ";
910    
911            protected static String ALTER_COLUMN_NAME = "alter_column_name ";
912    
913            protected static String DROP_INDEX = "drop index";
914    
915            protected static String DROP_PRIMARY_KEY = "drop primary key";
916    
917            protected static String[] REWORD_TEMPLATE = {
918                    "@table@", "@old-column@", "@new-column@", "@type@", "@nullable@"
919            };
920    
921            protected static String[] TEMPLATE = {
922                    "##", "TRUE", "FALSE",
923                    "'01/01/1970'", "CURRENT_TIMESTAMP",
924                    " BLOB", " BOOLEAN", " DATE",
925                    " DOUBLE", " INTEGER", " LONG",
926                    " STRING", " TEXT", " VARCHAR",
927                    " IDENTITY", "COMMIT_TRANSACTION"
928            };
929    
930            private static final boolean _SUPPORTS_ALTER_COLUMN_NAME = true;
931    
932            private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = true;
933    
934            private static final boolean _SUPPORTS_DATE_MILLISECONDS = true;
935    
936            private static final boolean _SUPPORTS_INLINE_DISTINCT = true;
937    
938            private static final boolean _SUPPORTS_SCROLLABLE_RESULTS = true;
939    
940            private static final boolean _SUPPORTS_UPDATE_WITH_INNER_JOIN = true;
941    
942            private static Log _log = LogFactoryUtil.getLog(BaseDB.class);
943    
944            private String _type;
945            private boolean _supportsStringCaseSensitiveQuery;
946    
947    }