KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > torque > adapter > DBOracle


1 package org.apache.torque.adapter;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements. See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership. The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License. You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied. See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */

21
22 import java.sql.Connection JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import java.sql.Statement JavaDoc;
25 import java.text.SimpleDateFormat JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.ListIterator JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import org.apache.torque.util.Query;
32 import org.apache.torque.util.UniqueList;
33
34 /**
35  * This code should be used for an Oracle database pool.
36  *
37  * @author <a HREF="mailto:jon@clearink.com">Jon S. Stevens</a>
38  * @author <a HREF="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
39  * @author <a HREF="mailto:bschneider@vecna.com">Bill Schneider</a>
40  * @author <a HREF="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
41  * @version $Id: DBOracle.java 476550 2006-11-18 16:08:37Z tfischer $
42  */

43 public class DBOracle extends AbstractDBAdapter
44 {
45     /**
46      * Serial version
47      */

48     private static final long serialVersionUID = 8966976210230241194L;
49
50     /** date format used in getDateString() */
51     private static final String JavaDoc DATE_FORMAT = "dd-MM-yyyy HH:mm:ss";
52
53     /**
54      * Empty constructor.
55      */

56     protected DBOracle()
57     {
58     }
59
60     /**
61      * This method is used to ignore case.
62      *
63      * @param in The string to transform to upper case.
64      * @return The upper case string.
65      */

66     public String JavaDoc toUpperCase(String JavaDoc in)
67     {
68         return new StringBuffer JavaDoc("UPPER(").append(in).append(")").toString();
69     }
70
71     /**
72      * This method is used to ignore case.
73      *
74      * @param in The string whose case to ignore.
75      * @return The string in a case that can be ignored.
76      */

77     public String JavaDoc ignoreCase(String JavaDoc in)
78     {
79         return new StringBuffer JavaDoc("UPPER(").append(in).append(")").toString();
80     }
81
82     /**
83      * This method is used to format any date string.
84      *
85      * @param date the Date to format
86      * @return The date formatted String for Oracle.
87      */

88     public String JavaDoc getDateString(Date JavaDoc date)
89     {
90         return "TO_DATE('" + new SimpleDateFormat JavaDoc(DATE_FORMAT).format(date)
91                 + "', 'DD-MM-YYYY HH24:MI:SS')";
92     }
93
94     /**
95      * @see org.apache.torque.adapter.DB#getIDMethodType()
96      */

97     public String JavaDoc getIDMethodType()
98     {
99         return SEQUENCE;
100     }
101
102     /**
103      * Returns the next key from a sequence. Uses the following
104      * implementation:
105      *
106      * <blockquote><code><pre>
107      * select sequenceName.nextval from dual
108      * </pre></code></blockquote>
109      *
110      * @param sequenceName The name of the sequence (should be of type
111      * <code>String</code>).
112      * @return SQL to retreive the next database key.
113      * @see org.apache.torque.adapter.DB#getIDMethodSQL(Object)
114      */

115     public String JavaDoc getIDMethodSQL(Object JavaDoc sequenceName)
116     {
117         return ("select " + sequenceName + ".nextval from dual");
118     }
119
120     /**
121      * Locks the specified table.
122      *
123      * @param con The JDBC connection to use.
124      * @param table The name of the table to lock.
125      * @exception SQLException No Statement could be created or executed.
126      */

127     public void lockTable(Connection JavaDoc con, String JavaDoc table) throws SQLException JavaDoc
128     {
129         Statement JavaDoc statement = con.createStatement();
130
131         StringBuffer JavaDoc stmt = new StringBuffer JavaDoc();
132         stmt.append("SELECT next_id FROM ")
133                 .append(table)
134                 .append(" FOR UPDATE");
135
136         statement.executeQuery(stmt.toString());
137     }
138
139     /**
140      * Unlocks the specified table.
141      *
142      * @param con The JDBC connection to use.
143      * @param table The name of the table to unlock.
144      * @exception SQLException No Statement could be created or executed.
145      */

146     public void unlockTable(Connection JavaDoc con, String JavaDoc table) throws SQLException JavaDoc
147     {
148         // Tables in Oracle are unlocked when a commit is issued. The
149
// user may have issued a commit but do it here to be sure.
150
con.commit();
151     }
152
153     /**
154      * This method is used to check whether the database supports
155      * limiting the size of the resultset.
156      *
157      * @return LIMIT_STYLE_ORACLE.
158      * @deprecated This should not be exposed to the outside
159      */

160     public int getLimitStyle()
161     {
162         return DB.LIMIT_STYLE_ORACLE;
163     }
164
165     /**
166      * Return true for Oracle
167      * @see org.apache.torque.adapter.AbstractDBAdapter#supportsNativeLimit()
168      */

169     public boolean supportsNativeLimit()
170     {
171         return true;
172     }
173
174     /**
175      * Return true for Oracle
176      * @see org.apache.torque.adapter.AbstractDBAdapter#supportsNativeOffset()
177      */

178     public boolean supportsNativeOffset()
179     {
180         return true;
181     }
182
183     /**
184      * Build Oracle-style query with limit or offset.
185      * If the original SQL is in variable: query then the requlting
186      * SQL looks like this:
187      * <pre>
188      * SELECT B.* FROM (
189      * SELECT A.*, rownum as TORQUE$ROWNUM FROM (
190      * query
191      * ) A
192      * ) B WHERE B.TORQUE$ROWNUM > offset AND B.TORQUE$ROWNUM
193      * <= offset + limit
194      * </pre>
195      *
196      * @param query The query to modify
197      * @param offset the offset Value
198      * @param limit the limit Value
199      */

200     public void generateLimits(Query query, int offset, int limit)
201     {
202         StringBuffer JavaDoc preLimit = new StringBuffer JavaDoc()
203         .append("SELECT B.* FROM ( ")
204         .append("SELECT A.*, rownum AS TORQUE$ROWNUM FROM ( ");
205
206         StringBuffer JavaDoc postLimit = new StringBuffer JavaDoc()
207                 .append(" ) A ")
208                 .append(" ) B WHERE ");
209
210         if (offset > 0)
211         {
212             postLimit.append(" B.TORQUE$ROWNUM > ")
213                     .append(offset);
214
215             if (limit >= 0)
216             {
217                 postLimit.append(" AND B.TORQUE$ROWNUM <= ")
218                         .append(offset + limit);
219             }
220         }
221         else
222         {
223             postLimit.append(" B.TORQUE$ROWNUM <= ")
224                     .append(limit);
225         }
226
227         query.setPreLimit(preLimit.toString());
228         query.setPostLimit(postLimit.toString());
229         query.setLimit(null);
230
231         // the query must not contain same column names or aliases.
232
// Find double column names and aliases and create unique aliases
233
// TODO: does not work for functions yet
234
UniqueList selectColumns = query.getSelectClause();
235         int replacementSuffix = 0;
236         Set JavaDoc columnNames = new HashSet JavaDoc();
237         // first pass: only remember aliased columns
238
// No replacements need to take place because double aliases
239
// are not allowed anyway
240
// So alias names will be retained
241
for (ListIterator JavaDoc columnIt = selectColumns.listIterator();
242                 columnIt.hasNext();)
243         {
244             String JavaDoc selectColumn = (String JavaDoc) columnIt.next();
245
246             // check for sql function
247
if ((selectColumn.indexOf('(') != -1)
248                 || (selectColumn.indexOf(')') != -1))
249             {
250                 // Sql function. Disregard.
251
continue;
252             }
253
254             // check if alias name exists
255
int spacePos = selectColumn.lastIndexOf(' ');
256             if (spacePos == -1)
257             {
258                 // no alias, disregard for now
259
continue;
260             }
261
262             String JavaDoc aliasName = selectColumn.substring(spacePos + 1);
263             columnNames.add(aliasName);
264         }
265
266         // second pass. Regard ordinary columns only
267
for (ListIterator JavaDoc columnIt = selectColumns.listIterator();
268                 columnIt.hasNext();)
269         {
270             String JavaDoc selectColumn = (String JavaDoc) columnIt.next();
271
272             // check for sql function
273
if ((selectColumn.indexOf('(') != -1)
274                 || (selectColumn.indexOf(')') != -1))
275             {
276                 // Sql function. Disregard.
277
continue;
278             }
279
280             {
281                 int spacePos = selectColumn.lastIndexOf(' ');
282                 if (spacePos != -1)
283                 {
284                     // alias, already processed in first pass
285
continue;
286                 }
287             }
288             // split into column name and tableName
289
String JavaDoc column;
290             {
291                 int dotPos = selectColumn.lastIndexOf('.');
292                 if (dotPos != -1)
293                 {
294                     column = selectColumn.substring(dotPos + 1);
295                 }
296                 else
297                 {
298                     column = selectColumn;
299                 }
300             }
301             if (columnNames.contains(column))
302             {
303                 // column needs to be aliased
304
// get replacement name
305
String JavaDoc aliasName;
306                 do
307                 {
308                     aliasName = "a" + replacementSuffix;
309                     ++replacementSuffix;
310                 }
311                 while (columnNames.contains(aliasName));
312
313                 selectColumn = selectColumn + " " + aliasName;
314                 columnIt.set(selectColumn);
315                 columnNames.add(aliasName);
316             }
317             else
318             {
319                 columnNames.add(column);
320             }
321         }
322     }
323
324     /**
325      * This method is for the SqlExpression.quoteAndEscape rules. The rule is,
326      * any string in a SqlExpression with a BACKSLASH will either be changed to
327      * "\\" or left as "\". SapDB does not need the escape character.
328      *
329      * @return false.
330      */

331     public boolean escapeText()
332     {
333         return false;
334     }
335
336     /**
337      * Whether an escape clause in like should be used.
338      * Example : select * from AUTHOR where AUTHOR.NAME like '\_%' ESCAPE '\';
339      *
340      * Oracle needs this, so this implementation always returns
341      * <code>true</code>.
342      *
343      * @return whether the escape clause should be appended or not.
344      */

345     public boolean useEscapeClauseForLike()
346     {
347         return true;
348     }
349 }
350
Popular Tags