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