001: /*
002:
003: Derby - Class org.apache.derby.client.am.Utils
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.client.am;
023:
024: import java.sql.SQLException;
025: import org.apache.derby.iapi.types.SQLBit;
026: import org.apache.derby.shared.common.i18n.MessageUtil;
027: import org.apache.derby.shared.common.reference.MessageId;
028:
029: // Self-contained utilities.
030: // Don't reference any other driver classes, except Configuration, from within this class.
031:
032: public final class Utils {
033:
034: static String getStringFromBytes(byte[] bytes) {
035: if (bytes == null) {
036: return "{}";
037: }
038: StringBuffer stringBuffer = new StringBuffer(
039: bytes.length * 6 + 4);
040: stringBuffer.append("{ ");
041: for (int i = 0; i < bytes.length; i++) {
042: stringBuffer.append("0x");
043: stringBuffer.append(Integer.toHexString(bytes[i] & 0xff));
044: if (i != bytes.length - 1) {
045: stringBuffer.append(", ");
046: }
047: }
048: stringBuffer.append(" }");
049: return stringBuffer.toString();
050: }
051:
052: static String getStringFromInts(int[] ints) {
053: if (ints == null) {
054: return "{}";
055: }
056: StringBuffer stringBuffer = new StringBuffer();
057: stringBuffer.append("{ ");
058: for (int i = 0; i < ints.length; i++) {
059: stringBuffer.append(String.valueOf(ints[i]));
060: if (i != ints.length - 1) {
061: stringBuffer.append(", ");
062: }
063: }
064: stringBuffer.append(" }");
065: return stringBuffer.toString();
066: }
067:
068: static String getStringFromStrings(String[] strings) {
069: if (strings == null) {
070: return "{}";
071: }
072: StringBuffer stringBuffer = new StringBuffer();
073: stringBuffer.append("{ ");
074: for (int i = 0; i < strings.length; i++) {
075: stringBuffer.append(strings[i]);
076: if (i != strings.length - 1) {
077: stringBuffer.append(", ");
078: }
079: }
080: stringBuffer.append(" }");
081: return stringBuffer.toString();
082: }
083:
084: static public int computeBigDecimalPrecision(
085: java.math.BigDecimal decimal) {
086: byte[] bBytes = decimal.unscaledValue().abs().toByteArray();
087:
088: if (byteArrayCmp(bBytes, tenRadixArr[tenRadixArr.length - 1]) >= 0) {
089: throw new java.lang.IllegalArgumentException(SqlException
090: .getMessageUtil().getTextMessage(
091: MessageId.CONN_PRECISION_TOO_LARGE));
092: }
093:
094: int lo = 0, hi = tenRadixArr.length - 1, mi = (hi + lo) / 2;
095: do {
096: int compare = byteArrayCmp(bBytes, tenRadixArr[mi]);
097: if (compare == 1) {
098: lo = mi;
099: } else if (compare == -1) {
100: hi = mi;
101: } else {
102: break;
103: }
104:
105: mi = (hi + lo) / 2;
106: } while (mi != lo);
107:
108: return (mi + 1);
109: }
110:
111: // Used only by computeBigDecimalPrecision()
112: private static int byteArrayCmp(byte[] arg1, byte[] arg2) {
113: int arg1Offset = 0;
114: int arg2Offset = 0;
115: int length;
116: if (arg1.length > arg2.length) {
117: int diff = arg1.length - arg2.length;
118: for (; arg1Offset < diff; arg1Offset++) {
119: if (arg1[arg1Offset] != 0) {
120: return 1;
121: }
122: }
123: length = arg2.length;
124: } else if (arg1.length < arg2.length) {
125: int diff = arg2.length - arg1.length;
126: for (; arg2Offset < diff; arg2Offset++) {
127: if (arg2[arg2Offset] != 0) {
128: return -1;
129: }
130: }
131: length = arg1.length;
132: } else {
133: length = arg1.length;
134: }
135:
136: for (int i = 0; i < length; i++) {
137: int b1 = arg1[arg1Offset + i] & 0xFF;
138: int b2 = arg2[arg2Offset + i] & 0xFF;
139: if (b1 > b2) {
140: return 1;
141: } else if (b1 < b2) {
142: return -1;
143: }
144: }
145: return 0;
146: }
147:
148: // Used only by computeBigDecimalPrecision()
149: // byte array of 1, 10, 100, 1000, 10000, ..., 10^31 for
150: // fast computing the length a BigDecimal.
151: private static byte[][] tenRadixArr = {
152: { (byte) 0x01 }, // 10^0
153: { (byte) 0x0A }, // 10^1
154: { (byte) 0x64 }, // 10^2
155: { (byte) 0x03, (byte) 0xe8 }, // 10^3
156: { (byte) 0x27, (byte) 0x10 }, // 10^4
157: { (byte) 0x01, (byte) 0x86, (byte) 0xa0 }, // 10^5
158: { (byte) 0x0f, (byte) 0x42, (byte) 0x40 }, // 10^6
159: { (byte) 0x98, (byte) 0x96, (byte) 0x80 }, // 10^7
160: { (byte) 0x05, (byte) 0xf5, (byte) 0xe1, (byte) 0x00 }, // 10^8
161: { (byte) 0x3b, (byte) 0x9a, (byte) 0xca, (byte) 0x00 }, // 10^9
162: { (byte) 0x02, (byte) 0x54, (byte) 0x0b, (byte) 0xe4,
163: (byte) 0x00 }, // 10^10
164: { (byte) 0x17, (byte) 0x48, (byte) 0x76, (byte) 0xe8,
165: (byte) 0x00 }, // 10^11
166: { (byte) 0xe8, (byte) 0xd4, (byte) 0xa5, (byte) 0x10,
167: (byte) 0x00 }, // 10^12
168: { (byte) 0x09, (byte) 0x18, (byte) 0x4e, (byte) 0x72,
169: (byte) 0xa0, (byte) 0x00 }, // 10^13
170: { (byte) 0x5a, (byte) 0xf3, (byte) 0x10, (byte) 0x7a,
171: (byte) 0x40, (byte) 0x00 }, // 10^14
172: { (byte) 0x03, (byte) 0x8d, (byte) 0x7e, (byte) 0xa4,
173: (byte) 0xc6, (byte) 0x80, (byte) 0x00 }, // 10^15
174: { (byte) 0x23, (byte) 0x86, (byte) 0xf2, (byte) 0x6f,
175: (byte) 0xc1, (byte) 0x00, (byte) 0x00 }, // 10^16
176: { (byte) 0x01, (byte) 0x63, (byte) 0x45, (byte) 0x78,
177: (byte) 0x5d, (byte) 0x8a, (byte) 0x00, (byte) 0x00 }, // 10^17
178: { (byte) 0x0d, (byte) 0xe0, (byte) 0xb6, (byte) 0xb3,
179: (byte) 0xa7, (byte) 0x64, (byte) 0x00, (byte) 0x00 }, // 10^18
180: { (byte) 0x8a, (byte) 0xc7, (byte) 0x23, (byte) 0x04,
181: (byte) 0x89, (byte) 0xe8, (byte) 0x00, (byte) 0x00 }, // 10^19
182: { (byte) 0x05, (byte) 0x6b, (byte) 0xc7, (byte) 0x5e,
183: (byte) 0x2d, (byte) 0x63, (byte) 0x10, (byte) 0x00,
184: (byte) 0x00 }, // 10^20
185: { (byte) 0x36, (byte) 0x35, (byte) 0xc9, (byte) 0xad,
186: (byte) 0xc5, (byte) 0xde, (byte) 0xa0, (byte) 0x00,
187: (byte) 0x00 }, // 10^21
188: { (byte) 0x02, (byte) 0x1e, (byte) 0x19, (byte) 0xe0,
189: (byte) 0xc9, (byte) 0xba, (byte) 0xb2, (byte) 0x40,
190: (byte) 0x00, (byte) 0x00 }, // 10^22
191: { (byte) 0x15, (byte) 0x2d, (byte) 0x02, (byte) 0xc7,
192: (byte) 0xe1, (byte) 0x4a, (byte) 0xf6, (byte) 0x80,
193: (byte) 0x00, (byte) 0x00 }, // 10^23
194: { (byte) 0xd3, (byte) 0xc2, (byte) 0x1b, (byte) 0xce,
195: (byte) 0xcc, (byte) 0xed, (byte) 0xa1, (byte) 0x00,
196: (byte) 0x00, (byte) 0x00 }, // 10^24
197: { (byte) 0x08, (byte) 0x45, (byte) 0x95, (byte) 0x16,
198: (byte) 0x14, (byte) 0x01, (byte) 0x48, (byte) 0x4a,
199: (byte) 0x00, (byte) 0x00, (byte) 0x00 }, // 10^25
200: { (byte) 0x52, (byte) 0xb7, (byte) 0xd2, (byte) 0xdc,
201: (byte) 0xc8, (byte) 0x0c, (byte) 0xd2, (byte) 0xe4,
202: (byte) 0x00, (byte) 0x00, (byte) 0x00 }, // 10^26
203: { (byte) 0x03, (byte) 0x3b, (byte) 0x2e, (byte) 0x3c,
204: (byte) 0x9f, (byte) 0xd0, (byte) 0x80, (byte) 0x3c,
205: (byte) 0xe8, (byte) 0x00, (byte) 0x00, (byte) 0x00 }, // 10^27
206: { (byte) 0x20, (byte) 0x4f, (byte) 0xce, (byte) 0x5e,
207: (byte) 0x3e, (byte) 0x25, (byte) 0x02, (byte) 0x61,
208: (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00 }, // 10^28
209: { (byte) 0x01, (byte) 0x43, (byte) 0x1e, (byte) 0x0f,
210: (byte) 0xae, (byte) 0x6d, (byte) 0x72, (byte) 0x17,
211: (byte) 0xca, (byte) 0xa0, (byte) 0x00, (byte) 0x00,
212: (byte) 0x00 }, // 10^29
213: { (byte) 0x0c, (byte) 0x9f, (byte) 0x2c, (byte) 0x9c,
214: (byte) 0xd0, (byte) 0x46, (byte) 0x74, (byte) 0xed,
215: (byte) 0xea, (byte) 0x40, (byte) 0x00, (byte) 0x00,
216: (byte) 0x00 }, // 10^30
217: { (byte) 0x7e, (byte) 0x37, (byte) 0xbe, (byte) 0x20,
218: (byte) 0x22, (byte) 0xc0, (byte) 0x91, (byte) 0x4b,
219: (byte) 0x26, (byte) 0x80, (byte) 0x00, (byte) 0x00,
220: (byte) 0x00 } // 10^31
221: };
222:
223: // If the input string is short, pad it with blanks.
224: // If the input string is long, truncate it.
225: static public String padOrTruncate(String s, int fixedLength) {
226: if (s.length() >= fixedLength) // we need to truncate
227: {
228: return s.substring(0, fixedLength);
229: } else { // we need to pad
230: StringBuffer buffer = new StringBuffer(s);
231: for (int i = 0; i < fixedLength - s.length(); i++) {
232: buffer.append(" ");
233: }
234: return buffer.toString();
235: }
236: }
237:
238: static public void checkForNegativePositiveSqlcard(Sqlca sqlca,
239: Statement statement) throws SqlException {
240: if (sqlca != null) {
241: int sqlcode = sqlca.getSqlCode();
242: if (sqlcode < 0) {
243: throw new SqlException(statement.agent_.logWriter_,
244: sqlca);
245: } else {
246: if (sqlcode > 0) {
247: statement.accumulateWarning(new SqlWarning(
248: statement.agent_.logWriter_, sqlca));
249: }
250: }
251: }
252: }
253:
254: static public void checkForNegativePositiveSqlcard(Sqlca sqlca,
255: ResultSet resultSet) throws SqlException {
256: if (sqlca != null) {
257: int sqlcode = sqlca.getSqlCode();
258: if (sqlcode < 0) {
259: throw new SqlException(resultSet.agent_.logWriter_,
260: sqlca);
261: } else {
262: if (sqlcode > 0) {
263: resultSet.accumulateWarning(new SqlWarning(
264: resultSet.agent_.logWriter_, sqlca));
265: }
266: }
267: }
268: }
269:
270: static public int getSqlcodeFromSqlca(Sqlca sqlca) {
271: if (sqlca == null) {
272: return 0;
273: }
274: return sqlca.getSqlCode();
275: }
276:
277: static public int getUpdateCountFromSqlcard(Sqlca sqlca) {
278: if (sqlca == null) {
279: return 0;
280: } else {
281: return sqlca.getUpdateCount();
282: }
283: }
284:
285: public static int min(int i, int j) {
286: return (i < j) ? i : j;
287: }
288:
289: public static int max(int i, int j) {
290: return (i < j) ? j : i;
291: }
292:
293: // latestException is assumed to be non-null, accumulatedExceptions can be null
294: public static SQLException accumulateSQLException(
295: SQLException latestException,
296: SQLException accumulatedExceptions) {
297: if (accumulatedExceptions == null) {
298: return latestException;
299: } else {
300: accumulatedExceptions.setNextException(latestException);
301: return accumulatedExceptions;
302: }
303: }
304:
305: public static SqlException accumulateSQLException(
306: SqlException latestException,
307: SqlException accumulatedExceptions) {
308: if (accumulatedExceptions == null) {
309: return latestException;
310: } else {
311: accumulatedExceptions.setNextException(latestException);
312: return accumulatedExceptions;
313: }
314: }
315:
316: // latestException is assumed to be non-null, accumulatedExceptions can be null
317: public static SqlWarning accumulateSQLWarning(
318: SqlWarning latestException, SqlWarning accumulatedExceptions) {
319: latestException.setNextException(accumulatedExceptions);
320: return latestException;
321: }
322:
323: // just a thought...
324: static String getSQLTypeName(int sqlType) {
325: switch (sqlType) {
326: case java.sql.Types.BIGINT:
327: return "BIGINT";
328: case java.sql.Types.BINARY:
329: return "BINARY";
330: case java.sql.Types.BIT:
331: return "BIT";
332: case java.sql.Types.CHAR:
333: return "CHAR";
334: case java.sql.Types.DATE:
335: return "DATE";
336: case java.sql.Types.DECIMAL:
337: return "DECIMAL";
338: case java.sql.Types.DOUBLE:
339: return "DOUBLE";
340: case java.sql.Types.REAL:
341: return "REAL";
342: case java.sql.Types.INTEGER:
343: return "INTEGER";
344: case java.sql.Types.LONGVARBINARY:
345: return "LONGVARBINARY";
346: case java.sql.Types.LONGVARCHAR:
347: return "LONGVARCHAR";
348: case java.sql.Types.NULL:
349: return "NULL";
350: case java.sql.Types.NUMERIC:
351: return "NUMERIC";
352: case java.sql.Types.OTHER:
353: return "OTHER";
354: case java.sql.Types.FLOAT:
355: return "FLOAT";
356: case java.sql.Types.SMALLINT:
357: return "SMALLINT";
358: case java.sql.Types.TIME:
359: return "TIME";
360: case java.sql.Types.TIMESTAMP:
361: return "TIMESTAMP";
362: case java.sql.Types.TINYINT:
363: return "TINYINT";
364: case java.sql.Types.VARBINARY:
365: return "VARBINARY";
366: case java.sql.Types.VARCHAR:
367: return "VARCHAR";
368: default:
369: return null;
370: }
371: }
372:
373: public static boolean isSqlTypeNullable(int sqlType) {
374: return (sqlType | 0x01) == sqlType;
375: }
376:
377: public static int getNonNullableSqlType(int sqlType) {
378: return sqlType & ~1;
379: }
380: }
|