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