1 package org.apache.torque.adapter;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.sql.Connection;
23 import java.sql.SQLException;
24 import java.sql.Timestamp;
25 import java.util.Date;
26 import java.util.Hashtable;
27 import java.util.Map;
28
29 import org.apache.torque.TorqueException;
30 import org.apache.torque.util.Query;
31 import org.apache.torque.util.functions.Aggregate;
32 import org.apache.torque.util.functions.FunctionEnum;
33
34 /***
35 * This class is the abstract base for any database adapter
36 * Support for new databases is added by subclassing this
37 * class and implementing its abstract methods, and by
38 * registering the new database adapter and its corresponding
39 * JDBC driver in the service configuration file.
40 *
41 * <p>The Torque database adapters exist to present a uniform
42 * interface to database access across all available databases. Once
43 * the necessary adapters have been written and configured,
44 * transparent swapping of databases is theoretically supported with
45 * <i>zero code changes</i> and minimal configuration file
46 * modifications.
47 *
48 * <p>Torque uses the driver class name to find the right adapter.
49 * A JDBC driver corresponding to your adapter must be added to the properties
50 * file, using the fully-qualified class name of the driver. If no driver is
51 * specified for your database, <code>driver.default</code> is used.
52 *
53 * <pre>
54 * #### MySQL MM Driver
55 * database.default.driver=org.gjt.mm.mysql.Driver
56 * database.default.url=jdbc:mysql://localhost/DATABASENAME
57 * </pre>
58 *
59 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
60 * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
61 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
62 * @author <a href="mailto:vido@ldh.org">Augustin Vidovic</a>
63 * @author <a href="mailto:greg.monroe@dukece.com">Greg Monroe</a>
64 * @version $Id: DB.java 393063 2006-04-10 20:59:16Z tfischer $
65 */
66 public abstract class AbstractDBAdapter implements DB
67 {
68 /***
69 * The default look up table for function classes.
70 */
71 private Map functionClasses = new Hashtable(10);
72
73
74
75
76
77
78
79
80
81 {
82 functionClasses.put( FunctionEnum.AVG, Aggregate.Avg.class );
83 functionClasses.put( FunctionEnum.COUNT, Aggregate.Count.class );
84 functionClasses.put( FunctionEnum.MAX, Aggregate.Max.class );
85 functionClasses.put( FunctionEnum.MIN, Aggregate.Min.class );
86 functionClasses.put( FunctionEnum.SUM, Aggregate.Sum.class );
87 }
88
89 /***
90 * Empty constructor.
91 */
92 protected AbstractDBAdapter()
93 {
94 }
95
96 /***
97 * This method is used to ignore case.
98 *
99 * @param in The string to transform to upper case.
100 * @return The upper case string.
101 */
102 public abstract String toUpperCase(String in);
103
104 /***
105 * Returns the character used to indicate the beginning and end of
106 * a piece of text used in a SQL statement (generally a single
107 * quote).
108 *
109 * @return The text delimeter.
110 */
111 public char getStringDelimiter()
112 {
113 return '\'';
114 }
115
116 /***
117 * Returns the constant from the {@link
118 * org.apache.torque.adapter.IDMethod} interface denoting which
119 * type of primary key generation method this type of RDBMS uses.
120 *
121 * @return IDMethod constant
122 */
123 public abstract String getIDMethodType();
124
125 /***
126 * Returns SQL used to get the most recently inserted primary key.
127 * Databases which have no support for this return
128 * <code>null</code>.
129 *
130 * @param obj Information used for key generation.
131 * @return The most recently inserted database key.
132 */
133 public abstract String getIDMethodSQL(Object obj);
134
135 /***
136 * Locks the specified table.
137 *
138 * @param con The JDBC connection to use.
139 * @param table The name of the table to lock.
140 * @throws SQLException No Statement could be created or executed.
141 */
142 public abstract void lockTable(Connection con, String table)
143 throws SQLException;
144
145 /***
146 * Unlocks the specified table.
147 *
148 * @param con The JDBC connection to use.
149 * @param table The name of the table to unlock.
150 * @throws SQLException No Statement could be created or executed.
151 */
152 public abstract void unlockTable(Connection con, String table)
153 throws SQLException;
154
155 /***
156 * This method is used to ignore case.
157 *
158 * @param in The string whose case to ignore.
159 * @return The string in a case that can be ignored.
160 */
161 public abstract String ignoreCase(String in);
162
163 /***
164 * This method is used to ignore case in an ORDER BY clause.
165 * Usually it is the same as ignoreCase, but some databases
166 * (Interbase for example) does not use the same SQL in ORDER BY
167 * and other clauses.
168 *
169 * @param in The string whose case to ignore.
170 * @return The string in a case that can be ignored.
171 */
172 public String ignoreCaseInOrderBy(String in)
173 {
174 return ignoreCase(in);
175 }
176
177 /***
178 * This method is used to check whether the database natively
179 * supports limiting the size of the resultset.
180 *
181 * @return True if the database natively supports limiting the
182 * size of the resultset.
183 */
184 public boolean supportsNativeLimit()
185 {
186 return false;
187 }
188
189 /***
190 * This method is used to check whether the database natively
191 * supports returning results starting at an offset position other
192 * than 0.
193 *
194 * @return True if the database natively supports returning
195 * results starting at an offset position other than 0.
196 */
197 public boolean supportsNativeOffset()
198 {
199 return false;
200 }
201
202 /***
203 * This method is used to generate the database specific query
204 * extension to limit the number of record returned.
205 *
206 * @param query The query to modify
207 * @param offset the offset Value
208 * @param limit the limit Value
209 *
210 * @throws TorqueException if any error occurs when building the query
211 */
212 public void generateLimits(Query query, int offset, int limit)
213 throws TorqueException
214 {
215 if (supportsNativeLimit())
216 {
217 query.setLimit(String.valueOf(limit));
218 }
219 }
220
221 /***
222 * This method is for the SqlExpression.quoteAndEscape rules. The rule is,
223 * any string in a SqlExpression with a BACKSLASH will either be changed to
224 * "//" or left as "\". SapDB does not need the escape character.
225 *
226 * @return true if the database needs to escape text in SqlExpressions.
227 */
228
229 public boolean escapeText()
230 {
231 return true;
232 }
233
234 /***
235 * This method is used to check whether the database supports
236 * limiting the size of the resultset.
237 *
238 * @return The limit style for the database.
239 * @deprecated This should not be exposed to the outside
240 */
241 public int getLimitStyle()
242 {
243 return LIMIT_STYLE_NONE;
244 }
245
246 /***
247 * This method is used to format any date string.
248 * Database can use different default date formats.
249 *
250 * @param date the Date to format
251 * @return The proper date formatted String.
252 */
253 public String getDateString(Date date)
254 {
255 Timestamp ts = null;
256 if (date instanceof Timestamp)
257 {
258 ts = (Timestamp) date;
259 }
260 else
261 {
262 ts = new Timestamp(date.getTime());
263 }
264
265 return ("{ts '" + ts + "'}");
266 }
267
268 /***
269 * This method is used to format a boolean string.
270 *
271 * @param b the Boolean to format
272 * @return The proper date formatted String.
273 */
274 public String getBooleanString(Boolean b)
275 {
276 return (Boolean.TRUE.equals(b) ? "1" : "0");
277 }
278
279 /***
280 * Whether ILIKE should be used for case insensitive like clauses.
281 *
282 * As most databases do not use ILIKE, this implementation returns false.
283 * This behaviour may be overwritten in subclasses.
284 *
285 * @return true if ilike should be used for case insensitive likes,
286 * false if ignoreCase should be applied to the compared strings.
287 */
288 public boolean useIlike()
289 {
290 return false;
291 }
292
293 /***
294 * Whether an escape clause in like should be used.
295 * Example : select * from AUTHOR where AUTHOR.NAME like '\_%' ESCAPE '\';
296 *
297 * As most databases do not need the escape clause, this implementation
298 * always returns <code>false</code>. This behaviour can be overwritten
299 * in subclasses.
300 *
301 * @return whether the escape clause should be appended or not.
302 */
303 public boolean useEscapeClauseForLike()
304 {
305 return false;
306 }
307
308 /***
309 * Return the class which implements the SQLFunction interface for the
310 * specified function.
311 *
312 * @param function The function to get the class for.
313 * @return The SQLFunction implementation for a function of this type that
314 * will work with this type of DB. Null indicates a class was not
315 * found.
316 */
317 public Class getFunctionClass( FunctionEnum function )
318 {
319 return (Class) functionClasses.get( function );
320 }
321
322 }