001
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.PreparedStatement;
030 import java.sql.ResultSet;
031 import java.sql.SQLException;
032
033 import java.util.HashSet;
034 import java.util.Set;
035
036
042 public class DB2DB extends BaseDB {
043
044 public static DB getInstance() {
045 return _instance;
046 }
047
048 @Override
049 public String buildSQL(String template) throws IOException {
050 template = convertTimestamp(template);
051 template = replaceTemplate(template, getTemplate());
052
053 template = reword(template);
054 template = removeLongInserts(template);
055 template = removeNull(template);
056 template = StringUtil.replace(template, "\\'", "''");
057 template = StringUtil.replace(template, "\\n", "'||CHR(10)||'");
058
059 return template;
060 }
061
062 @Override
063 public boolean isSupportsAlterColumnType() {
064 return _SUPPORTS_ALTER_COLUMN_TYPE;
065 }
066
067 @Override
068 public boolean isSupportsInlineDistinct() {
069 return _SUPPORTS_INLINE_DISTINCT;
070 }
071
072 @Override
073 public boolean isSupportsScrollableResults() {
074 return _SUPPORTS_SCROLLABLE_RESULTS;
075 }
076
077 @Override
078 public void runSQL(String template) throws IOException, SQLException {
079 if (template.startsWith(ALTER_COLUMN_NAME)) {
080 String sql = buildSQL(template);
081
082 String[] alterSqls = StringUtil.split(sql, CharPool.SEMICOLON);
083
084 for (String alterSql : alterSqls) {
085 alterSql = StringUtil.trim(alterSql);
086
087 runSQL(alterSql);
088 }
089 }
090 else {
091 super.runSQL(template);
092 }
093 }
094
095 @Override
096 public void runSQL(String[] templates) throws IOException, SQLException {
097 super.runSQL(templates);
098
099 reorgTables(templates);
100 }
101
102 protected DB2DB() {
103 super(TYPE_DB2);
104 }
105
106 @Override
107 protected String buildCreateFileContent(
108 String sqlDir, String databaseName, int population)
109 throws IOException {
110
111 String suffix = getSuffix(population);
112
113 StringBundler sb = new StringBundler(14);
114
115 sb.append("drop database ");
116 sb.append(databaseName);
117 sb.append(";\n");
118 sb.append("create database ");
119 sb.append(databaseName);
120 sb.append(" pagesize 8192;\n");
121
122 if (population != BARE) {
123 sb.append("connect to ");
124 sb.append(databaseName);
125 sb.append(";\n");
126 sb.append(getCreateTablesContent(sqlDir, suffix));
127 sb.append("\n\n");
128 sb.append(readFile(sqlDir + "/indexes/indexes-db2.sql"));
129 sb.append("\n\n");
130 sb.append(readFile(sqlDir + "/sequences/sequences-db2.sql"));
131 }
132
133 return sb.toString();
134 }
135
136 @Override
137 protected String getServerName() {
138 return "db2";
139 }
140
141 @Override
142 protected String[] getTemplate() {
143 return _DB2;
144 }
145
146 protected boolean isRequiresReorgTable(Connection con, String tableName)
147 throws SQLException {
148
149 boolean reorgTableRequired = false;
150
151 PreparedStatement ps = null;
152 ResultSet rs = null;
153
154 try {
155 StringBundler sb = new StringBundler(4);
156
157 sb.append("select num_reorg_rec_alters from table(");
158 sb.append("sysproc.admin_get_tab_info(current_schema, '");
159 sb.append(StringUtil.toUpperCase(tableName));
160 sb.append("')) where reorg_pending = 'Y'");
161
162 ps = con.prepareStatement(sb.toString());
163
164 rs = ps.executeQuery();
165
166 if (rs.next()) {
167 int numReorgRecAlters = rs.getInt(1);
168
169 if (numReorgRecAlters >= 1) {
170 reorgTableRequired = true;
171 }
172 }
173 }
174 finally {
175 DataAccess.cleanUp(null, ps, rs);
176 }
177
178 return reorgTableRequired;
179 }
180
181 protected void reorgTable(Connection con, String tableName)
182 throws SQLException {
183
184 if (!isRequiresReorgTable(con, tableName)) {
185 return;
186 }
187
188 CallableStatement callableStatement = null;
189
190 try {
191 callableStatement = con.prepareCall("call sysproc.admin_cmd(?)");
192
193 callableStatement.setString(1, "reorg table " + tableName);
194
195 callableStatement.execute();
196 }
197 finally {
198 DataAccess.cleanUp(callableStatement);
199 }
200 }
201
202 protected void reorgTables(String[] templates) throws SQLException {
203 Set<String> tableNames = new HashSet<String>();
204
205 for (String template : templates) {
206 if (template.startsWith("alter table")) {
207 tableNames.add(template.split(" ")[2]);
208 }
209 }
210
211 if (tableNames.isEmpty()) {
212 return;
213 }
214
215 Connection con = null;
216
217 try {
218 con = DataAccess.getConnection();
219
220 for (String tableName : tableNames) {
221 reorgTable(con, tableName);
222 }
223 }
224 finally {
225 DataAccess.cleanUp(con);
226 }
227 }
228
229 @Override
230 protected String reword(String data) throws IOException {
231 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
232 new UnsyncStringReader(data));
233
234 StringBundler sb = new StringBundler();
235
236 String line = null;
237
238 while ((line = unsyncBufferedReader.readLine()) != null) {
239 if (line.startsWith(ALTER_COLUMN_NAME)) {
240 String[] template = buildColumnNameTokens(line);
241
242 line = StringUtil.replace(
243 "alter table @table@ add column @new-column@ @type@;\n",
244 REWORD_TEMPLATE, template);
245
246 line = line + StringUtil.replace(
247 "update @table@ set @new-column@ = @old-column@;\n",
248 REWORD_TEMPLATE, template);
249
250 line = line + StringUtil.replace(
251 "alter table @table@ drop column @old-column@",
252 REWORD_TEMPLATE, template);
253 }
254 else if (line.startsWith(ALTER_TABLE_NAME)) {
255 String[] template = buildTableNameTokens(line);
256
257 line = StringUtil.replace(
258 "alter table @old-table@ to @new-table@;",
259 RENAME_TABLE_TEMPLATE, template);
260 }
261 else if (line.contains(DROP_INDEX)) {
262 String[] tokens = StringUtil.split(line, ' ');
263
264 line = StringUtil.replace(
265 "drop index @index@;", "@index@", tokens[2]);
266 }
267
268 sb.append(line);
269 sb.append("\n");
270 }
271
272 unsyncBufferedReader.close();
273
274 return sb.toString();
275 }
276
277 private static final String[] _DB2 = {
278 "--", "1", "0", "'1970-01-01-00.00.00.000000'", "current timestamp",
279 " blob", " blob", " smallint", " timestamp", " double", " integer",
280 " bigint", " varchar(750)", " clob", " varchar",
281 " generated always as identity", "commit"
282 };
283
284 private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = false;
285
286 private static final boolean _SUPPORTS_INLINE_DISTINCT = false;
287
288 private static final boolean _SUPPORTS_SCROLLABLE_RESULTS = false;
289
290 private static DB2DB _instance = new DB2DB();
291
292 }