001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.core.framework.persistence.platform; 017 018import org.apache.ojb.broker.PersistenceBroker; 019import org.apache.ojb.broker.accesslayer.LookupException; 020import org.kuali.rice.core.api.config.property.ConfigContext; 021import org.kuali.rice.core.api.util.RiceConstants; 022 023import java.sql.Connection; 024import java.sql.PreparedStatement; 025import java.sql.ResultSet; 026import java.sql.SQLException; 027import java.util.regex.Pattern; 028 029/** 030 * DatabasePlatform implementation that generates Oracle-compliant SQL 031 * @author Kuali Rice Team (rice.collab@kuali.org) 032 */ 033public class OracleDatabasePlatform extends ANSISqlDatabasePlatform { 034 035 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OracleDatabasePlatform.class); 036 private static final long DEFAULT_TIMEOUT_SECONDS = 60 * 60; // default to 1 hour 037 public static final long WAIT_FOREVER = -1; 038 039 private static final Pattern APOS_PAT = Pattern.compile("'"); 040 041 @Override 042 public String applyLimitSql(Integer limit) { 043 if (limit != null) { 044 return "rownum <= " + limit.intValue(); 045 } 046 return null; 047 } 048 049 public String getStrToDateFunction() { 050 return "TO_DATE"; 051 } 052 053 public String getCurTimeFunction() { 054 return "sysdate"; 055 } 056 057 public String getDateFormatString(String dateFormatString) { 058 return "'" + dateFormatString + "'"; 059 } 060 061 /** 062 * Generate next id value for the logical sequence given the JDBC Connection 063 * @param sequenceName the logical sequence name 064 * @param connection JDBC Connection to use (without closing) 065 * @return next id in sequence or RuntimeException on error 066 */ 067 @Override 068 protected Long getNextValSqlJdbc(String sequenceName, Connection connection) { 069 PreparedStatement statement = null; 070 ResultSet resultSet = null; 071 try { 072 statement = connection.prepareStatement("select " + sequenceName + ".nextval from dual"); 073 resultSet = statement.executeQuery(); 074 075 if (!resultSet.next()) { 076 throw new RuntimeException("Error retrieving next option id for action list from sequence."); 077 } 078 return new Long(resultSet.getLong(1)); 079 } catch (SQLException e) { 080 throw new RuntimeException("Error retrieving next option id for action list from sequence.", e); 081 } finally { 082 if (statement != null) { 083 try { 084 statement.close(); 085 } catch (SQLException e) { 086 } 087 } 088 if (resultSet != null) { 089 try { 090 resultSet.close(); 091 } catch (SQLException e) { 092 } 093 } 094 } 095 } 096 097 @Deprecated 098 @Override 099 protected Long getNextValSqlOjb(String sequenceName, PersistenceBroker persistenceBroker) { 100 try { 101 Connection connection = persistenceBroker.serviceConnectionManager().getConnection(); 102 return getNextValSqlJdbc(sequenceName, connection); 103 } catch (LookupException e) { 104 throw new RuntimeException("Error retrieving next option id for action list from sequence.", e); 105 } 106 } 107 108 public String getLockRouteHeaderQuerySQL(String documentId, boolean wait) { 109 long timeoutSeconds = getTimeoutSeconds(); 110 String waitClause = ""; 111 if (!wait) { 112 waitClause = " NOWAIT"; 113 } else if (wait && timeoutSeconds > 0) { 114 waitClause = " WAIT " + timeoutSeconds; 115 } 116 return "SELECT DOC_HDR_ID FROM KREW_DOC_HDR_T WHERE DOC_HDR_ID=? FOR UPDATE" + waitClause; 117 } 118 119 public String toString() { 120 return "[OracleDatabasePlatform]"; 121 } 122 123 protected long getTimeoutSeconds() { 124 String timeoutValue = ConfigContext.getCurrentContextConfig().getDocumentLockTimeout(); 125 if (timeoutValue != null) { 126 try { 127 return Long.parseLong(timeoutValue); 128 } catch (NumberFormatException e) { 129 LOG.warn("Failed to parse document lock timeout as it was not a valid number: " + timeoutValue); 130 } 131 } 132 return DEFAULT_TIMEOUT_SECONDS; 133 } 134 135 public String getSelectForUpdateSuffix(long waitMillis) { 136 String sql = "for update"; 137 if (WAIT_FOREVER == waitMillis) { 138 // do nothing 139 LOG.warn("Selecting for update and waiting forever..."); 140 } else if (RiceConstants.NO_WAIT == waitMillis) { 141 sql += " nowait"; 142 } else { 143 // Oracle only supports wait time in seconds... 144 long seconds = waitMillis / 1000; 145 if (seconds == 0) seconds = 1; 146 sql += " wait " + seconds; 147 } 148 return sql; 149 } 150 151 /** 152 * Performs Oracle-specific escaping of String parameters. 153 * 154 * @see DatabasePlatform#escapeString(java.lang.String) 155 */ 156 public String escapeString(String sqlString) { 157 return (sqlString != null) ? APOS_PAT.matcher(sqlString).replaceAll("''") : null; 158 } 159 160 /** 161 * Converts date-only values into JDBC d{...} date literals, but converts date-and-time values into timestamp 162 * strings that are then converted into date values via the strToDateFunction. 163 * 164 * @see ANSISqlDatabasePlatform#getDateSQL(java.lang.String, java.lang.String) 165 */ 166 @Override 167 public String getDateSQL(String date, String time) { 168 String d = date.replace('/', '-'); 169 if (time == null) { 170 return new StringBuilder("{d '").append(d).append("'}").toString(); 171 } else { 172 return new StringBuilder(getStrToDateFunction()).append("('").append(d).append(" ").append( 173 time).append("', 'YYYY-MM-DD HH24:MI:SS')").toString(); 174 } 175 } 176 177 @Override 178 public String getValidationQuery() { 179 return "select 1 from dual"; 180 } 181 182}