001    /**
002     * Copyright (c) 2000-2012 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.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
020    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringUtil;
024    
025    import java.io.IOException;
026    
027    import java.sql.CallableStatement;
028    import java.sql.Connection;
029    import java.sql.SQLException;
030    
031    import java.util.HashSet;
032    import java.util.Set;
033    
034    /**
035     * @author Alexander Chow
036     * @author Bruno Farache
037     * @author Sandeep Soni
038     * @author Ganesh Ram
039     */
040    public class DB2DB extends BaseDB {
041    
042            public static DB getInstance() {
043                    return _instance;
044            }
045    
046            @Override
047            public String buildSQL(String template) throws IOException {
048                    template = convertTimestamp(template);
049                    template = replaceTemplate(template, getTemplate());
050    
051                    template = reword(template);
052                    template = removeLongInserts(template);
053                    template = removeNull(template);
054                    template = StringUtil.replace(template, "\\'", "''");
055    
056                    return template;
057            }
058    
059            @Override
060            public boolean isSupportsAlterColumnType() {
061                    return _SUPPORTS_ALTER_COLUMN_TYPE;
062            }
063    
064            @Override
065            public boolean isSupportsInlineDistinct() {
066                    return _SUPPORTS_INLINE_DISTINCT;
067            }
068    
069            @Override
070            public boolean isSupportsScrollableResults() {
071                    return _SUPPORTS_SCROLLABLE_RESULTS;
072            }
073    
074            @Override
075            public void runSQL(String template) throws IOException, SQLException {
076                    if (template.startsWith(ALTER_COLUMN_NAME)) {
077                            String sql = buildSQL(template);
078    
079                            String[] alterSqls = StringUtil.split(sql, CharPool.SEMICOLON);
080    
081                            for (String alterSql : alterSqls) {
082                                    runSQL(alterSql);
083                            }
084                    }
085                    else {
086                            super.runSQL(template);
087                    }
088            }
089    
090            @Override
091            public void runSQL(String[] templates) throws IOException, SQLException {
092                    super.runSQL(templates);
093    
094                    _reorgTables(templates);
095            }
096    
097            protected DB2DB() {
098                    super(TYPE_DB2);
099            }
100    
101            @Override
102            protected String buildCreateFileContent(
103                            String sqlDir, String databaseName, int population)
104                    throws IOException {
105    
106                    String suffix = getSuffix(population);
107    
108                    StringBundler sb = new StringBundler(14);
109    
110                    sb.append("drop database ");
111                    sb.append(databaseName);
112                    sb.append(";\n");
113                    sb.append("create database ");
114                    sb.append(databaseName);
115                    sb.append(" pagesize 8192;\n");
116                    sb.append("connect to ");
117                    sb.append(databaseName);
118                    sb.append(";\n");
119                    sb.append(
120                            readFile(
121                                    sqlDir + "/portal" + suffix + "/portal" + suffix + "-db2.sql"));
122                    sb.append("\n\n");
123                    sb.append(readFile(sqlDir + "/indexes/indexes-db2.sql"));
124                    sb.append("\n\n");
125                    sb.append(readFile(sqlDir + "/sequences/sequences-db2.sql"));
126    
127                    return sb.toString();
128            }
129    
130            @Override
131            protected String getServerName() {
132                    return "db2";
133            }
134    
135            @Override
136            protected String[] getTemplate() {
137                    return _DB2;
138            }
139    
140            @Override
141            protected String reword(String data) throws IOException {
142                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
143                            new UnsyncStringReader(data));
144    
145                    StringBundler sb = new StringBundler();
146    
147                    String line = null;
148    
149                    while ((line = unsyncBufferedReader.readLine()) != null) {
150                            if (line.startsWith(ALTER_COLUMN_NAME)) {
151                                    String[] template = buildColumnNameTokens(line);
152    
153                                    line = StringUtil.replace(
154                                            "alter table @table@ add column @new-column@ @type@;\n",
155                                            REWORD_TEMPLATE, template);
156    
157                                    line = line + StringUtil.replace(
158                                            "update @table@ set @new-column@ = @old-column@;\n",
159                                            REWORD_TEMPLATE, template);
160    
161                                    line = line + StringUtil.replace(
162                                            "alter table @table@ drop column @old-column@",
163                                            REWORD_TEMPLATE, template);
164                            }
165                            else if (line.indexOf(DROP_INDEX) != -1) {
166                                    String[] tokens = StringUtil.split(line, ' ');
167    
168                                    line = StringUtil.replace(
169                                            "drop index @index@;", "@index@", tokens[2]);
170                            }
171    
172                            sb.append(line);
173                            sb.append("\n");
174                    }
175    
176                    unsyncBufferedReader.close();
177    
178                    return sb.toString();
179            }
180    
181            private void _reorgTables(String[] templates) throws SQLException {
182                    Set<String> tableNames = new HashSet<String>();
183    
184                    for (String template : templates) {
185                            if (template.startsWith("alter table")) {
186                                    tableNames.add(template.split(" ")[2]);
187                            }
188                    }
189    
190                    if (tableNames.size() == 0) {
191                            return;
192                    }
193    
194                    Connection con = null;
195                    CallableStatement callStmt = null;
196    
197                    try {
198                            con = DataAccess.getConnection();
199    
200                            for (String tableName : tableNames) {
201                                    String sql = "call sysproc.admin_cmd(?)";
202    
203                                    callStmt = con.prepareCall(sql);
204    
205                                    String param = "reorg table " + tableName;
206    
207                                    callStmt.setString(1, param);
208    
209                                    callStmt.execute();
210                            }
211                    }
212                    finally {
213                            DataAccess.cleanUp(con, callStmt);
214                    }
215            }
216    
217            private static final String[] _DB2 = {
218                    "--", "1", "0", "'1970-01-01-00.00.00.000000'", "current timestamp",
219                    " blob", " blob", " smallint", " timestamp", " double", " integer",
220                    " bigint", " varchar(500)", " clob", " varchar",
221                    " generated always as identity", "commit"
222            };
223    
224            private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = false;
225    
226            private static final boolean _SUPPORTS_INLINE_DISTINCT = false;
227    
228            private static final boolean _SUPPORTS_SCROLLABLE_RESULTS = false;
229    
230            private static DB2DB _instance = new DB2DB();
231    
232    }