com.microsoft.sqlserver.jdbc.SQLServerException Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mssql-jdbc Show documentation
Show all versions of mssql-jdbc Show documentation
Microsoft JDBC 4.2 Driver for SQL Server.
The Azure Key Vault feature in Microsoft JDBC Driver for SQL Server depends on
Azure SDK for JAVA and Azure Active Directory Library For Java.
//---------------------------------------------------------------------------------------------------------------------------------
// File: SQLServerException.java
//
//
// Microsoft JDBC Driver for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
package com.microsoft.sqlserver.jdbc;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.*;
/**
* SQLServerException is thrown from any point in the driver that throws a java.sql.SQLException.
* SQLServerException handles both SQL 92 and XOPEN state codes. They are switchable via a
* user specified connection property.
* SQLServerExceptions are written to any open log files the user has specified.
*/
enum SQLState
{
STATEMENT_CANCELED ("HY008"),
DATA_EXCEPTION_NOT_SPECIFIC ("22000"),
DATA_EXCEPTION_DATETIME_FIELD_OVERFLOW ("22008"),
DATA_EXCEPTION_LENGTH_MISMATCH ("22026"),
COL_NOT_FOUND ("42S22");
private final String sqlStateCode;
final String getSQLStateCode() { return sqlStateCode; }
SQLState(String sqlStateCode)
{
this.sqlStateCode = sqlStateCode;
}
}
enum DriverError
{
NOT_SET (0);
private final int errorCode;
final int getErrorCode() { return errorCode; }
DriverError(int errorCode)
{
this.errorCode = errorCode;
}
}
public final class SQLServerException extends java.sql.SQLException
{
static final String EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH = "08001";
static final String EXCEPTION_XOPEN_CONNECTION_DOES_NOT_EXIST = "08003";
static final String EXCEPTION_XOPEN_CONNECTION_FAILURE = "08006"; //After connection was connected OK
static final String LOG_CLIENT_CONNECTION_ID_PREFIX = " ClientConnectionId:";
// SQL error values (from sqlerrorcodes.h)
static final int LOGON_FAILED = 18456;
static final int PASSWORD_EXPIRED = 18488;
static java.util.logging.Logger exLogger = java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerException");
// Facility for driver-specific error codes
static final int DRIVER_ERROR_NONE = 0;
static final int DRIVER_ERROR_FROM_DATABASE = 2;
static final int DRIVER_ERROR_IO_FAILED = 3;
static final int DRIVER_ERROR_INVALID_TDS = 4;
static final int DRIVER_ERROR_SSL_FAILED = 5;
static final int DRIVER_ERROR_UNSUPPORTED_CONFIG = 6;
static final int DRIVER_ERROR_INTERMITTENT_TLS_FAILED = 7;
private int driverErrorCode = DRIVER_ERROR_NONE;
final int getDriverErrorCode() { return driverErrorCode; }
final void setDriverErrorCode(int value) { driverErrorCode = value; }
/**
* Log an exception to the driver log file
* @param o the io buffer that generated the exception
* @param errText the excception message
* @param bStack true to generate the stack trace
*/
/*L0*/ private void logException(Object o, String errText, boolean bStack)
{
String id="";
if (o!=null)
id = o.toString();
if (exLogger.isLoggable(Level.FINE))
exLogger.fine("*** SQLException:"+id+" "+this.toString()+" "+errText);
if (bStack)
{
if (exLogger.isLoggable(Level.FINE))
{
StringBuilder sb = new StringBuilder(100);
StackTraceElement st[] = this.getStackTrace();
for(int i=0; i = 20) && (null != con))
{
con.notifyPooledConnection(theException);
con.close();
}
throw theException;
}
//This code is same as the conversion logic that previously existed in connecthelper.
static void ConvertConnectExceptionToSQLServerException(String hostName, int portNumber, SQLServerConnection conn, Exception ex) throws SQLServerException
{
Exception connectException = ex;
// Throw the exception if exception was caught by code above (stored in connectException).
if (connectException != null)
{
MessageFormat formDetail = new MessageFormat(SQLServerException.getErrString("R_tcpOpenFailed"));
Object[] msgArgsDetail = {connectException.getMessage()};
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_tcpipConnectionFailed"));
Object[] msgArgs = {hostName, Integer.toString(portNumber), formDetail.format(msgArgsDetail)};
String s = form.format(msgArgs);
SQLServerException.makeFromDriverError(conn, conn, s,
SQLServerException.
EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH, false);
}
}
/**
* Map XOPEN states.
* @param state the state
* @return the mapped state
*/
/*L0*/ static String mapFromXopen(String state)
{
//Exceptions generated by the driver (not the database) are instanced with an XOPEN state code
//since the SQL99 states cant be located on the web (must pay) and the XOPEN states appear to
//be specific. Therefore if the driver is in SQL 99 mode we must map to SQL 99 state codes.
//SQL99 values based on previous SQLServerConnect code and some inet values..
if (state==null)
return null;
if (state.equals("07009"))
return "S1093";
//Connection (network) failure after connection made
if (state.equals(SQLServerException.EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH))
return "08S01";
if (state.equals(SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE))
return "08S01";
//if (state.equals(SQLServerException.EXCEPTION_XOPEN_NETWORK_ERROR))
//return "S0022"; //Previous SQL99 state code for bad column name
return "";
}
/**
* Generate the JDBC state code based on the error number returned from the database
* @param con the connection
* @param errNum the error number
* @param databaseState the database state
* @return the state code
*/
/*L0*/ static String generateStateCode(SQLServerConnection con, int errNum, int databaseState)
{
//Generate a SQL 99 or XOPEN state from a database generated error code
boolean xopenStates = (con!=null && con.xopenStates);
if (xopenStates)
{
switch (errNum)
{
case 4060: return "08001"; //Database name undefined at loging
case 18456: return "08001"; //username password wrong at login
case 2714: return "42S01"; //Table already exists
case 208: return "42S02"; //Table not found
case 207: return "42S22"; //Column not found
//case 156: return "42000"; //Invalid syntax
}
return "42000"; //Use XOPEN 'Syntax error or access violation'
//The error code came from the db but XOPEN does not have a specific case for it.
}
else
{
switch (errNum)
{
//case 18456: return "08001"; //username password wrong at login
case 8152: return "22001"; //String data right truncation
case 515: //2.2705
case 547: return "23000"; //Integrity constraint violation
case 2601:return "23000"; //Integrity constraint violation
case 2714: return "S0001"; //table already exists
case 208: return "S0002"; //table not found
case 1205: return "40001"; //deadlock detected
case 2627: return "23000"; //DPM 4.04. Primary key violation
}
return "S000"+databaseState;
}
}
/**
* Append ClientConnectionId to an error message if applicable
* @param errMsg - the orginal error message.
* @param conn - the SQLServerConnection object
* @return error string concated by ClientConnectionId(in string format) if applicable,
* otherwise, return original error string.
*/
static String checkAndAppendClientConnId(String errMsg, SQLServerConnection conn) throws SQLServerException
{
if(null != conn && conn.attachConnId())
{
UUID clientConnId = conn.getClientConIdInternal();
assert null != clientConnId;
StringBuilder sb = new StringBuilder (errMsg);
// This syntex of adding connection id is matched in a retry logic. If anything changes here, make
// necessary changes to enableSSL() function's exception handling mechanism.
sb.append(LOG_CLIENT_CONNECTION_ID_PREFIX);
sb.append(clientConnId.toString());
return sb.toString();
}
else
return errMsg;
}
}