KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > lateralnz > c3d > util > DBUtils


1 /* ====================================================================
2  * The LateralNZ Software License, Version 1.0
3  *
4  * Copyright (c) 2003 LateralNZ. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by
21  * LateralNZ (http://www.lateralnz.org/) and other third parties."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "LateralNZ" must not be used to endorse or promote
26  * products derived from this software without prior written
27  * permission. For written permission, please
28  * contact oss@lateralnz.org.
29  *
30  * 5. Products derived from this software may not be called "Panther",
31  * or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
32  * "LATERALNZ" appear in their name, without prior written
33  * permission of LateralNZ.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of LateralNZ. For more
51  * information on Lateral, please see http://www.lateralnz.com/ or
52  * http://www.lateralnz.org
53  *
54  */

55 package org.lateralnz.c3d.util;
56
57 import java.sql.Date JavaDoc;
58 import java.sql.PreparedStatement JavaDoc;
59 import java.sql.ResultSet JavaDoc;
60 import java.sql.SQLException JavaDoc;
61 import java.sql.Time JavaDoc;
62 import java.sql.Timestamp JavaDoc;
63 import java.sql.Types JavaDoc;
64 import java.math.BigDecimal JavaDoc;
65 import java.util.regex.*;
66 import java.util.HashMap JavaDoc;
67 import java.util.Iterator JavaDoc;
68 import java.util.ArrayList JavaDoc;
69 import java.util.List JavaDoc;
70 import java.util.Map JavaDoc;
71 import java.util.NoSuchElementException JavaDoc;
72 import java.util.StringTokenizer JavaDoc;
73
74 import org.lateralnz.common.util.Constants;
75 import org.lateralnz.common.util.StringUtils;
76
77 /**
78  * general utilities
79  */

80 public class DBUtils implements Constants {
81   
82   public static final int DELETE_STATEMENT = 1;
83   public static final int INSERT_STATEMENT = 2;
84   public static final int SELECT_STATEMENT = 3;
85   public static final int UPDATE_STATEMENT = 4;
86   public static final int CLEAR_CACHE_STATEMENT = 5;
87   public static final int QUERY_CACHE_STATEMENT = 6;
88   public static final int QUERY_CACHE_DUMP_STATEMENT = 7;
89   public static final int QUERY_STATS_STATEMENT = 8;
90   
91   public static final String JavaDoc SEP = "::";
92   
93   private static final String JavaDoc IGNORE_SPACES_TO_END = "\\s*$";
94   private static final String JavaDoc SET_CLAUSE_DELIMS = ",=";
95   
96   private static final Pattern SPLIT_PATTERN = Pattern.compile("\\G(?:^|;)([^';]*+(?:'(?:[^'\\\\]|\\\\')*+'[^';]*+)*+)");
97   private static final Pattern CACHE_NAME_PATTERN = Pattern.compile("clear|query\\s*cache\\s*([^\\s]*).*", Pattern.DOTALL);
98   private static final Pattern DUMP_NAME_PATTERN = Pattern.compile("query\\s*cache\\s.*\\sdump\\s*'(.*)'$", Pattern.DOTALL);
99   private static final Pattern WHERE_CLAUSE_PATTERN = Pattern.compile("\\swhere\\s+(.*?)$", Pattern.DOTALL);
100   private static final Pattern INSERT_TABLE_PATTERN = Pattern.compile("insert\\s*into\\s*([^\\s]*).*", Pattern.DOTALL);
101   private static final Pattern UPDATE_TABLE_PATTERN = Pattern.compile("update\\s*([^\\s]*).*", Pattern.DOTALL);
102   private static final Pattern DELETE_TABLE_PATTERN = Pattern.compile("delete\\s*from\\s*([^\\s]*).*", Pattern.DOTALL);
103   
104   private static final Pattern CLEAR_CACHE_PATTERN = Pattern.compile("^\\s*clear\\s*cache.*", Pattern.DOTALL);
105   private static final Pattern DELETE_PATTERN = Pattern.compile("^\\s*delete\\s*from.+", Pattern.DOTALL);
106   private static final Pattern INSERT_PATTERN = Pattern.compile("^\\s*insert\\s*into.+", Pattern.DOTALL);
107   private static final Pattern QUERY_CACHE_PATTERN = Pattern.compile("^\\s*query\\s*cache.*", Pattern.DOTALL);
108   private static final Pattern QUERY_CACHE_DUMP_PATTERN = Pattern.compile("^\\s*query\\s*cache.*\\sdump\\s.*", Pattern.DOTALL);
109   private static final Pattern QUERY_STATS_PATTERN = Pattern.compile("^\\s*query\\s*stats.*", Pattern.DOTALL);
110   private static final Pattern SELECT_PATTERN = Pattern.compile("^(/\\*.*\\*/)*\\s*select\\s.+", Pattern.DOTALL);
111   private static final Pattern UPDATE_PATTERN = Pattern.compile("^\\s*update\\s.+", Pattern.DOTALL);
112     
113   private DBUtils() {
114   }
115   
116   /**
117    * count the selects that appear in a list of SQL statements
118    */

119   public static final int countSelects(List JavaDoc l) {
120     Iterator JavaDoc iter = l.iterator();
121     int count = 0;
122     while (iter.hasNext()) {
123       String JavaDoc s = (String JavaDoc)iter.next();
124       if (isStatementType(s, SELECT_STATEMENT)) {
125         count++;
126       }
127     }
128     return count;
129   }
130   
131   /**
132    * create a column object from the resultset using an array of db types and the index
133    * of the column we're creating
134    */

135   public static final Column createColumn(ResultSet JavaDoc rs, int[] types, int idx) throws SQLException JavaDoc {
136     Column col = new Column(rs.getBytes(idx), types[idx-1]);
137     col.setNull(rs.wasNull());
138     return col;
139   }
140   
141   public static final Column createColumn(String JavaDoc value) {
142     Column col = new Column(value.getBytes(), Types.VARCHAR);
143     col.setNull(false);
144     return col;
145   }
146   
147   public static final Column[] createRow(String JavaDoc[] values) {
148     Column[] cols = new Column[values.length];
149     for (int i = 0; i < values.length; i++) {
150       if (values[i] == null) {
151         cols[i] = createColumn(EMPTY);
152       }
153       else {
154         cols[i] = createColumn(values[i]);
155       }
156     }
157     return cols;
158   }
159     
160   
161   /**
162    * flatten an array of columns into a string
163    */

164   public static final String JavaDoc flatten(Column[] cols, String JavaDoc delim) {
165     if (cols == null) {
166       return EMPTY;
167     }
168     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
169     int max = cols.length - 1;
170     for (int i = 0; i < cols.length; i++) {
171       Object JavaDoc obj = cols[i].getObjectValue();
172       if (obj != null) {
173         sb.append(cols[i].getObjectValue().toString());
174         if (i < max) {
175           sb.append(delim);
176         }
177       }
178     }
179     
180     return sb.toString();
181   }
182   
183   
184   public static final String JavaDoc getCacheNameFromKey(String JavaDoc key) {
185     String JavaDoc[] s = key.split(SEP);
186     if (s == null) {
187       return EMPTY;
188     }
189     else {
190       return s[0];
191     }
192   }
193   
194   
195  /**
196   * return the column data based on an array of primary key columns.
197   * For example, if the primary keys are in columns 1, 5 and 6 of the resultset,
198   * this will return the data in those columns as a 3 element array.
199   */

200   public static final String JavaDoc[] getKeyColumnData(int[] keyColumns, ResultSet JavaDoc rs) throws SQLException JavaDoc {
201     String JavaDoc[] keyData = new String JavaDoc[keyColumns.length];
202     for (int i = 0; i < keyColumns.length; i++) {
203       keyData[i] = rs.getString(keyColumns[i]);
204     }
205     return keyData;
206   }
207   
208   public static final String JavaDoc getInsertTableName(String JavaDoc sql) {
209     Matcher matcher = INSERT_TABLE_PATTERN.matcher(sql);
210     String JavaDoc table = null;
211     if (matcher.find()) {
212       return matcher.group(1);
213     }
214     else {
215       return null;
216     }
217   }
218   
219   public static final Object JavaDoc getObjectFromMap(Object JavaDoc key, Map JavaDoc m, Class JavaDoc newObjClass) throws SQLException JavaDoc {
220     if (!m.containsKey(key)) {
221       synchronized (m) {
222         if (!m.containsKey(key)) {
223           try {
224             m.put(key, newObjClass.newInstance());
225           }
226           catch (Exception JavaDoc e) {
227             throw new SQLException JavaDoc("system error: " + e.getMessage());
228           }
229         }
230       }
231     }
232     
233     return m.get(key);
234   }
235   
236   public static final String JavaDoc getResultSetDataKey(String JavaDoc cache, String JavaDoc[] keyColumns) {
237     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
238     sb.append(cache).append(SEP);
239     int len = keyColumns.length - 1;
240     for (int i = 0; i < keyColumns.length; i++) {
241       sb.append(keyColumns[i]);
242       if (i < len) {
243         sb.append(PIPE);
244       }
245     }
246     return sb.toString();
247   }
248   
249   public static final String JavaDoc getTargetName(String JavaDoc sql, int type) {
250     Pattern pat;
251     switch (type) {
252       case INSERT_STATEMENT:
253         pat = INSERT_TABLE_PATTERN;
254         break;
255       case DELETE_STATEMENT:
256         pat = DELETE_TABLE_PATTERN;
257         break;
258       case UPDATE_STATEMENT:
259         pat = UPDATE_TABLE_PATTERN;
260         break;
261       case CLEAR_CACHE_STATEMENT:
262       case QUERY_CACHE_STATEMENT:
263         pat = CACHE_NAME_PATTERN;
264         break;
265       case QUERY_CACHE_DUMP_STATEMENT:
266         pat = DUMP_NAME_PATTERN;
267         break;
268       default:
269         return null;
270     }
271     
272     Matcher matcher = pat.matcher(sql);
273     String JavaDoc table = null;
274     if (matcher.find()) {
275       return matcher.group(1);
276     }
277     else {
278       return null;
279     }
280   }
281   
282   /**
283    * get the where clause of an SQL statement
284    */

285   public static final String JavaDoc getWhereClause(String JavaDoc sql) {
286     Matcher matcher = WHERE_CLAUSE_PATTERN.matcher(sql);
287     if (matcher.find()) {
288       return matcher.group(1);
289     }
290     else {
291       return EMPTY;
292     }
293   }
294   
295   
296   public static final boolean isStatementType(String JavaDoc s, int type) {
297     Pattern pat;
298     switch (type) {
299       case DELETE_STATEMENT:
300         pat = DELETE_PATTERN;
301         break;
302       case INSERT_STATEMENT:
303         pat = INSERT_PATTERN;
304         break;
305       case SELECT_STATEMENT:
306         pat = SELECT_PATTERN;
307         break;
308       case UPDATE_STATEMENT:
309         pat = UPDATE_PATTERN;
310         break;
311       case CLEAR_CACHE_STATEMENT:
312         pat = CLEAR_CACHE_PATTERN;
313         break;
314       case QUERY_CACHE_DUMP_STATEMENT:
315         pat = QUERY_CACHE_DUMP_PATTERN;
316         break;
317       case QUERY_CACHE_STATEMENT:
318         pat = QUERY_CACHE_PATTERN;
319         break;
320       case QUERY_STATS_STATEMENT:
321         pat = QUERY_STATS_PATTERN;
322         break;
323
324       default:
325         return false;
326     }
327     s = s.trim();
328     Matcher m = pat.matcher(s);
329     return m.matches();
330   }
331   
332   /**
333    * given an array of Column objects set the values of those columns as parameters in
334    * a prepared statement
335    */

336   public static final void setParams(PreparedStatement JavaDoc ps, Column[] cols, int offset, int length) throws SQLException JavaDoc {
337     for (int i = offset, j = 1; i < cols.length && j <= length; i++, j++) {
338       if (cols[i].getNull()) {
339         if (cols[i].getObjectValue() == null) {
340           ps.setNull(j, cols[i].getType());
341         }
342         else {
343           ps.setNull(j, cols[i].getType(), (String JavaDoc)cols[i].getObjectValue());
344         }
345         continue;
346       }
347       
348       switch (cols[i].getType()) {
349         case Types.BIGINT:
350           ps.setLong(j, ((Long JavaDoc)cols[i].getObjectValue()).longValue());
351           break;
352         case Types.BOOLEAN:
353           ps.setBoolean(j, Boolean.valueOf((String JavaDoc)cols[i].getObjectValue()).booleanValue());
354           break;
355         case Types.DATE:
356           ps.setDate(j, (Date JavaDoc)cols[i].getObjectValue());
357           break;
358         case Types.DOUBLE:
359           ps.setDouble(j, ((Double JavaDoc)cols[i].getObjectValue()).doubleValue());
360           break;
361         case Types.FLOAT:
362           ps.setFloat(j, ((Float JavaDoc)cols[i].getObjectValue()).floatValue());
363           break;
364         case Types.INTEGER:
365           ps.setInt(j, ((Integer JavaDoc)cols[i].getObjectValue()).intValue());
366           break;
367         case Types.NUMERIC:
368           ps.setBigDecimal(j, (BigDecimal JavaDoc)cols[i].getObjectValue());
369           break;
370         case Types.SMALLINT:
371           ps.setShort(j, ((Short JavaDoc)cols[i].getObjectValue()).shortValue());
372           break;
373         case Types.TIME:
374           ps.setTime(j, (Time JavaDoc)cols[i].getObjectValue());
375           break;
376         case Types.TIMESTAMP:
377           ps.setTimestamp(j, (Timestamp JavaDoc)cols[i].getObjectValue());
378           break;
379         case Types.TINYINT:
380           ps.setByte(j, ((Byte JavaDoc)cols[i].getObjectValue()).byteValue());
381           break;
382         case Types.VARBINARY:
383           ps.setBytes(j, cols[i].getValue());
384           break;
385         case Types.VARCHAR:
386           ps.setString(j, (String JavaDoc)cols[i].getObjectValue());
387           break;
388       }
389     }
390   }
391   
392   /**
393    * split an SQL statement into SQL fragments separated by ;
394    * for example, select * from table1;insert into table2
395    * should result in 2 separate statements
396    */

397   public static final List JavaDoc splitSQL(String JavaDoc s) {
398     ArrayList JavaDoc ll = new ArrayList JavaDoc();
399     
400     Matcher matcher = SPLIT_PATTERN.matcher(s);
401     while(matcher.find()) {
402       String JavaDoc field = matcher.group(1);
403       
404       field = field.trim();
405       if (!StringUtils.isEmpty(field)) {
406         ll.add(field);
407       }
408     }
409     return ll;
410   }
411   
412   /**
413    * split a SQL set clause into a map of column=value
414    */

415   public static final Map JavaDoc splitSet(String JavaDoc setSQL) throws SQLException JavaDoc {
416     StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(setSQL, SET_CLAUSE_DELIMS, true);
417     try {
418       HashMap JavaDoc rtn = new HashMap JavaDoc();
419       while (st.hasMoreTokens()) {
420         String JavaDoc col = st.nextToken();
421         if (!st.nextToken().equals(EQUALS)) {
422           throw new SQLException JavaDoc("unexpected token in update columns");
423         }
424         String JavaDoc tmp;
425         StringBuffer JavaDoc val = new StringBuffer JavaDoc();
426         while (st.hasMoreTokens()) {
427           tmp = st.nextToken();
428           if (tmp.equals(COMMA) && (StringUtils.countOccurrences(val, '\'') % 2) == 0) {
429             break;
430           }
431           val.append(tmp);
432         }
433         rtn.put(col, val.toString());
434       }
435       return rtn;
436     }
437     catch (SQLException JavaDoc se) {
438       throw se;
439     }
440     catch (NoSuchElementException JavaDoc nsee) {
441       throw new SQLException JavaDoc("error parsing columns in update");
442     }
443   }
444
445 }
Popular Tags