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 sb.append("connect to ");
122 sb.append(databaseName);
123 sb.append(";\n");
124 sb.append(getCreateTablesContent(sqlDir, suffix));
125 sb.append("\n\n");
126 sb.append(readFile(sqlDir + "/indexes/indexes-db2.sql"));
127 sb.append("\n\n");
128 sb.append(readFile(sqlDir + "/sequences/sequences-db2.sql"));
129
130 return sb.toString();
131 }
132
133 @Override
134 protected String getServerName() {
135 return "db2";
136 }
137
138 @Override
139 protected String[] getTemplate() {
140 return _DB2;
141 }
142
143 protected boolean isRequiresReorgTable(Connection con, String tableName)
144 throws SQLException {
145
146 boolean reorgTableRequired = false;
147
148 PreparedStatement ps = null;
149 ResultSet rs = null;
150
151 try {
152 StringBundler sb = new StringBundler(4);
153
154 sb.append("select num_reorg_rec_alters from table(");
155 sb.append("sysproc.admin_get_tab_info(current_schema, '");
156 sb.append(StringUtil.toUpperCase(tableName));
157 sb.append("')) where reorg_pending = 'Y'");
158
159 ps = con.prepareStatement(sb.toString());
160
161 rs = ps.executeQuery();
162
163 if (rs.next()) {
164 int numReorgRecAlters = rs.getInt(1);
165
166 if (numReorgRecAlters >= 1) {
167 reorgTableRequired = true;
168 }
169 }
170 }
171 finally {
172 DataAccess.cleanUp(null, ps, rs);
173 }
174
175 return reorgTableRequired;
176 }
177
178 protected void reorgTable(Connection con, String tableName)
179 throws SQLException {
180
181 if (!isRequiresReorgTable(con, tableName)) {
182 return;
183 }
184
185 CallableStatement callableStatement = null;
186
187 try {
188 callableStatement = con.prepareCall("call sysproc.admin_cmd(?)");
189
190 callableStatement.setString(1, "reorg table " + tableName);
191
192 callableStatement.execute();
193 }
194 finally {
195 DataAccess.cleanUp(callableStatement);
196 }
197 }
198
199 protected void reorgTables(String[] templates) throws SQLException {
200 Set<String> tableNames = new HashSet<String>();
201
202 for (String template : templates) {
203 if (template.startsWith("alter table")) {
204 tableNames.add(template.split(" ")[2]);
205 }
206 }
207
208 if (tableNames.isEmpty()) {
209 return;
210 }
211
212 Connection con = null;
213
214 try {
215 con = DataAccess.getConnection();
216
217 for (String tableName : tableNames) {
218 reorgTable(con, tableName);
219 }
220 }
221 finally {
222 DataAccess.cleanUp(con);
223 }
224 }
225
226 @Override
227 protected String reword(String data) throws IOException {
228 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
229 new UnsyncStringReader(data));
230
231 StringBundler sb = new StringBundler();
232
233 String line = null;
234
235 while ((line = unsyncBufferedReader.readLine()) != null) {
236 if (line.startsWith(ALTER_COLUMN_NAME)) {
237 String[] template = buildColumnNameTokens(line);
238
239 line = StringUtil.replace(
240 "alter table @table@ add column @new-column@ @type@;\n",
241 REWORD_TEMPLATE, template);
242
243 line = line + StringUtil.replace(
244 "update @table@ set @new-column@ = @old-column@;\n",
245 REWORD_TEMPLATE, template);
246
247 line = line + StringUtil.replace(
248 "alter table @table@ drop column @old-column@",
249 REWORD_TEMPLATE, template);
250 }
251 else if (line.startsWith(ALTER_TABLE_NAME)) {
252 String[] template = buildTableNameTokens(line);
253
254 line = StringUtil.replace(
255 "alter table @old-table@ to @new-table@;",
256 RENAME_TABLE_TEMPLATE, template);
257 }
258 else if (line.contains(DROP_INDEX)) {
259 String[] tokens = StringUtil.split(line, ' ');
260
261 line = StringUtil.replace(
262 "drop index @index@;", "@index@", tokens[2]);
263 }
264
265 sb.append(line);
266 sb.append("\n");
267 }
268
269 unsyncBufferedReader.close();
270
271 return sb.toString();
272 }
273
274 private static final String[] _DB2 = {
275 "--", "1", "0", "'1970-01-01-00.00.00.000000'", "current timestamp",
276 " blob", " blob", " smallint", " timestamp", " double", " integer",
277 " bigint", " varchar(750)", " clob", " varchar",
278 " generated always as identity", "commit"
279 };
280
281 private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = false;
282
283 private static final boolean _SUPPORTS_INLINE_DISTINCT = false;
284
285 private static final boolean _SUPPORTS_SCROLLABLE_RESULTS = false;
286
287 private static DB2DB _instance = new DB2DB();
288
289 }