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