001    /**
002     * Copyright (c) 2000-present 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.verify;
016    
017    import com.liferay.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.DBManagerUtil;
019    import com.liferay.portal.kernel.dao.db.DBType;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.LoggingTimer;
024    import com.liferay.portal.kernel.util.ReleaseInfo;
025    import com.liferay.portal.kernel.util.StringBundler;
026    
027    import java.sql.PreparedStatement;
028    import java.sql.ResultSet;
029    import java.sql.SQLException;
030    
031    /**
032     * @author Ivica Cardic
033     * @author Brian Wing Shun Chan
034     */
035    public class VerifyOracle extends VerifyProcess {
036    
037            protected void alterVarchar2Columns() throws Exception {
038                    try (LoggingTimer loggingTimer = new LoggingTimer();
039                            PreparedStatement ps = connection.prepareStatement(
040                                    "select table_name, column_name, data_length from " +
041                                            "user_tab_columns where data_type = 'VARCHAR2' and " +
042                                                    "char_used = 'B'");
043                            ResultSet rs = ps.executeQuery()) {
044    
045                            int buildNumber = getBuildNumber();
046    
047                            while (rs.next()) {
048                                    String tableName = rs.getString(1);
049    
050                                    if (!isPortalTableName(tableName)) {
051                                            continue;
052                                    }
053    
054                                    String columnName = rs.getString(2);
055                                    int dataLength = rs.getInt(3);
056    
057                                    if (isBetweenBuildNumbers(
058                                                    buildNumber, ReleaseInfo.RELEASE_5_2_9_BUILD_NUMBER,
059                                                    ReleaseInfo.RELEASE_6_0_0_BUILD_NUMBER) ||
060                                            isBetweenBuildNumbers(
061                                                    buildNumber, ReleaseInfo.RELEASE_6_0_5_BUILD_NUMBER,
062                                                    ReleaseInfo.RELEASE_6_1_20_BUILD_NUMBER)) {
063    
064                                            // LPS-33903
065    
066                                            if (!ArrayUtil.contains(
067                                                            _ORIGINAL_DATA_LENGTH_VALUES, dataLength)) {
068    
069                                                    dataLength = dataLength / 4;
070                                            }
071                                    }
072    
073                                    try {
074                                            runSQL(
075                                                    "alter table " + tableName + " modify " + columnName +
076                                                            " varchar2(" + dataLength + " char)");
077                                    }
078                                    catch (SQLException sqle) {
079                                            if (sqle.getErrorCode() == 1441) {
080                                                    if (_log.isWarnEnabled()) {
081                                                            StringBundler sb = new StringBundler(6);
082    
083                                                            sb.append("Unable to alter length of column ");
084                                                            sb.append(columnName);
085                                                            sb.append(" for table ");
086                                                            sb.append(tableName);
087                                                            sb.append(" because it contains values that are ");
088                                                            sb.append("larger than the new column length");
089    
090                                                            _log.warn(sb.toString());
091                                                    }
092                                            }
093                                            else {
094                                                    throw sqle;
095                                            }
096                                    }
097                            }
098                    }
099            }
100    
101            @Override
102            protected void doVerify() throws Exception {
103                    DB db = DBManagerUtil.getDB();
104    
105                    if (db.getDBType() != DBType.ORACLE) {
106                            return;
107                    }
108    
109                    alterVarchar2Columns();
110            }
111    
112            protected boolean isBetweenBuildNumbers(
113                    int buildNumber, int startBuildNumber, int endBuildNumber) {
114    
115                    if ((buildNumber >= startBuildNumber) &&
116                            (buildNumber < endBuildNumber)) {
117    
118                            return true;
119                    }
120    
121                    return false;
122            }
123    
124            private static final int[] _ORIGINAL_DATA_LENGTH_VALUES = {
125                    75, 100, 150, 200, 255, 500, 1000, 1024, 2000, 4000
126            };
127    
128            private static final Log _log = LogFactoryUtil.getLog(VerifyOracle.class);
129    
130    }