001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdbc;
012:
013: import com.versant.core.common.GenericState;
014: import com.versant.core.common.GenericOID;
015: import com.versant.core.metadata.MDStatics;
016: import com.versant.core.jdbc.conn.PooledPSWithParamLogging;
017:
018: import java.sql.PreparedStatement;
019: import java.sql.SQLException;
020: import java.sql.ResultSet;
021: import java.math.BigDecimal;
022: import java.math.BigInteger;
023: import java.util.ArrayList;
024:
025: import com.versant.core.common.BindingSupportImpl;
026:
027: /**
028: * Static JDBC utility functions. These are used to implement GenericOID
029: * and GenericState in a way similar to the generated State and OID
030: * implementations. They are also used elsewhere in JdbcDataStore.
031: * @see GenericOID
032: * @see GenericState
033: */
034: public class JdbcUtils implements MDStatics {
035:
036: private JdbcUtils() {
037: }
038:
039: /**
040: * Set a parameter on a PreparedStatement. This will call setInt or
041: * setShort etc depending on the type of value.
042: */
043: public static void set(PreparedStatement ps, int index,
044: Object value, int javaTypeCode, int jdbcType)
045: throws SQLException {
046: if (value == null) {
047: ps.setNull(index, jdbcType);
048: } else {
049: switch (javaTypeCode) {
050: case INT:
051:
052: case INTW:
053: ps.setInt(index, ((Number) value).intValue());
054: break;
055: case SHORT:
056:
057: case SHORTW:
058: ps.setShort(index, ((Number) value).shortValue());
059: break;
060: case STRING:
061: ps.setString(index, (String) value);
062: break;
063: case BOOLEAN:
064:
065: case BOOLEANW:
066: ps.setBoolean(index, ((Boolean) value).booleanValue());
067: break;
068: case BYTE:
069:
070: case BYTEW:
071: ps.setByte(index, ((Number) value).byteValue());
072: break;
073: case BIGDECIMAL:
074: ps.setBigDecimal(index, (BigDecimal) value);
075: break;
076: case BIGINTEGER:
077: ps.setBigDecimal(index, new BigDecimal(
078: (BigInteger) value));
079: break;
080: case DOUBLE:
081:
082: case DOUBLEW:
083: ps.setDouble(index, ((Number) value).doubleValue());
084: break;
085: case FLOAT:
086:
087: case FLOATW:
088: ps.setFloat(index, ((Number) value).floatValue());
089: break;
090: case LONG:
091:
092: case LONGW:
093: ps.setLong(index, ((Number) value).longValue());
094: break;
095:
096: default:
097: ps.setObject(index, value, jdbcType);
098: }
099: ;
100: }
101: }
102:
103: /**
104: * Set a parameter on a PreparedStatement. This will call setInt or
105: * setShort etc depending on the type of value. This method is used
106: * when the value is available as an int to avoid creating a wrapper
107: * instance.
108: */
109: public static void set(PreparedStatement ps, int index, int value,
110: int javaTypeCode, int jdbcType) throws SQLException {
111: switch (javaTypeCode) {
112: case INTW:
113: case INT:
114: ps.setInt(index, value);
115: break;
116: case SHORTW:
117: case SHORT:
118: ps.setShort(index, (short) value);
119: break;
120: case BYTEW:
121: case BYTE:
122: ps.setByte(index, (byte) value);
123: break;
124:
125: default:
126: throw BindingSupportImpl.getInstance().internal(
127: "set(...int...) called " + "for javaTypeCode "
128: + javaTypeCode);
129: }
130: ;
131: }
132:
133: /**
134: * Get a value from a ResultSet. This will call getInt or getShort etc.
135: */
136: public static Object get(ResultSet rs, int index, int javaTypeCode,
137: int scale) throws SQLException {
138: switch (javaTypeCode) {
139: case INT:
140:
141: case INTW:
142: return new Integer(rs.getInt(index));
143: case SHORT:
144:
145: case SHORTW:
146: return new Short(rs.getShort(index));
147: case STRING:
148: return rs.getString(index);
149: case BOOLEAN:
150:
151: case BOOLEANW:
152: return rs.getBoolean(index) ? Boolean.TRUE : Boolean.FALSE;
153: case BYTE:
154:
155: case BYTEW:
156: return new Byte(rs.getByte(index));
157: case BIGDECIMAL:
158: return rs.getBigDecimal(index);
159: case BIGINTEGER:
160: BigDecimal d = rs.getBigDecimal(index);
161: if (d == null)
162: return null;
163:
164: return d.unscaledValue();
165:
166: case DOUBLE:
167:
168: case DOUBLEW:
169: return new Double(rs.getDouble(index));
170: case FLOAT:
171:
172: case FLOATW:
173: return new Float(rs.getFloat(index));
174: case LONG:
175:
176: case LONGW:
177: return new Long(rs.getLong(index));
178:
179: default:
180: return rs.getObject(index);
181: }
182: }
183:
184: /**
185: * Convert an ArrayList of values into an properly typed array (int[],
186: * String[], byte[] etc.). Arrays of wrapper types (Integer et al) are
187: * returned as arrays of primitives to save memory. This means that
188: * there cannot be any nulls in values.
189: */
190: public static Object toArrayNoNulls(ArrayList values,
191: int javaTypeCode) throws SQLException {
192: int n = values.size();
193: switch (javaTypeCode) {
194: case INTW:
195: case INT:
196:
197: int[] inta = new int[n];
198: for (int i = inta.length - 1; i >= 0; i--) {
199: inta[i] = ((Integer) values.get(i)).intValue();
200: }
201: return inta;
202: case SHORTW:
203: case SHORT:
204:
205: short[] shorta = new short[n];
206: for (int i = shorta.length - 1; i >= 0; i--) {
207: shorta[i] = ((Short) values.get(i)).shortValue();
208: }
209: return shorta;
210: case STRING:
211: String[] stringa = new String[n];
212: values.toArray(stringa);
213: return stringa;
214: case BOOLEANW:
215: case BOOLEAN:
216: boolean[] booleana = new boolean[n];
217: for (int i = booleana.length - 1; i >= 0; i--) {
218: booleana[i] = ((Boolean) values.get(i)).booleanValue();
219: }
220: return booleana;
221: case BYTEW:
222: case BYTE:
223: byte[] bytea = new byte[n];
224: for (int i = bytea.length - 1; i >= 0; i--) {
225: bytea[i] = ((Byte) values.get(i)).byteValue();
226: }
227: return bytea;
228: case BIGDECIMAL:
229: BigDecimal[] bigdecimala = new BigDecimal[n];
230: values.toArray(bigdecimala);
231: return bigdecimala;
232: case BIGINTEGER:
233: BigInteger[] bigintegera = new BigInteger[n];
234: values.toArray(bigintegera);
235: return bigintegera;
236: case DOUBLEW:
237: case DOUBLE:
238: double[] doublea = new double[n];
239: for (int i = doublea.length - 1; i >= 0; i--) {
240: doublea[i] = ((Double) values.get(i)).doubleValue();
241: }
242: return doublea;
243: case FLOATW:
244: case FLOAT:
245: float[] floata = new float[n];
246: for (int i = floata.length - 1; i >= 0; i--) {
247: floata[i] = ((Float) values.get(i)).floatValue();
248: }
249: return floata;
250: case LONGW:
251: case LONG:
252:
253: long[] longa = new long[n];
254: for (int i = longa.length - 1; i >= 0; i--) {
255: longa[i] = ((Long) values.get(i)).longValue();
256: }
257: return longa;
258: default:
259: return values.toArray();
260: }
261: }
262:
263: /**
264: * Convert x to a String by calling its toString method. If x is an
265: * SQLException then any getNextExceptions() are recursively added to
266: * the string preceded by linefeeds.
267: */
268: public static String toString(Throwable x) {
269: if (x instanceof SQLException) {
270: StringBuffer s = new StringBuffer();
271: s.append(x);
272: SQLException se = (SQLException) x;
273: for (se = se.getNextException(); se != null; se = se
274: .getNextException()) {
275: s.append('\n');
276: s.append(se);
277: int n = s.length() - 1;
278: if (s.charAt(n) == '\n')
279: s.setLength(n);
280: }
281: return s.toString();
282: } else {
283: return x.toString();
284: }
285: }
286:
287: /**
288: * Build a message with info about ps for exceptions and so on. If the
289: * ps contains batches of parameters they are all added to the info
290: * String.
291: */
292: public static String getPreparedStatementInfo(String sql,
293: PreparedStatement ps) {
294: StringBuffer s = new StringBuffer();
295: s.append(sql);
296: s.append('\n');
297: if (ps instanceof PooledPSWithParamLogging) {
298: s.append("Params: ");
299: PooledPSWithParamLogging lps = (PooledPSWithParamLogging) ps;
300: int bc = lps.getLastBatchCount();
301: if (bc > 0) {
302: for (int i = 0; i < bc; i++) {
303: s.append('\n');
304: s.append(lps.getLastExecParamsString(i));
305: }
306: } else {
307: s.append(lps.getLastExecParamsString());
308: }
309: } else {
310: s
311: .append("(set event logging to all to see parameter values)");
312: }
313: return s.toString();
314: }
315:
316: /**
317: * Build a message with info about ps for exceptions and so on. Parameter
318: * info is provided for the given batch entry if available.
319: */
320: public static String getPreparedStatementInfo(String sql,
321: PreparedStatement ps, int batchEntry) {
322: StringBuffer s = new StringBuffer();
323: s.append(sql);
324: s.append('\n');
325: if (ps instanceof PooledPSWithParamLogging) {
326: s.append("Params: ");
327: PooledPSWithParamLogging lps = (PooledPSWithParamLogging) ps;
328: s.append(lps.getLastExecParamsString(batchEntry));
329: } else {
330: s
331: .append("(set event logging to all to see parameter data)");
332: }
333: return s.toString();
334: }
335:
336: }
|