001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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 isSupportsScrollableResults() {
169                    return _SUPPORTS_SCROLLABLE_RESULTS;
170            }
171    
172            public boolean isSupportsStringCaseSensitiveQuery() {
173                    return _supportsStringCaseSensitiveQuery;
174            }
175    
176            public boolean isSupportsUpdateWithInnerJoin() {
177                    return _SUPPORTS_UPDATE_WITH_INNER_JOIN;
178            }
179    
180            public void runSQL(String sql) throws IOException, SQLException {
181                    runSQL(new String[] {sql});
182            }
183    
184            public void runSQL(Connection con, String sql)
185                    throws IOException, SQLException {
186    
187                    runSQL(con, new String[] {sql});
188            }
189    
190            public void runSQL(String[] sqls) throws IOException, SQLException {
191                    Connection con = DataAccess.getConnection();
192    
193                    try {
194                            runSQL(con, sqls);
195                    }
196                    finally {
197                            DataAccess.cleanUp(con);
198                    }
199            }
200    
201            public void runSQL(Connection con, String[] sqls)
202                    throws IOException, SQLException {
203    
204                    Statement s = null;
205    
206                    try {
207                            s = con.createStatement();
208    
209                            for (int i = 0; i < sqls.length; i++) {
210                                    String sql = buildSQL(sqls[i]);
211    
212                                    sql = sql.trim();
213    
214                                    if (sql.endsWith(";")) {
215                                            sql = sql.substring(0, sql.length() - 1);
216                                    }
217    
218                                    if (sql.endsWith("go")) {
219                                            sql = sql.substring(0, sql.length() - 2);
220                                    }
221    
222                                    if (_log.isDebugEnabled()) {
223                                            _log.debug(sql);
224                                    }
225    
226                                    try {
227                                            s.executeUpdate(sql);
228                                    }
229                                    catch (SQLException sqle) {
230                                            throw sqle;
231                                    }
232                            }
233                    }
234                    finally {
235                            DataAccess.cleanUp(s);
236                    }
237            }
238    
239            public void runSQLTemplate(String path)
240                    throws IOException, NamingException, SQLException {
241    
242                    runSQLTemplate(path, true);
243            }
244    
245            public void runSQLTemplate(String path, boolean failOnError)
246                    throws IOException, NamingException, SQLException {
247    
248                    Thread currentThread = Thread.currentThread();
249    
250                    ClassLoader classLoader = currentThread.getContextClassLoader();
251    
252                    InputStream is = classLoader.getResourceAsStream(
253                            "com/liferay/portal/tools/sql/dependencies/" + path);
254    
255                    if (is == null) {
256                            is = classLoader.getResourceAsStream(path);
257                    }
258    
259                    if (is == null) {
260                            _log.error("Invalid path " + path);
261    
262                            if (failOnError) {
263                                    throw new IOException("Invalid path " + path);
264                            }
265                            else {
266                                    return;
267                            }
268                    }
269    
270                    String template = StringUtil.read(is);
271    
272                    is.close();
273    
274                    boolean evaluate = path.endsWith(".vm");
275    
276                    runSQLTemplateString(template, evaluate, failOnError);
277            }
278    
279            public void runSQLTemplateString(
280                            String template, boolean evaluate, boolean failOnError)
281                    throws IOException, NamingException, SQLException {
282    
283                    if (evaluate) {
284                            try {
285                                    template = evaluateVM(template);
286                            }
287                            catch (Exception e) {
288                                    _log.error(e, e);
289                            }
290                    }
291    
292                    StringBundler sb = new StringBundler();
293    
294                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
295                            new UnsyncStringReader(template));
296    
297                    String line = null;
298    
299                    while ((line = unsyncBufferedReader.readLine()) != null) {
300                            if (!line.startsWith("##")) {
301                                    if (line.startsWith("@include ")) {
302                                            int pos = line.indexOf(" ");
303    
304                                            String includeFileName = line.substring(pos + 1);
305    
306                                            Thread currentThread = Thread.currentThread();
307    
308                                            ClassLoader classLoader =
309                                                    currentThread.getContextClassLoader();
310    
311                                            InputStream is = classLoader.getResourceAsStream(
312                                                    "com/liferay/portal/tools/sql/dependencies/" +
313                                                            includeFileName);
314    
315                                            if (is == null) {
316                                                    is = classLoader.getResourceAsStream(includeFileName);
317                                            }
318    
319                                            String include = StringUtil.read(is);
320    
321                                            is.close();
322    
323                                            if (includeFileName.endsWith(".vm")) {
324                                                    try {
325                                                            include = evaluateVM(include);
326                                                    }
327                                                    catch (Exception e) {
328                                                            _log.error(e, e);
329                                                    }
330                                            }
331    
332                                            include = convertTimestamp(include);
333                                            include = replaceTemplate(include, getTemplate());
334    
335                                            runSQLTemplateString(include, false, true);
336                                    }
337                                    else{
338                                            sb.append(line);
339    
340                                            if (line.endsWith(";")) {
341                                                    String sql = sb.toString();
342    
343                                                    sb.setIndex(0);
344    
345                                                    try {
346                                                            if (!sql.equals("COMMIT_TRANSACTION;")) {
347                                                                    runSQL(sql);
348                                                            }
349                                                            else {
350                                                                    if (_log.isDebugEnabled()) {
351                                                                            _log.debug("Skip commit sql");
352                                                                    }
353                                                            }
354                                                    }
355                                                    catch (IOException ioe) {
356                                                            if (failOnError) {
357                                                                    throw ioe;
358                                                            }
359                                                            else if (_log.isWarnEnabled()) {
360                                                                    _log.warn(ioe.getMessage());
361                                                            }
362                                                    }
363                                                    catch (SQLException sqle) {
364                                                            if (failOnError) {
365                                                                    throw sqle;
366                                                            }
367                                                            else if (_log.isWarnEnabled()) {
368                                                                    String message = GetterUtil.getString(
369                                                                            sqle.getMessage());
370    
371                                                                    if (!message.startsWith("Duplicate key name")) {
372                                                                            _log.warn(message + ": " + sql);
373                                                                    }
374    
375                                                                    if (message.startsWith("Duplicate entry") ||
376                                                                            message.startsWith(
377                                                                                    "Specified key was too long")) {
378    
379                                                                            _log.error(line);
380                                                                    }
381                                                            }
382                                                    }
383                                            }
384                                    }
385                            }
386                    }
387    
388                    unsyncBufferedReader.close();
389            }
390    
391            public void setSupportsStringCaseSensitiveQuery(
392                    boolean supportsStringCaseSensitiveQuery) {
393    
394                    if (_log.isInfoEnabled()) {
395                            if (supportsStringCaseSensitiveQuery) {
396                                    _log.info("Database supports case sensitive queries");
397                            }
398                            else {
399                                    _log.info("Database does not support case sensitive queries");
400                            }
401                    }
402    
403                    _supportsStringCaseSensitiveQuery = supportsStringCaseSensitiveQuery;
404            }
405    
406            public void updateIndexes(
407                            String tablesSQL, String indexesSQL, String indexesProperties,
408                            boolean dropIndexes)
409                    throws IOException, SQLException {
410    
411                    List<Index> indexes = getIndexes();
412    
413                    Set<String> validIndexNames = null;
414    
415                    if (dropIndexes) {
416                            validIndexNames = dropIndexes(
417                                    tablesSQL, indexesSQL, indexesProperties, indexes);
418                    }
419                    else {
420                            validIndexNames = new HashSet<String>();
421    
422                            for (Index index : indexes) {
423                                    String indexName = index.getIndexName().toUpperCase();
424    
425                                    validIndexNames.add(indexName);
426                            }
427                    }
428    
429                    addIndexes(indexesSQL, validIndexNames);
430            }
431    
432            protected BaseDB(String type) {
433                    _type = type;
434            }
435    
436            protected void addIndexes(String indexesSQL, Set<String> validIndexNames)
437                    throws IOException {
438    
439                    if (_log.isInfoEnabled()) {
440                            _log.info("Adding indexes");
441                    }
442    
443                    DB db = DBFactoryUtil.getDB();
444    
445                    UnsyncBufferedReader bufferedReader = new UnsyncBufferedReader(
446                            new UnsyncStringReader(indexesSQL));
447    
448                    String sql = null;
449    
450                    while ((sql = bufferedReader.readLine()) != null) {
451                            if (Validator.isNull(sql)) {
452                                    continue;
453                            }
454    
455                            int y = sql.indexOf(" on ");
456                            int x = sql.lastIndexOf(" ", y - 1);
457    
458                            String indexName = sql.substring(x + 1, y);
459    
460                            if (validIndexNames.contains(indexName)) {
461                                    continue;
462                            }
463    
464                            if (_log.isInfoEnabled()) {
465                                    _log.info(sql);
466                            }
467    
468                            try {
469                                    db.runSQL(sql);
470                            }
471                            catch (Exception e) {
472                                    if (_log.isWarnEnabled()) {
473                                            _log.warn(e.getMessage());
474                                    }
475                            }
476                    }
477            }
478    
479            protected abstract String buildCreateFileContent(
480                            String sqlDir, String databaseName, int population)
481                    throws IOException;
482    
483            protected String[] buildColumnNameTokens(String line) {
484                    String[] words = StringUtil.split(line, " ");
485    
486                    if (words.length == 7) {
487                            words[5] = "not null;";
488                    }
489    
490                    String[] template = {
491                            words[1], words[2], words[3], words[4], words[5]
492                    };
493    
494                    return template;
495            }
496    
497            protected String[] buildColumnTypeTokens(String line) {
498                    String[] words = StringUtil.split(line, " ");
499    
500                    String nullable = "";
501    
502                    if (words.length == 6) {
503                            nullable = "not null;";
504                    }
505                    else if (words.length == 5) {
506                            nullable = words[4];
507                    }
508                    else if (words.length == 4) {
509                            nullable = "not null;";
510    
511                            if (words[3].endsWith(";")) {
512                                    words[3] = words[3].substring(0, words[3].length() - 1);
513                            }
514                    }
515    
516                    String[] template = {
517                            words[1], words[2], "", words[3], nullable
518                    };
519    
520                    return template;
521            }
522    
523            protected String buildTemplate(String sqlDir, String fileName)
524                    throws IOException {
525    
526                    String template = readFile(sqlDir + "/" + fileName + ".sql");
527    
528                    if (fileName.equals("portal") || fileName.equals("portal-minimal") ||
529                            fileName.equals("update-5.0.1-5.1.0")) {
530    
531                            UnsyncBufferedReader unsyncBufferedReader =
532                                    new UnsyncBufferedReader(new UnsyncStringReader(template));
533    
534                            StringBundler sb = new StringBundler();
535    
536                            String line = null;
537    
538                            while ((line = unsyncBufferedReader.readLine()) != null) {
539                                    if (line.startsWith("@include ")) {
540                                            int pos = line.indexOf(" ");
541    
542                                            String includeFileName = line.substring(pos + 1);
543    
544                                            File includeFile = new File(
545                                                    sqlDir + "/" + includeFileName);
546    
547                                            if (!includeFile.exists()) {
548                                                    continue;
549                                            }
550    
551                                            String include = FileUtil.read(includeFile);
552    
553                                            if (includeFileName.endsWith(".vm")) {
554                                                    try {
555                                                            include = evaluateVM(include);
556                                                    }
557                                                    catch (Exception e) {
558                                                            _log.error(e, e);
559                                                    }
560                                            }
561    
562                                            include = convertTimestamp(include);
563                                            include = replaceTemplate(include, getTemplate());
564    
565                                            sb.append(include);
566                                            sb.append("\n\n");
567                                    }
568                                    else {
569                                            sb.append(line);
570                                            sb.append("\n");
571                                    }
572                            }
573    
574                            unsyncBufferedReader.close();
575    
576                            template = sb.toString();
577                    }
578    
579                    if (fileName.equals("indexes") && (this instanceof SybaseDB)) {
580                            template = removeBooleanIndexes(sqlDir, template);
581                    }
582    
583                    return template;
584            }
585    
586            protected String convertTimestamp(String data) {
587                    String s = null;
588    
589                    if (this instanceof MySQLDB) {
590                            s = StringUtil.replace(data, "SPECIFIC_TIMESTAMP_", "");
591                    }
592                    else {
593                            s = data.replaceAll(
594                                    "SPECIFIC_TIMESTAMP_" + "\\d+", "CURRENT_TIMESTAMP");
595                    }
596    
597                    return s;
598            }
599    
600            protected Set<String> dropIndexes(
601                            String tablesSQL, String indexesSQL, String indexesProperties,
602                            List<Index> indexes)
603                    throws IOException, SQLException {
604    
605                    if (_log.isInfoEnabled()) {
606                            _log.info("Dropping stale indexes");
607                    }
608    
609                    Set<String> validIndexNames = new HashSet<String>();
610    
611                    if (indexes.isEmpty()) {
612                            return validIndexNames;
613                    }
614    
615                    DB db = DBFactoryUtil.getDB();
616    
617                    String tablesSQLLowerCase = tablesSQL.toLowerCase();
618                    String indexesSQLLowerCase = indexesSQL.toLowerCase();
619    
620                    Properties indexesPropertiesObj = PropertiesUtil.load(
621                            indexesProperties);
622    
623                    Enumeration<String> enu =
624                            (Enumeration<String>)indexesPropertiesObj.propertyNames();
625    
626                    while (enu.hasMoreElements()) {
627                            String key = enu.nextElement();
628    
629                            String value = indexesPropertiesObj.getProperty(key);
630    
631                            indexesPropertiesObj.setProperty(key.toLowerCase(), value);
632                    }
633    
634                    for (Index index : indexes) {
635                            String indexNameUpperCase = index.getIndexName().toUpperCase();
636                            String indexNameLowerCase = indexNameUpperCase.toLowerCase();
637                            String tableName = index.getTableName();
638                            String tableNameLowerCase = tableName.toLowerCase();
639                            boolean unique = index.isUnique();
640    
641                            validIndexNames.add(indexNameUpperCase);
642    
643                            if (indexesPropertiesObj.containsKey(indexNameLowerCase)) {
644                                    if (unique &&
645                                            indexesSQLLowerCase.contains(
646                                                    "create unique index " + indexNameLowerCase + " ")) {
647    
648                                            continue;
649                                    }
650    
651                                    if (!unique &&
652                                            indexesSQLLowerCase.contains(
653                                                    "create index " + indexNameLowerCase + " ")) {
654    
655                                            continue;
656                                    }
657                            }
658                            else {
659                                    if (!tablesSQLLowerCase.contains(
660                                                    "create table " + tableNameLowerCase + " (")) {
661    
662                                            continue;
663                                    }
664                            }
665    
666                            validIndexNames.remove(indexNameUpperCase);
667    
668                            db.runSQL("drop index " + indexNameUpperCase + " on " + tableName);
669                    }
670    
671                    return validIndexNames;
672            }
673    
674            protected String evaluateVM(String template) throws Exception {
675                    Map<String, Object> variables = new HashMap<String, Object>();
676    
677                    variables.put("counter", new SimpleCounter());
678    
679                    template = VelocityUtil.evaluate(template, variables);
680    
681                    // Trim insert statements because it breaks MySQL Query Browser
682    
683                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
684                            new UnsyncStringReader(template));
685    
686                    StringBundler sb = new StringBundler();
687    
688                    String line = null;
689    
690                    while ((line = unsyncBufferedReader.readLine()) != null) {
691                            line = line.trim();
692    
693                            sb.append(line);
694                            sb.append("\n");
695                    }
696    
697                    unsyncBufferedReader.close();
698    
699                    template = sb.toString();
700                    template = StringUtil.replace(template, "\n\n\n", "\n\n");
701    
702                    return template;
703            }
704    
705            protected abstract String getServerName();
706    
707            protected String getSuffix(int type) {
708                    if (type == MINIMAL) {
709                            return "-minimal";
710                    }
711                    else if (type == SHARDED) {
712                            return "-sharded";
713                    }
714                    else {
715                            return StringPool.BLANK;
716                    }
717            }
718    
719            protected abstract String[] getTemplate();
720    
721            protected String readFile(String fileName) throws IOException {
722                    if (FileUtil.exists(fileName)) {
723                            return FileUtil.read(fileName);
724                    }
725                    else {
726                            return StringPool.BLANK;
727                    }
728            }
729    
730            protected String readSQL(String fileName, String comments, String eol)
731                    throws IOException {
732    
733                    if (!FileUtil.exists(fileName)) {
734                            return StringPool.BLANK;
735                    }
736    
737                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
738                            new FileReader(new File(fileName)));
739    
740                    StringBundler sb = new StringBundler();
741    
742                    String line = null;
743    
744                    while ((line = unsyncBufferedReader.readLine()) != null) {
745                            if (!line.startsWith(comments)) {
746                                    line = StringUtil.replace(
747                                            line,
748                                            new String[] {"\n", "\t"},
749                                            new String[] {"", ""});
750    
751                                    if (line.endsWith(";")) {
752                                            sb.append(line.substring(0, line.length() - 1));
753                                            sb.append(eol);
754                                    }
755                                    else {
756                                            sb.append(line);
757                                    }
758                            }
759                    }
760    
761                    unsyncBufferedReader.close();
762    
763                    return sb.toString();
764            }
765    
766            protected String removeBooleanIndexes(String sqlDir, String data)
767                    throws IOException {
768    
769                    String portalData = readFile(sqlDir + "/portal-tables.sql");
770    
771                    if (Validator.isNull(portalData)) {
772                            return StringPool.BLANK;
773                    }
774    
775                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
776                            new UnsyncStringReader(data));
777    
778                    StringBundler sb = new StringBundler();
779    
780                    String line = null;
781    
782                    while ((line = unsyncBufferedReader.readLine()) != null) {
783                            boolean append = true;
784    
785                            int x = line.indexOf(" on ");
786    
787                            if (x != -1) {
788                                    int y = line.indexOf(" (", x);
789    
790                                    String table = line.substring(x + 4, y);
791    
792                                    x = y + 2;
793                                    y = line.indexOf(")", x);
794    
795                                    String[] columns = StringUtil.split(line.substring(x, y));
796    
797                                    x = portalData.indexOf("create table " + table + " (");
798                                    y = portalData.indexOf(");", x);
799    
800                                    String portalTableData = portalData.substring(x, y);
801    
802                                    for (int i = 0; i < columns.length; i++) {
803                                            if (portalTableData.indexOf(
804                                                            columns[i].trim() + " BOOLEAN") != -1) {
805    
806                                                    append = false;
807    
808                                                    break;
809                                            }
810                                    }
811                            }
812    
813                            if (append) {
814                                    sb.append(line);
815                                    sb.append("\n");
816                            }
817                    }
818    
819                    unsyncBufferedReader.close();
820    
821                    return sb.toString();
822            }
823    
824            protected String removeInserts(String data) throws IOException {
825                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
826                            new UnsyncStringReader(data));
827    
828                    StringBundler sb = new StringBundler();
829    
830                    String line = null;
831    
832                    while ((line = unsyncBufferedReader.readLine()) != null) {
833                            if (!line.startsWith("insert into ") &&
834                                    !line.startsWith("update ")) {
835    
836                                    sb.append(line);
837                                    sb.append("\n");
838                            }
839                    }
840    
841                    unsyncBufferedReader.close();
842    
843                    return sb.toString();
844            }
845    
846            protected String removeLongInserts(String data) throws IOException {
847                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
848                            new UnsyncStringReader(data));
849    
850                    StringBundler sb = new StringBundler();
851    
852                    String line = null;
853    
854                    while ((line = unsyncBufferedReader.readLine()) != null) {
855                            if (!line.startsWith("insert into Image (") &&
856                                    !line.startsWith("insert into JournalArticle (") &&
857                                    !line.startsWith("insert into JournalStructure (") &&
858                                    !line.startsWith("insert into JournalTemplate (")) {
859    
860                                    sb.append(line);
861                                    sb.append("\n");
862                            }
863                    }
864    
865                    unsyncBufferedReader.close();
866    
867                    return sb.toString();
868            }
869    
870            protected String removeNull(String content) {
871                    content = StringUtil.replace(content, " is null", " IS NULL");
872                    content = StringUtil.replace(content, " not null", " not_null");
873                    content = StringUtil.replace(content, " null", "");
874                    content = StringUtil.replace(content, " not_null", " not null");
875    
876                    return content;
877            }
878    
879            protected String replaceTemplate(String template, String[] actual) {
880                    if ((template == null) || (TEMPLATE == null) || (actual == null)) {
881                            return null;
882                    }
883    
884                    if (TEMPLATE.length != actual.length) {
885                            return template;
886                    }
887    
888                    for (int i = 0; i < TEMPLATE.length; i++) {
889                            if (TEMPLATE[i].equals("##") ||
890                                    TEMPLATE[i].equals("'01/01/1970'")) {
891    
892                                    template = template.replaceAll(TEMPLATE[i], actual[i]);
893                            }
894                            else {
895                                    template = template.replaceAll(
896                                            "\\b" + TEMPLATE[i] + "\\b", actual[i]);
897                            }
898                    }
899    
900                    return template;
901            }
902    
903            protected abstract String reword(String data) throws IOException;
904    
905            protected static String ALTER_COLUMN_TYPE = "alter_column_type ";
906    
907            protected static String ALTER_COLUMN_NAME = "alter_column_name ";
908    
909            protected static String DROP_INDEX = "drop index";
910    
911            protected static String DROP_PRIMARY_KEY = "drop primary key";
912    
913            protected static String[] REWORD_TEMPLATE = {
914                    "@table@", "@old-column@", "@new-column@", "@type@", "@nullable@"
915            };
916    
917            protected static String[] TEMPLATE = {
918                    "##", "TRUE", "FALSE",
919                    "'01/01/1970'", "CURRENT_TIMESTAMP",
920                    " BLOB", " BOOLEAN", " DATE",
921                    " DOUBLE", " INTEGER", " LONG",
922                    " STRING", " TEXT", " VARCHAR",
923                    " IDENTITY", "COMMIT_TRANSACTION"
924            };
925    
926            private static boolean _SUPPORTS_ALTER_COLUMN_NAME = true;
927    
928            private static boolean _SUPPORTS_ALTER_COLUMN_TYPE = true;
929    
930            private static boolean _SUPPORTS_DATE_MILLISECONDS = true;
931    
932            private static boolean _SUPPORTS_SCROLLABLE_RESULTS = true;
933    
934            private static boolean _SUPPORTS_UPDATE_WITH_INNER_JOIN;
935    
936            private static Log _log = LogFactoryUtil.getLog(BaseDB.class);
937    
938            private String _type;
939            private boolean _supportsStringCaseSensitiveQuery;
940    
941    }