001: // jTDS JDBC Driver for Microsoft SQL Server and Sybase
002: // Copyright (C) 2004 The jTDS Project
003: //
004: // This library is free software; you can redistribute it and/or
005: // modify it under the terms of the GNU Lesser General Public
006: // License as published by the Free Software Foundation; either
007: // version 2.1 of the License, or (at your option) any later version.
008: //
009: // This library is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: // Lesser General Public License for more details.
013: //
014: // You should have received a copy of the GNU Lesser General Public
015: // License along with this library; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: //
018: package net.sourceforge.jtds.jdbc;
019:
020: import java.sql.DataTruncation;
021: import java.sql.SQLException;
022: import java.sql.SQLWarning;
023: import java.util.HashMap;
024:
025: /**
026: * Helper class for handling SQL warnings and errors. <p>Assigns SQL state values
027: * in accordance to the native error number returned by the database server.
028: *
029: * @author Alin Sinpalean
030: * @author Mike Hutchinson
031: * @version $Id: SQLDiagnostic.java,v 1.12 2007/08/05 20:17:54 bheineman Exp $
032: */
033: class SQLDiagnostic {
034: /**
035: * Map to convert Microsoft SQL server error codes to ANSI SQLSTATE codes.
036: * The values in this table are derived from the list compiled by the
037: * FreeTDS project. Thank you for the hard work.
038: */
039: private final static HashMap mssqlStates = new HashMap();
040:
041: /**
042: * Map to convert Sybase SQL server error codes to ANSI SQLSTATE codes.
043: * The values in this table are derived from the list compiled by the
044: * FreeTDS project. Thank you for the hard work.
045: */
046: private final static HashMap sybStates = new HashMap();
047:
048: static {
049: // When adding values into this map please ensure that you maintain
050: // the ascending order. This is for readability purposes only, but it's
051: // still important.
052: mssqlStates.put(new Integer(102), "42000"); // ADDED
053: mssqlStates.put(new Integer(105), "37000"); // ADDED
054: mssqlStates.put(new Integer(109), "21S01");
055: mssqlStates.put(new Integer(110), "21S01");
056: mssqlStates.put(new Integer(113), "42000");
057: mssqlStates.put(new Integer(131), "37000");
058: mssqlStates.put(new Integer(168), "22003");
059: mssqlStates.put(new Integer(170), "37000");
060: mssqlStates.put(new Integer(174), "37000");
061: mssqlStates.put(new Integer(195), "42000"); // ADDED
062: mssqlStates.put(new Integer(201), "37000");
063: mssqlStates.put(new Integer(206), "22005"); // ADDED
064: mssqlStates.put(new Integer(207), "42S22"); // (i-net is 42000)
065: mssqlStates.put(new Integer(208), "S0002"); // MODIFIED: was 42S02 (i-net is 42000) (Microsoft is S0002)
066: mssqlStates.put(new Integer(210), "22007"); // ? (i-net is 22008)
067: mssqlStates.put(new Integer(211), "22008"); // ADDED
068: mssqlStates.put(new Integer(213), "42000"); // MODIFIED: was 21S01
069: mssqlStates.put(new Integer(220), "22003");
070: mssqlStates.put(new Integer(229), "42000");
071: mssqlStates.put(new Integer(230), "42000");
072: mssqlStates.put(new Integer(232), "22003");
073: mssqlStates.put(new Integer(233), "23000"); // ADDED
074: mssqlStates.put(new Integer(234), "22003"); // ADDED
075: mssqlStates.put(new Integer(235), "22005"); // ADDED
076: mssqlStates.put(new Integer(236), "22003"); // ADDED
077: mssqlStates.put(new Integer(237), "22003"); // ADDED
078: mssqlStates.put(new Integer(238), "22003"); // ADDED
079: mssqlStates.put(new Integer(241), "22007"); // ? (i-net is 22008)
080: mssqlStates.put(new Integer(242), "22008");
081: mssqlStates.put(new Integer(244), "22003"); // ADDED
082: mssqlStates.put(new Integer(245), "22018"); // ? (i-net is 22005)
083: mssqlStates.put(new Integer(246), "22003"); // ADDED
084: mssqlStates.put(new Integer(247), "22005"); // ADDED
085: mssqlStates.put(new Integer(248), "22003"); // ADDED
086: mssqlStates.put(new Integer(249), "22005"); // ADDED
087: mssqlStates.put(new Integer(256), "22005"); // ADDED
088: mssqlStates.put(new Integer(257), "22005"); // ADDED
089: mssqlStates.put(new Integer(260), "42000"); // ADDED
090: mssqlStates.put(new Integer(262), "42000");
091: mssqlStates.put(new Integer(266), "25000");
092: mssqlStates.put(new Integer(272), "23000"); // ADDED
093: mssqlStates.put(new Integer(273), "23000"); // ADDED
094: mssqlStates.put(new Integer(277), "25000"); // ADDED
095: mssqlStates.put(new Integer(295), "22007"); // ? (i-net is 22008)
096: mssqlStates.put(new Integer(296), "22008");
097: mssqlStates.put(new Integer(298), "22008");
098: mssqlStates.put(new Integer(305), "22005"); // ADDED
099: mssqlStates.put(new Integer(307), "42S12");
100: mssqlStates.put(new Integer(308), "42S12");
101: mssqlStates.put(new Integer(310), "22025"); // ADDED
102: mssqlStates.put(new Integer(409), "22005"); // ADDED
103: mssqlStates.put(new Integer(506), "22019"); // ADDED
104: mssqlStates.put(new Integer(512), "21000");
105: mssqlStates.put(new Integer(515), "23000");
106: mssqlStates.put(new Integer(517), "22008"); // ?
107: mssqlStates.put(new Integer(518), "22005"); // ADDED
108: mssqlStates.put(new Integer(519), "22003"); // ADDED
109: mssqlStates.put(new Integer(520), "22003"); // ADDED
110: mssqlStates.put(new Integer(521), "22003"); // ADDED
111: mssqlStates.put(new Integer(522), "22003"); // ADDED
112: mssqlStates.put(new Integer(523), "22003"); // ADDED
113: mssqlStates.put(new Integer(524), "22003"); // ADDED
114: mssqlStates.put(new Integer(529), "22005"); // ADDED
115: mssqlStates.put(new Integer(530), "23000"); // ADDED
116: mssqlStates.put(new Integer(532), "01001"); // ADDED
117: mssqlStates.put(new Integer(535), "22003"); // MODIFIED: was 22008
118: mssqlStates.put(new Integer(542), "22008");
119: mssqlStates.put(new Integer(544), "23000");
120: mssqlStates.put(new Integer(547), "23000");
121: mssqlStates.put(new Integer(550), "44000"); // MODIFIED: was 23000
122: mssqlStates.put(new Integer(611), "25000"); // ADDED
123: mssqlStates.put(new Integer(626), "25000");
124: mssqlStates.put(new Integer(627), "25000");
125: mssqlStates.put(new Integer(628), "25000");
126: mssqlStates.put(new Integer(911), "08004"); // WRONG: db not found != connection rejected
127: mssqlStates.put(new Integer(1007), "22003");
128: mssqlStates.put(new Integer(1010), "22019"); // ADDED
129: mssqlStates.put(new Integer(1205), "40001"); // ADDED
130: mssqlStates.put(new Integer(1211), "40001"); // ADDED
131: mssqlStates.put(new Integer(1505), "23000");
132: mssqlStates.put(new Integer(1508), "23000");
133: mssqlStates.put(new Integer(1774), "21S02");
134: mssqlStates.put(new Integer(1911), "42S22");
135: mssqlStates.put(new Integer(1913), "42S11");
136: mssqlStates.put(new Integer(2526), "37000");
137: mssqlStates.put(new Integer(2557), "42000");
138: mssqlStates.put(new Integer(2571), "42000");
139: mssqlStates.put(new Integer(2601), "23000"); // ADDED
140: mssqlStates.put(new Integer(2615), "23000"); // ADDED
141: mssqlStates.put(new Integer(2625), "40001"); // ADDED
142: mssqlStates.put(new Integer(2626), "23000"); // ADDED
143: mssqlStates.put(new Integer(2627), "23000");
144: mssqlStates.put(new Integer(2714), "S0001"); // MODIFIED: was 42S01 (Microsoft is S0001)
145: mssqlStates.put(new Integer(2760), "42000");
146: mssqlStates.put(new Integer(2812), "37000");
147: mssqlStates.put(new Integer(3110), "42000");
148: mssqlStates.put(new Integer(3309), "40001"); // ADDED
149: mssqlStates.put(new Integer(3604), "23000"); // ADDED
150: mssqlStates.put(new Integer(3605), "23000"); // ADDED
151: mssqlStates.put(new Integer(3606), "22003");
152: mssqlStates.put(new Integer(3607), "22012");
153: mssqlStates.put(new Integer(3621), "01000");
154: mssqlStates.put(new Integer(3701), "42S02");
155: mssqlStates.put(new Integer(3704), "42000");
156: mssqlStates.put(new Integer(3725), "23000");
157: mssqlStates.put(new Integer(3726), "23000");
158: mssqlStates.put(new Integer(3902), "25000");
159: mssqlStates.put(new Integer(3903), "25000");
160: mssqlStates.put(new Integer(3906), "25000"); // ADDED
161: mssqlStates.put(new Integer(3908), "25000"); // ADDED
162: mssqlStates.put(new Integer(3915), "25000"); // ADDED
163: mssqlStates.put(new Integer(3916), "25000");
164: mssqlStates.put(new Integer(3918), "25000");
165: mssqlStates.put(new Integer(3919), "25000");
166: mssqlStates.put(new Integer(3921), "25000");
167: mssqlStates.put(new Integer(3922), "25000");
168: mssqlStates.put(new Integer(3926), "25000");
169: mssqlStates.put(new Integer(3960), "S0005"); // ADDED for Feature Request 1491811
170: mssqlStates.put(new Integer(4415), "44000"); // MODIFIED: was 23000
171: mssqlStates.put(new Integer(4613), "42000");
172: mssqlStates.put(new Integer(4618), "42000");
173: mssqlStates.put(new Integer(4712), "23000");
174: mssqlStates.put(new Integer(4834), "42000");
175: mssqlStates.put(new Integer(4924), "42S22");
176: mssqlStates.put(new Integer(4925), "42S21");
177: mssqlStates.put(new Integer(4926), "42S22");
178: mssqlStates.put(new Integer(5011), "42000");
179: mssqlStates.put(new Integer(5116), "42000");
180: mssqlStates.put(new Integer(5146), "22003");
181: mssqlStates.put(new Integer(5812), "42000");
182: mssqlStates.put(new Integer(6004), "42000");
183: mssqlStates.put(new Integer(6102), "42000");
184: mssqlStates.put(new Integer(6104), "37000");
185: mssqlStates.put(new Integer(6401), "25000"); // ADDED
186: mssqlStates.put(new Integer(7112), "40001"); // ADDED
187: mssqlStates.put(new Integer(7956), "42000");
188: mssqlStates.put(new Integer(7969), "25000");
189: mssqlStates.put(new Integer(8114), "37000");
190: mssqlStates.put(new Integer(8115), "22003");
191: mssqlStates.put(new Integer(8134), "22012");
192: mssqlStates.put(new Integer(8144), "37000");
193: mssqlStates.put(new Integer(8152), "22001");
194: mssqlStates.put(new Integer(8162), "37000"); // ADDED
195: mssqlStates.put(new Integer(8153), "01003");
196: mssqlStates.put(new Integer(8506), "25000");
197: mssqlStates.put(new Integer(10015), "22003"); // ADDED
198: mssqlStates.put(new Integer(10033), "42S12");
199: mssqlStates.put(new Integer(10055), "23000");
200: mssqlStates.put(new Integer(10065), "23000");
201: mssqlStates.put(new Integer(10095), "01001"); // ADDED
202: mssqlStates.put(new Integer(11010), "42000");
203: mssqlStates.put(new Integer(11011), "23000");
204: mssqlStates.put(new Integer(11040), "23000");
205: mssqlStates.put(new Integer(11045), "42000");
206: mssqlStates.put(new Integer(14126), "42000");
207: mssqlStates.put(new Integer(15247), "42000");
208: mssqlStates.put(new Integer(15323), "42S12");
209: mssqlStates.put(new Integer(15605), "42S11");
210: mssqlStates.put(new Integer(15622), "42000");
211: mssqlStates.put(new Integer(15626), "25000");
212: mssqlStates.put(new Integer(15645), "42S22");
213: mssqlStates.put(new Integer(16905), "24000");
214: mssqlStates.put(new Integer(16909), "24000"); // ADDED
215: mssqlStates.put(new Integer(16911), "24000"); // ADDED
216: mssqlStates.put(new Integer(16917), "24000");
217: mssqlStates.put(new Integer(16934), "24000"); // ADDED
218: mssqlStates.put(new Integer(16946), "24000");
219: mssqlStates.put(new Integer(16950), "24000");
220: mssqlStates.put(new Integer(16999), "24000");
221: mssqlStates.put(new Integer(17308), "42000");
222: mssqlStates.put(new Integer(17571), "42000");
223: mssqlStates.put(new Integer(18002), "42000");
224: mssqlStates.put(new Integer(18452), "28000");
225: mssqlStates.put(new Integer(18456), "28000");
226: mssqlStates.put(new Integer(18833), "42S12");
227: mssqlStates.put(new Integer(20604), "42000");
228: mssqlStates.put(new Integer(21049), "42000");
229: mssqlStates.put(new Integer(21166), "42S22");
230: mssqlStates.put(new Integer(21255), "42S21");
231:
232: // When adding values into this map please ensure that you maintain
233: // the ascending order. This is for readability purposes only, but it's
234: // still important.
235: sybStates.put(new Integer(102), "37000");
236: sybStates.put(new Integer(109), "21S01");
237: sybStates.put(new Integer(110), "21S01");
238: sybStates.put(new Integer(113), "42000");
239: sybStates.put(new Integer(168), "22003");
240: sybStates.put(new Integer(201), "37000");
241: sybStates.put(new Integer(207), "42S22");
242: sybStates.put(new Integer(208), "42S02");
243: sybStates.put(new Integer(213), "21S01");
244: sybStates.put(new Integer(220), "22003");
245: sybStates.put(new Integer(227), "22003");
246: sybStates.put(new Integer(229), "42000");
247: sybStates.put(new Integer(230), "42000");
248: sybStates.put(new Integer(232), "22003");
249: sybStates.put(new Integer(233), "23000");
250: sybStates.put(new Integer(245), "22018");
251: sybStates.put(new Integer(247), "22003");
252: sybStates.put(new Integer(257), "37000");
253: sybStates.put(new Integer(262), "42000");
254: sybStates.put(new Integer(277), "25000");
255: sybStates.put(new Integer(307), "42S12");
256: sybStates.put(new Integer(512), "21000");
257: sybStates.put(new Integer(517), "22008");
258: sybStates.put(new Integer(535), "22008");
259: sybStates.put(new Integer(542), "22008");
260: sybStates.put(new Integer(544), "23000");
261: sybStates.put(new Integer(545), "23000");
262: sybStates.put(new Integer(546), "23000");
263: sybStates.put(new Integer(547), "23000");
264: sybStates.put(new Integer(548), "23000");
265: sybStates.put(new Integer(549), "23000");
266: sybStates.put(new Integer(550), "23000");
267: sybStates.put(new Integer(558), "24000");
268: sybStates.put(new Integer(559), "24000");
269: sybStates.put(new Integer(562), "24000");
270: sybStates.put(new Integer(565), "24000");
271: sybStates.put(new Integer(583), "24000");
272: sybStates.put(new Integer(611), "25000");
273: sybStates.put(new Integer(627), "25000");
274: sybStates.put(new Integer(628), "25000");
275: sybStates.put(new Integer(641), "25000");
276: sybStates.put(new Integer(642), "25000");
277: sybStates.put(new Integer(911), "08004");
278: sybStates.put(new Integer(1276), "25000");
279: sybStates.put(new Integer(1505), "23000");
280: sybStates.put(new Integer(1508), "23000");
281: sybStates.put(new Integer(1715), "21S02");
282: sybStates.put(new Integer(1720), "42S22");
283: sybStates.put(new Integer(1913), "42S11");
284: sybStates.put(new Integer(1921), "42S21");
285: sybStates.put(new Integer(2526), "37000");
286: sybStates.put(new Integer(2714), "42S01");
287: sybStates.put(new Integer(2812), "37000");
288: sybStates.put(new Integer(3606), "22003");
289: sybStates.put(new Integer(3607), "22012");
290: sybStates.put(new Integer(3621), "01000");
291: sybStates.put(new Integer(3701), "42S02");
292: sybStates.put(new Integer(3902), "25000");
293: sybStates.put(new Integer(3903), "25000");
294: sybStates.put(new Integer(4602), "42000");
295: sybStates.put(new Integer(4603), "42000");
296: sybStates.put(new Integer(4608), "42000");
297: sybStates.put(new Integer(4934), "42S22");
298: sybStates.put(new Integer(6104), "37000");
299: sybStates.put(new Integer(6235), "24000");
300: sybStates.put(new Integer(6259), "24000");
301: sybStates.put(new Integer(6260), "24000");
302: sybStates.put(new Integer(7010), "42S12");
303: sybStates.put(new Integer(7327), "37000");
304: sybStates.put(new Integer(9501), "01003");
305: sybStates.put(new Integer(9502), "22001");
306: sybStates.put(new Integer(10306), "42000");
307: sybStates.put(new Integer(10323), "42000");
308: sybStates.put(new Integer(10330), "42000");
309: sybStates.put(new Integer(10331), "42000");
310: sybStates.put(new Integer(10332), "42000");
311: sybStates.put(new Integer(11021), "37000");
312: sybStates.put(new Integer(11110), "42000");
313: sybStates.put(new Integer(11113), "42000");
314: sybStates.put(new Integer(11118), "42000");
315: sybStates.put(new Integer(11121), "42000");
316: sybStates.put(new Integer(17222), "42000");
317: sybStates.put(new Integer(17223), "42000");
318: sybStates.put(new Integer(18091), "42S12");
319: sybStates.put(new Integer(18117), "42S22");
320: sybStates.put(new Integer(18350), "42000");
321: sybStates.put(new Integer(18351), "42000");
322: }
323:
324: /**
325: * SQL Server type. Either <code>Driver.SQLSERVER</code> or
326: * <code>Driver.SYBASE</code>.
327: */
328: private final int serverType;
329:
330: SQLException exceptions;
331: SQLWarning warnings;
332:
333: void addWarning(SQLWarning w) {
334: if (warnings == null) {
335: warnings = w;
336: } else {
337: warnings.setNextWarning(w);
338: }
339: }
340:
341: void addException(SQLException e) {
342: if (exceptions == null) {
343: exceptions = e;
344: } else {
345: exceptions.setNextException(e);
346: }
347: }
348:
349: /**
350: * Create a dianostic SQLException or SQLWarning.
351: *
352: * @param number SQL Server error number.
353: * @param state SQL Server state code.
354: * @param serverity SQL Server serverity > 10 = error.
355: * @param message SQL Server error message text.
356: * @param server SQL Server name.
357: * @param procName SQL Server stored procedure name.
358: * @param line SQL Server error line number in SQL source.
359: */
360: void addDiagnostic(int number, int state, int serverity,
361: String message, String server, String procName, int line) {
362: if (serverity > 10) {
363: SQLException e = new SQLException(message, getStateCode(
364: number, serverType, "S1000"), number);
365: //
366: // See if the driver should return a DataTrunction exception
367: //
368: if ((serverType == Driver.SQLSERVER && (number == 8152
369: || number == 8115 || number == 220))
370: || (serverType == Driver.SYBASE && (number == 247 || number == 9502))) {
371: SQLException tmp = e;
372: e = new DataTruncation(-1, false, false, -1, -1);
373: // Chain the original exception as this has useful info.
374: e.setNextException(tmp);
375: }
376:
377: addException(e);
378: } else {
379: if (number == 0) {
380: // Output from a TransactSQL print statement.
381: SQLWarning w = new SQLWarning(message, null, 0);
382: addWarning(w);
383: } else {
384: SQLWarning w = new SQLWarning(message, getStateCode(
385: number, serverType, "01000"), number);
386: addWarning(w);
387: }
388: }
389: }
390:
391: /**
392: * Clear the warning chain.
393: */
394: void clearWarnings() {
395: warnings = null;
396: }
397:
398: /**
399: * Check the exception chain for errors and throw any found
400: * as an SQLException.
401: *
402: * @throws SQLException
403: */
404: void checkErrors() throws SQLException {
405: if (exceptions != null) {
406: SQLException tmp = exceptions;
407: exceptions = null;
408: throw tmp;
409: }
410: }
411:
412: /**
413: * Return the warning chain.
414: *
415: * @return The warning chain head as a <code>SQLWarning</code>.
416: */
417: SQLWarning getWarnings() {
418: return warnings;
419: }
420:
421: /**
422: * Create an SQL message for a specific server type.
423: *
424: * @param serverType either <code>Driver.SQLSERVER</code> or <code>Driver.SYBASE</code>
425: */
426: SQLDiagnostic(final int serverType) {
427: this .serverType = serverType;
428: }
429:
430: /**
431: * Map an SQL Server error code to an ANSI SQLSTATE code.
432: *
433: * @param number the SQL Server error number
434: * @param serverType <code>Driver.SQLSERVER</code> or <code>Driver.SYBASE</code>
435: * @param defState the default state code to return if the mapping fails
436: * @return the SQLSTATE code as a <code>String</code>
437: */
438: private static String getStateCode(final int number,
439: final int serverType, final String defState) {
440: final HashMap stateTable = (serverType == Driver.SYBASE) ? sybStates
441: : mssqlStates;
442: final String state = (String) stateTable
443: .get(new Integer(number));
444:
445: if (state != null) {
446: return state;
447: }
448:
449: return defState;
450: }
451: }
|