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