diff --git a/CHANGELOG.md b/CHANGELOG.md index c5181e0c2..700f4a6e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) +## [6.5.4] Preview Release +### Added +- Added new connection property "useBulkCopyForBatchInsert" to enable Bulk Copy API support for batch insert operation [#686](https://github.com/Microsoft/mssql-jdbc/pull/686) +- Added implementation for Java 9 introduced Boundary methods APIs on Connection interface [#708](https://github.com/Microsoft/mssql-jdbc/pull/708) +- Added support for "Data Classification Specifications" on fetched resultsets [#709](https://github.com/Microsoft/mssql-jdbc/pull/709) +- Added support for UTF-8 feature extension [#722](https://github.com/Microsoft/mssql-jdbc/pull/722) + +### Fixed Issues +- Fixed issue with escaping catalog name when retrieving from database metadata [#718](https://github.com/Microsoft/mssql-jdbc/pull/718) +- Fixed issue with tests requiring additional dependencies [#729](https://github.com/Microsoft/mssql-jdbc/pull/729) + +### Changed +- Made driver default compliant to JDBC 4.2 specifications [#711](https://github.com/Microsoft/mssql-jdbc/pull/711) +- Updated ADAL4J dependency version to 1.6.0 [#711](https://github.com/Microsoft/mssql-jdbc/pull/711) +- Cleaned up socket handling implementation to generalize functionality for different JVMs and simplified the logic for single address case [#663](https://github.com/Microsoft/mssql-jdbc/pull/663) + ## [6.5.3] Preview Release ### Added - Added removed constructor back to AKV Provider which supports authentication with a customized method to fetch accessToken [#675](https://github.com/Microsoft/mssql-jdbc/pull/675) @@ -35,7 +51,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) ## [6.5.1] Preview Release ### Added -- Test cases for Date, Time, and Datetime2 data types. [#558](https://github.com/Microsoft/mssql-jdbc/pull/558) +- Test cases for Date, Time, and Datetime2 data types [#558](https://github.com/Microsoft/mssql-jdbc/pull/558) ### Fixed Issues - Fixed an issue where ResultSetMetadata returned incorrect columnType for Geometry and Geography data types [#657](https://github.com/Microsoft/mssql-jdbc/pull/657) @@ -93,7 +109,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) ## [6.3.4] Preview Release ### Added -- Added new ThreadGroup creation to prevent IllegalThreadStateException if the underlying ThreadGroup has been destroyed. [#474](https://github.com/Microsoft/mssql-jdbc/pull/474) +- Added new ThreadGroup creation to prevent IllegalThreadStateException if the underlying ThreadGroup has been destroyed [#474](https://github.com/Microsoft/mssql-jdbc/pull/474) - Added try-with-resources to JUnit tests [#520](https://github.com/Microsoft/mssql-jdbc/pull/520) ### Fixed Issues diff --git a/README.md b/README.md index 23ea036a4..ece0f9277 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ To get the latest preview version of the driver, add the following to your POM f com.microsoft.sqlserver mssql-jdbc - 6.5.3.jre10-preview + 6.5.4.jre10-preview ``` @@ -118,14 +118,14 @@ Projects that require either of the two features need to explicitly declare the com.microsoft.sqlserver mssql-jdbc - 6.5.3.jre10-preview + 6.5.4.jre10-preview compile com.microsoft.azure adal4j - 1.5.0 + 1.6.0 ``` @@ -134,14 +134,14 @@ Projects that require either of the two features need to explicitly declare the com.microsoft.sqlserver mssql-jdbc - 6.5.3.jre10-preview + 6.5.4.jre10-preview compile com.microsoft.azure adal4j - 1.5.0 + 1.6.0 diff --git a/build.gradle b/build.gradle index bbb65a5fe..d6955d5c3 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ apply plugin: 'java' -version = '6.5.3' +version = '6.5.4' def jreVersion = "" def testOutputDir = file("build/classes/java/test") def archivesBaseName = 'mssql-jdbc' @@ -79,7 +79,7 @@ repositories { dependencies { compile 'com.microsoft.azure:azure-keyvault:1.0.0', - 'com.microsoft.azure:adal4j:1.5.0' + 'com.microsoft.azure:adal4j:1.6.0' testCompile 'junit:junit:4.12', 'org.junit.platform:junit-platform-console:1.2.0', 'org.junit.platform:junit-platform-commons:1.2.0', diff --git a/pom.xml b/pom.xml index c35395c07..8546b7cb8 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.microsoft.sqlserver mssql-jdbc - 6.5.3 + 6.5.4 jar Microsoft JDBC Driver for SQL Server @@ -54,7 +54,7 @@ com.microsoft.azure adal4j - 1.5.0 + 1.6.0 true diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Geography.java b/src/main/java/com/microsoft/sqlserver/jdbc/Geography.java index 0790a0691..8726cb001 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Geography.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Geography.java @@ -15,8 +15,15 @@ public class Geography extends SQLServerSpatialDatatype { /** * Private constructor used for creating a Geography object from WKT and srid. + * + * @param WellKnownText + * Well-Known Text (WKT) provided by the user. + * @param srid + * Spatial Reference Identifier (SRID) provided by the user. + * @throws SQLServerException + * if an exception occurs */ - private Geography(String WellKnownText, int srid) { + private Geography(String WellKnownText, int srid) throws SQLServerException { this.wkt = WellKnownText; this.srid = srid; @@ -24,7 +31,8 @@ private Geography(String WellKnownText, int srid) { parseWKTForSerialization(this, currentWktPos, -1, false); } catch (StringIndexOutOfBoundsException e) { - throw new IllegalArgumentException("Reached unexpected end of WKT. Please make sure WKT is valid."); + String strError = SQLServerException.getErrString("R_illegalWKT"); + throw new SQLServerException(strError, null, 0, null); } serializeToWkb(false); @@ -33,8 +41,13 @@ private Geography(String WellKnownText, int srid) { /** * Private constructor used for creating a Geography object from WKB. + * + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @throws SQLServerException + * if an exception occurs */ - private Geography(byte[] wkb) { + private Geography(byte[] wkb) throws SQLServerException { this.wkb = wkb; buffer = ByteBuffer.wrap(wkb); buffer.order(ByteOrder.LITTLE_ENDIAN); @@ -51,19 +64,20 @@ private Geography(byte[] wkb) { isNull = false; } - public Geography() { - // TODO Auto-generated constructor stub - } - /** * Returns a Geography instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) * representation augmented with any Z (elevation) and M (measure) values carried by the instance. * - * @param wkt WKT - * @param srid SRID - * @return Geography instance + * @param wkt + * Well-Known Text (WKT) provided by the user. + * @param srid + * Spatial Reference Identifier (SRID) provided by the user. + * @return Geography + * Geography instance created from WKT and SRID + * @throws SQLServerException + * if an exception occurs */ - public static Geography STGeomFromText(String wkt, int srid) { + public static Geography STGeomFromText(String wkt, int srid) throws SQLServerException { return new Geography(wkt, srid); } @@ -71,20 +85,28 @@ public static Geography STGeomFromText(String wkt, int srid) { * Returns a Geography instance from an Open Geospatial Consortium (OGC) * Well-Known Binary (WKB) representation. * - * @param wkb WKB - * @return Geography instance + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @return Geography + * Geography instance created from WKB + * @throws SQLServerException + * if an exception occurs */ - public static Geography STGeomFromWKB(byte[] wkb) { + public static Geography STGeomFromWKB(byte[] wkb) throws SQLServerException { return new Geography(wkb); } /** * Returns a constructed Geography from an internal SQL Server format for spatial data. * - * @param wkb WKB - * @return Geography instance + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @return Geography + * Geography instance created from WKB + * @throws SQLServerException + * if an exception occurs */ - public static Geography deserialize(byte[] wkb) { + public static Geography deserialize(byte[] wkb) throws SQLServerException { return new Geography(wkb); } @@ -92,22 +114,32 @@ public static Geography deserialize(byte[] wkb) { * Returns a Geography instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation. * SRID is defaulted to 4326. * - * @param wkt WKt - * @return Geography instance + * @param wkt + * Well-Known Text (WKT) provided by the user. + * @return Geography + * Geography instance created from WKT + * @throws SQLServerException + * if an exception occurs */ - public static Geography parse(String wkt) { + public static Geography parse(String wkt) throws SQLServerException { return new Geography(wkt, 4326); } /** * Constructs a Geography instance that represents a Point instance from its X and Y values and an SRID. * - * @param x x coordinate - * @param y y coordinate - * @param srid SRID - * @return Geography instance + * @param x + * x coordinate + * @param y + * y coordinate + * @param srid + * SRID + * @return Geography + * Geography instance + * @throws SQLServerException + * if an exception occurs */ - public static Geography point(double x, double y, int srid) { + public static Geography point(double x, double y, int srid) throws SQLServerException { return new Geography("POINT (" + x + " " + y + ")", srid); } @@ -115,9 +147,12 @@ public static Geography point(double x, double y, int srid) { * Returns the Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation of a * Geography instance. This text will not contain any Z (elevation) or M (measure) values carried by the instance. * - * @return the WKT representation without the Z and M values. + * @return + * the WKT representation without the Z and M values. + * @throws SQLServerException + * if an exception occurs */ - public String STAsText() { + public String STAsText() throws SQLServerException { if (null == wktNoZM) { buffer = ByteBuffer.wrap(wkb); buffer.order(ByteOrder.LITTLE_ENDIAN); @@ -135,7 +170,8 @@ public String STAsText() { /** * Returns the Open Geospatial Consortium (OGC) Well-Known Binary (WKB) representation of a * Geography instance. This value will not contain any Z or M values carried by the instance. - * @return WKB + * + * @return byte array representation of the Geography object. */ public byte[] STAsBinary() { if (null == wkbNoZM) { @@ -147,20 +183,35 @@ public byte[] STAsBinary() { /** * Returns the bytes that represent an internal SQL Server format of Geography type. * - * @return WKB + * @return byte array representation of the Geography object. */ public byte[] serialize() { return wkb; } + /** + * Returns if the object contains a M (measure) value. + * + * @return boolean that indicates if the object contains M value. + */ public boolean hasM() { return hasMvalues; } + /** + * Returns if the object contains a Z (elevation) value. + * + * @return boolean that indicates if the object contains Z value. + */ public boolean hasZ() { return hasZvalues; } + /** + * Returns the X coordinate value. + * + * @return double value that represents the X coordinate. + */ public Double getX() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && points.length == 2) { return points[0]; @@ -168,6 +219,11 @@ public Double getX() { return null; } + /** + * Returns the Y coordinate value. + * + * @return double value that represents the Y coordinate. + */ public Double getY() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && points.length == 2) { return points[1]; @@ -175,6 +231,11 @@ public Double getY() { return null; } + /** + * Returns the M (measure) value of the object. + * + * @return double value that represents the M value. + */ public Double getM() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && hasM()) { return mValues[0]; @@ -182,6 +243,11 @@ public Double getM() { return null; } + /** + * Returns the Z (elevation) value of the object. + * + * @return double value that represents the Z value. + */ public Double getZ() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && hasZ()) { return zValues[0]; @@ -189,14 +255,29 @@ public Double getZ() { return null; } + /** + * Returns the Spatial Reference Identifier (SRID) value. + * + * @return int value of SRID. + */ public int getSrid() { return srid; } + /** + * Returns if the Geography object is null. + * + * @return boolean that indicates if the object is null. + */ public boolean isNull() { return isNull; } + /** + * Returns the number of points in the Geography object. + * + * @return int that indicates the number of points in the Geography object. + */ public int STNumPoints() { return numberOfPoints; } @@ -204,7 +285,7 @@ public int STNumPoints() { /** * Returns the Open Geospatial Consortium (OGC) type name represented by a Geography instance. * - * @return type name + * @return String that contains the Geography object's type name */ public String STGeographyType() { if (null != internalType) { @@ -213,10 +294,21 @@ public String STGeographyType() { return null; } + /** + * Returns the Well-Known Text (WKT) representation of the Geography object. + * + * @return String that contains the WKT representation of the Geography object. + */ public String asTextZM() { return wkt; } + /** + * Returns the String representation of the Geography object. + * + * @return String that contains the WKT representation of the Geography object. + */ + @Override public String toString() { return wkt; } @@ -245,7 +337,6 @@ protected void serializeToWkb(boolean noZM) { buf.putDouble(zValues[i]); } } - if (hasMvalues) { for (int i = 0; i < numberOfPoints; i++) { buf.putDouble(mValues[i]); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Geometry.java b/src/main/java/com/microsoft/sqlserver/jdbc/Geometry.java index 90f4427a5..45a0960f1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Geometry.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Geometry.java @@ -12,118 +12,155 @@ import java.nio.ByteOrder; public class Geometry extends SQLServerSpatialDatatype { - + /** * Private constructor used for creating a Geometry object from WKT and srid. + * + * @param WellKnownText + * Well-Known Text (WKT) provided by the user. + * @param srid + * Spatial Reference Identifier (SRID) provided by the user. + * @throws SQLServerException + * if an exception occurs */ - private Geometry(String WellKnownText, int srid) { + private Geometry(String WellKnownText, + int srid) throws SQLServerException { this.wkt = WellKnownText; this.srid = srid; - + try { parseWKTForSerialization(this, currentWktPos, -1, false); } catch (StringIndexOutOfBoundsException e) { - throw new IllegalArgumentException("Reached unexpected end of WKT. Please make sure WKT is valid."); + String strError = SQLServerException.getErrString("R_illegalWKT"); + throw new SQLServerException(strError, null, 0, null); } - + serializeToWkb(false); isNull = false; } /** * Private constructor used for creating a Geometry object from WKB. + * + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @throws SQLServerException + * if an exception occurs */ - private Geometry(byte[] wkb) { + private Geometry(byte[] wkb) throws SQLServerException { this.wkb = wkb; buffer = ByteBuffer.wrap(wkb); buffer.order(ByteOrder.LITTLE_ENDIAN); - + parseWkb(); - + WKTsb = new StringBuffer(); WKTsbNoZM = new StringBuffer(); - + constructWKT(this, internalType, numberOfPoints, numberOfFigures, numberOfSegments, numberOfShapes); - + wkt = WKTsb.toString(); wktNoZM = WKTsbNoZM.toString(); isNull = false; } - - public Geometry() { - // TODO Auto-generated constructor stub - } - + /** - * Returns a Geometry instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) - * representation augmented with any Z (elevation) and M (measure) values carried by the instance. - * - * @param wkt WKT - * @param srid SRID - * @return Geometry instance + * Returns a Geometry instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation augmented with any Z (elevation) and + * M (measure) values carried by the instance. + * + * @param wkt + * Well-Known Text (WKT) provided by the user. + * @param srid + * Spatial Reference Identifier (SRID) provided by the user. + * @return Geometry + * Geometry instance created from WKT and SRID + * @throws SQLServerException + * if an exception occurs */ - public static Geometry STGeomFromText(String wkt, int srid) { + public static Geometry STGeomFromText(String wkt, + int srid) throws SQLServerException { return new Geometry(wkt, srid); } - + /** - * Returns a Geometry instance from an Open Geospatial Consortium (OGC) - * Well-Known Binary (WKB) representation. + * Returns a Geometry instance from an Open Geospatial Consortium (OGC) Well-Known Binary (WKB) representation. * - * @param wkb WKB - * @return Geometry instance + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @return Geometry + * Geometry instance created from WKB + * @throws SQLServerException + * if an exception occurs */ - public static Geometry STGeomFromWKB(byte[] wkb) { + public static Geometry STGeomFromWKB(byte[] wkb) throws SQLServerException { return new Geometry(wkb); } - + /** * Returns a constructed Geometry from an internal SQL Server format for spatial data. * - * @param wkb WKB - * @return Geometry instance + * @param wkb + * Well-Known Binary (WKB) provided by the user. + * @return Geometry + * Geometry instance created from WKB + * @throws SQLServerException + * if an exception occurs */ - public static Geometry deserialize(byte[] wkb) { + public static Geometry deserialize(byte[] wkb) throws SQLServerException { return new Geometry(wkb); } /** - * Returns a Geometry instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation. - * SRID is defaulted to 0. + * Returns a Geometry instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation. SRID is defaulted to 0. * - * @param wkt WKT - * @return Geometry instance + * @param wkt + * Well-Known Text (WKT) provided by the user. + * @return Geometry + * Geometry instance created from WKT + * @throws SQLServerException + * if an exception occurs */ - public static Geometry parse(String wkt) { + public static Geometry parse(String wkt) throws SQLServerException { return new Geometry(wkt, 0); } - + /** * Constructs a Geometry instance that represents a Point instance from its X and Y values and an SRID. * - * @param x x coordinate - * @param y y coordinate - * @param srid SRID - * @return Geometry instance + * @param x + * x coordinate + * @param y + * y coordinate + * @param srid + * SRID + * @return Geometry + * Geography instance + * @throws SQLServerException + * if an exception occurs */ - public static Geometry point(double x, double y, int srid) { + public static Geometry point(double x, + double y, + int srid) throws SQLServerException { return new Geometry("POINT (" + x + " " + y + ")", srid); } - + /** - * Returns the Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation of a - * Geometry instance. This text will not contain any Z (elevation) or M (measure) values carried by the instance. + * Returns the Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation of a Geometry instance. This text will not contain any Z + * (elevation) or M (measure) values carried by the instance. * - * @return the WKT representation without the Z and M values. + * @return + * the WKT representation without the Z and M values. + * @throws SQLServerException + * if an exception occurs */ - public String STAsText() { + public String STAsText() throws SQLServerException { if (null == wktNoZM) { buffer = ByteBuffer.wrap(wkb); buffer.order(ByteOrder.LITTLE_ENDIAN); - + parseWkb(); - + WKTsb = new StringBuffer(); WKTsbNoZM = new StringBuffer(); constructWKT(this, internalType, numberOfPoints, numberOfFigures, numberOfSegments, numberOfShapes); @@ -131,11 +168,12 @@ public String STAsText() { } return wktNoZM; } - + /** - * Returns the Open Geospatial Consortium (OGC) Well-Known Binary (WKB) representation of a - * Geometry instance. This value will not contain any Z or M values carried by the instance. - * @return WKB + * Returns the Open Geospatial Consortium (OGC) Well-Known Binary (WKB) representation of a Geometry instance. This value will not contain any Z + * or M values carried by the instance. + * + * @return byte array representation of the Geometry object. */ public byte[] STAsBinary() { if (null == wkbNoZM) { @@ -143,45 +181,75 @@ public byte[] STAsBinary() { } return wkbNoZM; } - + /** - * Returns the bytes that represent an internal SQL Server format of Geometry type. + * Returns the bytes that represent an internal SQL Server format of Geometry type. * - * @return WKB + * @return byte array representation of the Geometry object. */ public byte[] serialize() { return wkb; } - + + /** + * Returns if the object contains a M (measure) value. + * + * @return boolean that indicates if the object contains M value. + */ public boolean hasM() { return hasMvalues; } - + + /** + * Returns if the object contains a Z (elevation) value. + * + * @return boolean that indicates if the object contains Z value. + */ public boolean hasZ() { return hasZvalues; } - + + /** + * Returns the X coordinate value. + * + * @return double value that represents the X coordinate. + */ public Double getX() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && points.length == 2) { return points[0]; } return null; } - + + /** + * Returns the Y coordinate value. + * + * @return double value that represents the Y coordinate. + */ public Double getY() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && points.length == 2) { return points[1]; } return null; } - + + /** + * Returns the M (measure) value of the object. + * + * @return double value that represents the M value. + */ public Double getM() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && hasM()) { return mValues[0]; } return null; } - + + /** + * Returns the Z (elevation) value of the object. + * + * @return double value that represents the Z value. + */ public Double getZ() { if (null != internalType && internalType == InternalSpatialDatatype.POINT && hasZ()) { return zValues[0]; @@ -189,14 +257,29 @@ public Double getZ() { return null; } + /** + * Returns the Spatial Reference Identifier (SRID) value. + * + * @return int value of SRID. + */ public int getSrid() { return srid; } - + + /** + * Returns if the Geometry object is null. + * + * @return boolean that indicates if the object is null. + */ public boolean isNull() { return isNull; } - + + /** + * Returns the number of points in the Geometry object. + * + * @return int that indicates the number of points in the Geometry object. + */ public int STNumPoints() { return numberOfPoints; } @@ -204,7 +287,7 @@ public int STNumPoints() { /** * Returns the Open Geospatial Consortium (OGC) type name represented by a geometry instance. * - * @return type name + * @return String that contains the Geometry object's type name */ public String STGeometryType() { if (null != internalType) { @@ -212,105 +295,117 @@ public String STGeometryType() { } return null; } - + + /** + * Returns the Well-Known Text (WKT) representation of the Geometry object. + * + * @return String that contains the WKT representation of the Geometry object. + */ public String asTextZM() { return wkt; } - + + /** + * Returns the String representation of the Geometry object. + * + * @return String that contains the WKT representation of the Geometry object. + */ + @Override public String toString() { return wkt; } - + protected void serializeToWkb(boolean noZM) { ByteBuffer buf = ByteBuffer.allocate(determineWkbCapacity()); createSerializationProperties(); - + buf.order(ByteOrder.LITTLE_ENDIAN); buf.putInt(srid); buf.put(version); buf.put(serializationProperties); - + if (!isSinglePoint && !isSingleLineSegment) { buf.putInt(numberOfPoints); } - + for (int i = 0; i < numberOfPoints; i++) { buf.putDouble(points[2 * i]); buf.putDouble(points[2 * i + 1]); } - - if (!noZM ) { + + if (!noZM) { if (hasZvalues) { for (int i = 0; i < numberOfPoints; i++) { buf.putDouble(zValues[i]); } } - + if (hasMvalues) { for (int i = 0; i < numberOfPoints; i++) { buf.putDouble(mValues[i]); } } } - + if (isSinglePoint || isSingleLineSegment) { wkb = buf.array(); return; } - + buf.putInt(numberOfFigures); for (int i = 0; i < numberOfFigures; i++) { buf.put(figures[i].getFiguresAttribute()); buf.putInt(figures[i].getPointOffset()); } - + buf.putInt(numberOfShapes); for (int i = 0; i < numberOfShapes; i++) { buf.putInt(shapes[i].getParentOffset()); buf.putInt(shapes[i].getFigureOffset()); buf.put(shapes[i].getOpenGISType()); } - + if (version == 2 && null != segments) { buf.putInt(numberOfSegments); for (int i = 0; i < numberOfSegments; i++) { buf.put(segments[i].getSegmentType()); } } - - if (noZM) { + + if (noZM) { wkbNoZM = buf.array(); - } else { + } + else { wkb = buf.array(); } return; } - + protected void parseWkb() { srid = buffer.getInt(); version = buffer.get(); serializationProperties = buffer.get(); - + interpretSerializationPropBytes(); readNumberOfPoints(); readPoints(); - + if (hasZvalues) { readZvalues(); } - + if (hasMvalues) { readMvalues(); } - + if (!(isSinglePoint || isSingleLineSegment)) { readNumberOfFigures(); readFigures(); readNumberOfShapes(); readShapes(); } - + determineInternalType(); if (buffer.hasRemaining()) { @@ -320,7 +415,7 @@ protected void parseWkb() { } } } - + private void readPoints() { points = new double[2 * numberOfPoints]; for (int i = 0; i < numberOfPoints; i++) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 5d9e1652e..94e62341a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -73,6 +73,9 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; + +import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification; + import java.nio.Buffer; final class TDS { @@ -100,9 +103,11 @@ final class TDS { static final int TDS_DONEPROC = 0xFE; static final int TDS_DONEINPROC = 0xFF; static final int TDS_FEDAUTHINFO = 0xEE; + static final int TDS_SQLRESCOLSRCS = 0xa2; + static final int TDS_SQLDATACLASSIFICATION = 0xa3; // FedAuth - static final int TDS_FEATURE_EXT_FEDAUTH = 0x02; + static final byte TDS_FEATURE_EXT_FEDAUTH = 0x02; static final int TDS_FEDAUTH_LIBRARY_SECURITYTOKEN = 0x01; static final int TDS_FEDAUTH_LIBRARY_ADAL = 0x02; static final int TDS_FEDAUTH_LIBRARY_RESERVED = 0x7F; @@ -112,12 +117,22 @@ final class TDS { static final byte FEDAUTH_INFO_ID_SPN = 0x02; // FedAuthInfoData is the SPN to use for acquiring fed auth token // AE constants - static final int TDS_FEATURE_EXT_AE = 0x04; - static final int MAX_SUPPORTED_TCE_VERSION = 0x01; // max version + // 0x03 is for x_eFeatureExtensionId_Rcs + static final byte TDS_FEATURE_EXT_AE = 0x04; + static final byte MAX_SUPPORTED_TCE_VERSION = 0x01; // max version static final int CUSTOM_CIPHER_ALGORITHM_ID = 0; // max version + // 0x06 is for x_eFeatureExtensionId_LoginToken + // 0x07 is for x_eFeatureExtensionId_ClientSideTelemetry + // Data Classification constants + static final byte TDS_FEATURE_EXT_DATACLASSIFICATION = 0x09; + static final byte DATA_CLASSIFICATION_NOT_ENABLED = 0x00; + static final byte MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION = 0x01; + static final int AES_256_CBC = 1; static final int AEAD_AES_256_CBC_HMAC_SHA256 = 2; static final int AE_METADATA = 0x08; + + static final byte TDS_FEATURE_EXT_UTF8SUPPORT = 0x0A; static final int TDS_TVP = 0xF3; static final int TVP_ROW = 0x01; @@ -177,6 +192,10 @@ static final String getTokenName(int tdsTokenType) { return "TDS_DONEINPROC (0xFF)"; case TDS_FEDAUTHINFO: return "TDS_FEDAUTHINFO (0xEE)"; + case TDS_FEATURE_EXT_DATACLASSIFICATION: + return "TDS_FEATURE_EXT_DATACLASSIFICATION (0x09)"; + case TDS_FEATURE_EXT_UTF8SUPPORT: + return "TDS_FEATURE_EXT_UTF8SUPPORT (0x0A)"; default: return "unknown token (0x" + Integer.toHexString(tdsTokenType).toUpperCase() + ")"; } @@ -2329,58 +2348,22 @@ else if (!useTnir) { conn.terminate(SQLServerException.DRIVER_ERROR_UNSUPPORTED_CONFIG, errorStr); } + if (inetAddrs.length == 1) { + // Single address so do not start any threads + return getConnectedSocket(inetAddrs[0], portNumber, timeoutInMilliSeconds); + } + timeoutInMilliSeconds = Math.max(timeoutInMilliSeconds, minTimeoutForParallelConnections); if (Util.isIBM()) { - timeoutInMilliSeconds = Math.max(timeoutInMilliSeconds, minTimeoutForParallelConnections); if (logger.isLoggable(Level.FINER)) { logger.finer(this.toString() + "Using Java NIO with timeout:" + timeoutInMilliSeconds); } findSocketUsingJavaNIO(inetAddrs, portNumber, timeoutInMilliSeconds); } else { - LinkedList inet4Addrs = new LinkedList<>(); - LinkedList inet6Addrs = new LinkedList<>(); - - for (InetAddress inetAddr : inetAddrs) { - if (inetAddr instanceof Inet4Address) { - inet4Addrs.add((Inet4Address) inetAddr); - } - else { - assert inetAddr instanceof Inet6Address : "Unexpected IP address " + inetAddr.toString(); - inet6Addrs.add((Inet6Address) inetAddr); - } - } - - // use half timeout only if both IPv4 and IPv6 addresses are present - int timeoutForEachIPAddressType; - if ((!inet4Addrs.isEmpty()) && (!inet6Addrs.isEmpty())) { - timeoutForEachIPAddressType = Math.max(timeoutInMilliSeconds / 2, minTimeoutForParallelConnections); - } - else - timeoutForEachIPAddressType = Math.max(timeoutInMilliSeconds, minTimeoutForParallelConnections); - - if (!inet4Addrs.isEmpty()) { - if (logger.isLoggable(Level.FINER)) { - logger.finer(this.toString() + "Using Java Threading with timeout:" + timeoutForEachIPAddressType); - } - - findSocketUsingThreading(inet4Addrs, portNumber, timeoutForEachIPAddressType); - } - - if (!result.equals(Result.SUCCESS)) { - // try threading logic - if (!inet6Addrs.isEmpty()) { - // do not start any threads if there is only one ipv6 address - if (inet6Addrs.size() == 1) { - return getConnectedSocket(inet6Addrs.get(0), portNumber, timeoutForEachIPAddressType); - } - - if (logger.isLoggable(Level.FINER)) { - logger.finer(this.toString() + "Using Threading with timeout:" + timeoutForEachIPAddressType); - } - - findSocketUsingThreading(inet6Addrs, portNumber, timeoutForEachIPAddressType); - } + if (logger.isLoggable(Level.FINER)) { + logger.finer(this.toString() + "Using Threading with timeout:" + timeoutInMilliSeconds); } + findSocketUsingThreading(inetAddrs, portNumber, timeoutInMilliSeconds); } // If the thread continued execution due to timeout, the result may not be known. @@ -2633,12 +2616,12 @@ private Socket getConnectedSocket(InetSocketAddress addr, return selectedSocket; } - private void findSocketUsingThreading(LinkedList inetAddrs, + private void findSocketUsingThreading(InetAddress[] inetAddrs, int portNumber, int timeoutInMilliSeconds) throws IOException, InterruptedException { assert timeoutInMilliSeconds != 0 : "The timeout cannot be zero"; - assert inetAddrs.isEmpty() == false : "Number of inetAddresses should not be zero in this function"; + assert inetAddrs.length != 0 : "Number of inetAddresses should not be zero in this function"; LinkedList sockets = new LinkedList<>(); LinkedList socketConnectors = new LinkedList<>(); @@ -2646,7 +2629,7 @@ private void findSocketUsingThreading(LinkedList inetAddrs, try { // create a socket, inetSocketAddress and a corresponding socketConnector per inetAddress - noOfSpawnedThreads = inetAddrs.size(); + noOfSpawnedThreads = inetAddrs.length; for (InetAddress inetAddress : inetAddrs) { Socket s = new Socket(); sockets.add(s); @@ -6367,7 +6350,7 @@ final TDSCommand getCommand() { final SQLServerConnection getConnection() { return con; } - + private TDSPacket currentPacket = new TDSPacket(0); private TDSPacket lastPacket = currentPacket; private int payloadOffset = 0; @@ -6376,8 +6359,12 @@ final SQLServerConnection getConnection() { private boolean isStreaming = true; private boolean useColumnEncryption = false; private boolean serverSupportsColumnEncryption = false; + private boolean serverSupportsDataClassification = false; private final byte valueBytes[] = new byte[256]; + + protected SensitivityClassification sensitivityClassification; + private static final AtomicInteger lastReaderID = new AtomicInteger(0); private static int nextReaderID() { @@ -6404,6 +6391,7 @@ private static int nextReaderID() { useColumnEncryption = true; } serverSupportsColumnEncryption = con.getServerSupportsColumnEncryption(); + serverSupportsDataClassification = con.getServerSupportsDataClassification(); } final boolean isColumnEncryptionSettingEnabled() { @@ -6414,6 +6402,10 @@ final boolean getServerSupportsColumnEncryption() { return serverSupportsColumnEncryption; } + final boolean getServerSupportsDataClassification() { + return serverSupportsDataClassification; + } + final void throwInvalidTDS() throws SQLServerException { if (logger.isLoggable(Level.SEVERE)) logger.severe(toString() + " got unexpected value in TDS response at offset:" + payloadOffset); @@ -7105,7 +7097,7 @@ final void skip(int bytesToSkip) throws SQLServerException { } } - final void TryProcessFeatureExtAck(boolean featureExtAckReceived) throws SQLServerException { + final void tryProcessFeatureExtAck(boolean featureExtAckReceived) throws SQLServerException { // in case of redirection, do not check if TDS_FEATURE_EXTENSION_ACK is received or not. if (null != this.con.getRoutingInfo()) { return; @@ -7114,6 +7106,10 @@ final void TryProcessFeatureExtAck(boolean featureExtAckReceived) throws SQLServ if (isColumnEncryptionSettingEnabled() && !featureExtAckReceived) throw new SQLServerException(this, SQLServerException.getErrString("R_AE_NotSupportedByServer"), null, 0, false); } + + final void trySetSensitivityClassification(SensitivityClassification sensitivityClassification) { + this.sensitivityClassification = sensitivityClassification; + } } /** diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java index 9589cc239..0bf41d944 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java @@ -1,90 +1,181 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.util.Set; - -/** - * The ISQLServerBulkRecord interface can be used to create classes that read in data from any source (such as a file) and allow a SQLServerBulkCopy - * class to write the data to SQL Server tables. - */ -public interface ISQLServerBulkRecord { - /** - * Get the ordinals for each of the columns represented in this data record. - * - * @return Set of ordinals for the columns. - */ - public Set getColumnOrdinals(); - - /** - * Get the name of the given column. - * - * @param column - * Column ordinal - * @return Name of the column - */ - public String getColumnName(int column); - - /** - * Get the JDBC data type of the given column. - * - * @param column - * Column ordinal - * @return JDBC data type of the column - */ - public int getColumnType(int column); - - /** - * Get the precision for the given column. - * - * @param column - * Column ordinal - * @return Precision of the column - */ - public int getPrecision(int column); - - /** - * Get the scale for the given column. - * - * @param column - * Column ordinal - * @return Scale of the column - */ - public int getScale(int column); - - /** - * Indicates whether the column represents an identity column. - * - * @param column - * Column ordinal - * @return True if the column is an identity column; false otherwise. - */ - public boolean isAutoIncrement(int column); - - /** - * Gets the data for the current row as an array of Objects. - * - * Each Object must match the Java language Type that is used to represent the indicated JDBC data type for the given column. For more - * information, see 'Understanding the JDBC Driver Data Types' for the appropriate mappings. - * - * @return The data for the row. - * @throws SQLServerException - * If there are any errors in obtaining the data. - */ - public Object[] getRowData() throws SQLServerException; - - /** - * Advances to the next data row. - * - * @return True if rows are available; false if there are no more rows - * @throws SQLServerException - * If there are any errors in advancing to the next row. - */ - public boolean next() throws SQLServerException; -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.time.format.DateTimeFormatter; + +/** + * The ISQLServerBulkRecord interface can be used to create classes that read in data from any source (such as a file) and allow a SQLServerBulkCopy + * class to write the data to SQL Server tables. + * + * This interface is implemented by {@link SQLServerBulkCommon} Class + */ +public interface ISQLServerBulkRecord { + + /** + * Get the ordinals for each of the columns represented in this data record. + * + * @return Set of ordinals for the columns. + */ + public java.util.Set getColumnOrdinals(); + + /** + * Get the name of the given column. + * + * @param column + * Column ordinal + * @return Name of the column + */ + public String getColumnName(int column); + + /** + * Get the JDBC data type of the given column. + * + * @param column + * Column ordinal + * @return JDBC data type of the column + */ + public int getColumnType(int column); + + /** + * Get the precision for the given column. + * + * @param column + * Column ordinal + * @return Precision of the column + */ + public int getPrecision(int column); + + /** + * Get the scale for the given column. + * + * @param column + * Column ordinal + * @return Scale of the column + */ + public int getScale(int column); + + /** + * Indicates whether the column represents an identity column. + * + * @param column + * Column ordinal + * @return True if the column is an identity column; false otherwise. + */ + public boolean isAutoIncrement(int column); + + /** + * Gets the data for the current row as an array of Objects. + * + * Each Object must match the Java language Type that is used to represent the indicated JDBC data type for the given column. For more + * information, see 'Understanding the JDBC Driver Data Types' for the appropriate mappings. + * + * @return The data for the row. + * @throws SQLServerException + * If there are any errors in obtaining the data. + */ + public Object[] getRowData() throws SQLServerException; + + /** + * Advances to the next data row. + * + * @return True if rows are available; false if there are no more rows + * @throws SQLServerException + * If there are any errors in advancing to the next row. + */ + public boolean next() throws SQLServerException; + + /** + * Adds metadata for the given column in the file. + * + * @param positionInFile + * Indicates which column the metadata is for. Columns start at 1. + * @param name + * Name for the column (optional if only using column ordinal in a mapping for SQLServerBulkCopy operation) + * @param jdbcType + * JDBC data type of the column + * @param precision + * Precision for the column (ignored for the appropriate data types) + * @param scale + * Scale for the column (ignored for the appropriate data types) + * @param dateTimeFormatter + * format to parse data that is sent + * @throws SQLServerException + * when an error occurs + */ + public void addColumnMetadata(int positionInFile, + String name, + int jdbcType, + int precision, + int scale, + DateTimeFormatter dateTimeFormatter) throws SQLServerException; + + /** + * Adds metadata for the given column in the file. + * + * @param positionInFile + * Indicates which column the metadata is for. Columns start at 1. + * @param name + * Name for the column (optional if only using column ordinal in a mapping for SQLServerBulkCopy operation) + * @param jdbcType + * JDBC data type of the column + * @param precision + * Precision for the column (ignored for the appropriate data types) + * @param scale + * Scale for the column (ignored for the appropriate data types) + * @throws SQLServerException + * when an error occurs + */ + public void addColumnMetadata(int positionInFile, + String name, + int jdbcType, + int precision, + int scale) throws SQLServerException; + + /** + * Set the format for reading in dates from the file. + * + * @param dateTimeFormat + * format to parse data sent as java.sql.Types.TIMESTAMP_WITH_TIMEZONE + */ + public void setTimestampWithTimezoneFormat(String dateTimeFormat); + + /** + * Set the format for reading in dates from the file. + * + * @param dateTimeFormatter + * format to parse data sent as java.sql.Types.TIMESTAMP_WITH_TIMEZONE + */ + public void setTimestampWithTimezoneFormat(DateTimeFormatter dateTimeFormatter); + + /** + * Set the format for reading in dates from the file. + * + * @param timeFormat + * format to parse data sent as java.sql.Types.TIME_WITH_TIMEZONE + */ + public void setTimeWithTimezoneFormat(String timeFormat); + + /** + * Set the format for reading in dates from the file. + * + * @param dateTimeFormatter + * format to parse data sent as java.sql.Types.TIME_WITH_TIMEZONE + */ + public void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter); + + /** + * Retreives dateTimeFormatter for the given column + * + * @param column + * Column ordinal + * @return dateTimeFormatter + */ + public DateTimeFormatter getColumnDateTimeFormatter(int column); +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement.java index 280f66f1a..7be9957b3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement.java @@ -8,49 +8,1159 @@ package com.microsoft.sqlserver.jdbc; -import java.sql.SQLException; +import java.math.BigDecimal; +import java.sql.SQLType; +import java.sql.Timestamp; +import java.util.Calendar; /** - * - * This interface is implemented by SQLServerCallableStatement Class. - * + * This interface is implemented by {@link SQLServerCallableStatement} Class. */ public interface ISQLServerCallableStatement extends java.sql.CallableStatement, ISQLServerPreparedStatement { + + @Deprecated + public BigDecimal getBigDecimal(String parameterName, + int scale) throws SQLServerException; + /** - * Sets parameter parameterName to DateTimeOffset x + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param index + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getDateTime(int index) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. * * @param parameterName - * the name of the parameter - * @param x - * DateTimeOffset value - * @throws SQLException - * if parameterName does not correspond to a named parameter; if the driver can detect that a data conversion error could occur; if a - * database access error occurs or this method is called on a closed CallableStatement + * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the + * column + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs */ - public void setDateTimeOffset(String parameterName, - microsoft.sql.DateTimeOffset x) throws SQLException; + public Timestamp getDateTime(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does + * not store timezone information. + * + * @param index + * the first column is 1, the second is 2, ... + * @param cal + * the java.util.Calendar object to use in constructing the dateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getDateTime(int index, + Calendar cal) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does + * not store timezone information. + * + * @param name + * the name of the column + * @param cal + * the java.util.Calendar object to use in constructing the dateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getDateTime(String name, + Calendar cal) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param index + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getSmallDateTime(int index) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param parameterName + * The name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getSmallDateTime(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param index + * the first column is 1, the second is 2, ... + * @param cal + * the java.util.Calendar object to use in constructing the smalldateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getSmallDateTime(int index, + Calendar cal) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param name + * The name of a column + * @param cal + * the java.util.Calendar object to use in constructing the smalldateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Timestamp getSmallDateTime(String name, + Calendar cal) throws SQLServerException; /** * Gets the DateTimeOffset value of parameter with index parameterIndex * * @param parameterIndex * the first parameter is 1, the second is 2, and so on - * @return DateTimeOffset value - * @throws SQLException + * @return DateTimeOffset value if the value is SQL NULL, the value returned is null + * @throws SQLServerException * if parameterIndex is out of range; if a database access error occurs or this method is called on a closed * CallableStatement */ - public microsoft.sql.DateTimeOffset getDateTimeOffset(int parameterIndex) throws SQLException; + public microsoft.sql.DateTimeOffset getDateTimeOffset(int parameterIndex) throws SQLServerException; /** * Gets the DateTimeOffset value of parameter with name parameterName * * @param parameterName * the name of the parameter - * @return DateTimeOffset value - * @throws SQLException + * @return DateTimeOffset value if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public microsoft.sql.DateTimeOffset getDateTimeOffset(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. The + * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARCHAR values. + * The JDBC driver will do any necessary conversion from the database format into ASCII. + * + *

+ * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method + * implicitly closes the stream. Also, a stream may return 0 when the method InputStream.available is called whether + * there is data available or not. + * + * @param parameterIndex + * the first column is 1, the second is 2, ... + * @return a Java input stream that delivers the database column value as a stream of one-byte ASCII characters; if the value is SQL + * NULL, the value returned is null + * @throws SQLServerException + * if the columnIndex is not valid; if a database access error occurs or this method is called on a closed result set + */ + public java.io.InputStream getAsciiStream(int parameterIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. The + * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARCHAR values. + * The JDBC driver will do any necessary conversion from the database format into ASCII. + * + *

+ * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method + * implicitly closes the stream. Also, a stream may return 0 when the method available is called whether there is data + * available or not. + * + * @param parameterName + * the name of the parameter + * @return a Java input stream that delivers the database column value as a stream of one-byte ASCII characters. If the value is SQL + * NULL, the value returned is null. + * @throws SQLServerException + * if the columnLabel is not valid; if a database access error occurs or this method is called on a closed result set + */ + public java.io.InputStream getAsciiStream(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param parameterIndex + * The zero-based ordinal of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public BigDecimal getMoney(int parameterIndex) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param parameterName + * The name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null. + * @throws SQLServerException + * when an error occurs + */ + public BigDecimal getMoney(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param parameterIndex + * The zero-based ordinal of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public BigDecimal getSmallMoney(int parameterIndex) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param parameterName + * The name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null. + * @throws SQLServerException + * when an error occurs + */ + public BigDecimal getSmallMoney(String parameterName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of uninterpreted bytes. The + * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARBINARY values. + * + *

+ * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method + * implicitly closes the stream. Also, a stream may return 0 when the method InputStream.available is called whether + * there is data available or not. + * + * @param parameterIndex + * the first column is 1, the second is 2, ... + * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the value is SQL NULL, + * the value returned is null + * @throws SQLServerException + * if the columnIndex is not valid; if a database access error occurs or this method is called on a closed result set + */ + public java.io.InputStream getBinaryStream(int parameterIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of uninterpreted + * bytes. The value can then be read in chunks from the stream. This method is particularly suitable for retrieving large + * LONGVARBINARY values. + * + *

+ * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method + * implicitly closes the stream. Also, a stream may return 0 when the method available is called whether there is data + * available or not. + * + * @param parameterName + * the name of the parameter + * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the value is SQL NULL, + * the result is null + * @throws SQLServerException + * if the columnLabel is not valid; if a database access error occurs or this method is called on a closed result set + */ + public java.io.InputStream getBinaryStream(String parameterName) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param calendar + * a java.util.Calendar + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTimestamp + */ + public void setTimestamp(String parameterName, + java.sql.Timestamp value, + Calendar calendar, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value, using the given Calendar object. The driver uses the + * Calendar object to construct an SQL TIME value, which the driver then sends to the database. With a a + * Calendar object, the driver can calculate the time taking into account a custom timezone. If no Calendar object is + * specified, the driver uses the default timezone, which is that of the virtual machine running the application. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param calendar + * the Calendar object the driver will use to construct the time + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTime + */ + public void setTime(String parameterName, + java.sql.Time value, + Calendar calendar, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Date value, using the given Calendar object. The driver uses the + * Calendar object to construct an SQL DATE value, which the driver then sends to the database. With a a + * Calendar object, the driver can calculate the date taking into account a custom timezone. If no Calendar object is + * specified, the driver uses the default timezone, which is that of the virtual machine running the application. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param calendar + * the Calendar object the driver will use to construct the date + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getDate + */ + public void setDate(String parameterName, + java.sql.Date value, + Calendar calendar, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given String object. The driver converts this to a SQL NCHAR or + * NVARCHAR or LONGNVARCHAR + * + * @param parameterName + * the name of the parameter to be set + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if the driver does not support national character sets; if the driver + * can detect that a data conversion error could occur; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setNString(String parameterName, + String value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the value of the designated parameter with the given object. + * + *

+ * The given Java object will be converted to the given targetSqlType before being sent to the database. + * + * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method + * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing + * Ref, Blob, Clob, NClob, Struct, java.net.URL, or + * Array, the driver should pass it to the database as a value of the corresponding SQL type. + *

+ * Note that this method may be used to pass database- specific abstract data types. + * + * @param parameterName + * the name of the parameter + * @param value + * the object containing the input parameter value + * @param sqlType + * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. + * @param decimals + * for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types, this is the number of digits after the decimal point. For all other + * types, this value will be ignored. + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see java.sql.Types + * @see #getObject + */ + public void setObject(String parameterName, + Object value, + int sqlType, + int decimals, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the value of the designated parameter with the given object. + * + *

+ * The given Java object will be converted to the given targetSqlType before being sent to the database. + * + * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method + * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing + * Ref, Blob, Clob, NClob, Struct, java.net.URL, or + * Array, the driver should pass it to the database as a value of the corresponding SQL type. + *

+ * Note that this method may be used to pass datatabase- specific abstract data types. + * + * @param parameterName + * the name of the parameter + * @param value + * the object containing the input parameter value + * @param targetSqlType + * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. + * @param precision + * the precision of the column. + * @param scale + * the scale of the column. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see java.sql.Types + * @see #getObject + */ + public void setObject(String parameterName, + Object value, + int targetSqlType, + Integer precision, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param scale + * the scale of the parameter + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTimestamp + */ + public void setTimestamp(String parameterName, + java.sql.Timestamp value, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param scale + * the scale of the parameter + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTimestamp + */ + public void setTimestamp(String parameterName, + java.sql.Timestamp value, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets parameter parameterName to DateTimeOffset x + * + * @param parameterName + * the name of the parameter + * @param value + * DateTimeOffset value + * @throws SQLServerException + * if an error occurs + */ + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value) throws SQLServerException; + + /** + * Sets parameter parameterName to DateTimeOffset x + * + * @param parameterName + * the name of the parameter + * @param value + * DateTimeOffset value + * @param scale + * the scale of the parameter + * @throws SQLServerException + * if an error occurs + */ + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value, + int scale) throws SQLServerException; + + /** + * Sets parameter parameterName to DateTimeOffset x + * + * @param parameterName + * the name of the parameter + * @param value + * DateTimeOffset value + * @param scale + * the scale of the parameter + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if an error occurs + */ + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param scale + * the scale of the column + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTime + */ + public void setTime(String parameterName, + java.sql.Time value, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + * @see #getTime + */ + public void setTime(String parameterName, + java.sql.Time value, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL DATETIME + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setDateTime(String parameterName, + java.sql.Timestamp value) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL DATETIME + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setDateTime(String parameterName, + java.sql.Timestamp value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL SMALLDATETIME + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setSmallDateTime(String parameterName, + java.sql.Timestamp value) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL SMALLDATETIME + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setSmallDateTime(String parameterName, + java.sql.Timestamp value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given String value. The driver converts this to an SQL uniqueIdentifier value + * when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param guid + * the parameter value + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setUniqueIdentifier(String parameterName, + String guid) throws SQLServerException; + + /** + * Sets the designated parameter to the given String value. The driver converts this to an SQL uniqueIdentifier value + * when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param guid + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setUniqueIdentifier(String parameterName, + String guid, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java array of bytes. The driver converts this to an SQL VARBINARY or + * LONGVARBINARY (depending on the argument's size relative to the driver's limits on VARBINARY values) when it sends it + * to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setBytes(String parameterName, + byte[] value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java byte value. The driver converts this to an SQL TINYINT value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setByte(String parameterName, + byte value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or + * LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends + * it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setString(String parameterName, + String value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL Money + * value. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setMoney(String parameterName, + BigDecimal value) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL Money + * value. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setMoney(String parameterName, + BigDecimal value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL + * smallMoney value. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setSmallMoney(String parameterName, + BigDecimal value) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL + * smallMoney value. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setSmallMoney(String parameterName, + BigDecimal value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setBigDecimal(String parameterName, + BigDecimal value, + int precision, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setBigDecimal(String parameterName, + BigDecimal value, + int precision, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java double value. The driver converts this to an SQL DOUBLE value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setDouble(String parameterName, + double value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java float value. The driver converts this to an SQL FLOAT value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setFloat(String parameterName, + float value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java int value. The driver converts this to an SQL INTEGER value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setInt(String parameterName, + int value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java long value. The driver converts this to an SQL BIGINT value when it + * sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setLong(String parameterName, + long value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java short value. The driver converts this to an SQL SMALLINT value when + * it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setShort(String parameterName, + short value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java boolean value. The driver converts this to an SQL BIT or + * BOOLEAN value when it sends it to the database. + * + * @param parameterName + * the name of the parameter + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed + * CallableStatement + */ + public void setBoolean(String parameterName, + boolean value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Populates a table valued parameter passed to a stored procedure with a data table. + * + * @param parameterName + * the name of the parameter + * @param tvpName + * the name of the type TVP + * @param tvpDataTable + * the data table object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(String parameterName, + String tvpName, + SQLServerDataTable tvpDataTable) throws SQLServerException; + + /** + * Populates a table valued parameter passed to a stored procedure with a ResultSet retrieved from another table + * + * @param parameterName + * the name of the parameter + * @param tvpName + * the name of the type TVP + * @param tvpResultSet + * the source result set object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(String parameterName, + String tvpName, + java.sql.ResultSet tvpResultSet) throws SQLServerException; + + /** + * Populates a table valued parameter passed to a stored procedure with an ISQLServerDataRecord object. + * + * @param parameterName + * the name of the parameter + * @param tvpName + * the name of the type TVP + * @param tvpDataRecord + * ISQLServerDataRecord is used for streaming data and the user decides how to use it. tvpDataRecord is an ISQLServerDataRecord + * object.the source result set object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(String parameterName, + String tvpName, + ISQLServerDataRecord tvpDataRecord) throws SQLServerException; + + /** + * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure + * is executed. + *

+ * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that + * parameter. + * + * @param parameterName + * the name of the parameter + * @param sqlType + * the JDBC type code defined by SQLType to use to register the OUT Parameter. + * @param precision + * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. + * @param scale + * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. + * @throws SQLServerException + * If any errors occur. + */ + public void registerOutParameter(String parameterName, + SQLType sqlType, + int precision, + int scale) throws SQLServerException; + + /** + * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure + * is executed. + *

+ * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that + * parameter. + * + * @param parameterIndex + * the first column is 1, the second is 2, ... + * @param sqlType + * the JDBC type code defined by SQLType to use to register the OUT Parameter. + * @param precision + * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. + * @param scale + * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. + * @throws SQLServerException + * If any errors occur. + */ + public void registerOutParameter(int parameterIndex, + SQLType sqlType, + int precision, + int scale) throws SQLServerException; + + /** + * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure + * is executed. + *

+ * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that + * parameter. + * + * @param parameterIndex + * the first column is 1, the second is 2, ... + * @param sqlType + * the JDBC type code defined by SQLType to use to register the OUT Parameter. + * @param precision + * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. + * @param scale + * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. + * @throws SQLServerException + * If any errors occur. + */ + public void registerOutParameter(int parameterIndex, + int sqlType, + int precision, + int scale) throws SQLServerException; + + /** + * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure + * is executed. + *

+ * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that + * parameter. + * + * @param parameterName + * the name of the parameter + * @param sqlType + * the JDBC type code defined by SQLType to use to register the OUT Parameter. + * @param precision + * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. + * @param scale + * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. + * @throws SQLServerException + * If any errors occur. + */ + public void registerOutParameter(String parameterName, + int sqlType, + int precision, + int scale) throws SQLServerException; + + /** + * Sets the value of the designated parameter with the given object. + * + *

+ * The given Java object will be converted to the given targetSqlType before being sent to the database. + * + * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method + * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing + * Ref, Blob, Clob, NClob, Struct, java.net.URL, or + * Array, the driver should pass it to the database as a value of the corresponding SQL type. + *

+ * Note that this method may be used to pass datatabase- specific abstract data types. + * + * @param parameterName + * the name of the parameter + * @param value + * the object containing the input parameter value + * @param jdbcType + * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. + * @param scale + * the scale of the column. + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed * CallableStatement + * @see java.sql.Types + * @see #getObject */ - public microsoft.sql.DateTimeOffset getDateTimeOffset(String parameterName) throws SQLException; + public void setObject(String parameterName, + Object value, + SQLType jdbcType, + int scale, + boolean forceEncrypt) throws SQLServerException; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement42.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement42.java deleted file mode 100644 index 4684ec4ac..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerCallableStatement42.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * This interface requires all the CallableStatement methods including those are specific to JDBC 4.2 - * - */ -public interface ISQLServerCallableStatement42 extends ISQLServerCallableStatement, ISQLServerPreparedStatement42 { - - public void registerOutParameter(int index, - SQLType sqlType) throws SQLServerException; - - public void registerOutParameter(int index, - SQLType sqlType, - String typeName) throws SQLServerException; - - public void registerOutParameter(int index, - SQLType sqlType, - int scale) throws SQLServerException; - - /** - * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure - * is executed. - *

- * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that - * parameter. - * - * @param index - * the first parameter is 1, the second is 2,... - * @param sqlType - * the JDBC type code defined by SQLType to use to register the OUT Parameter. - * @param precision - * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. - * @param scale - * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. - * @throws SQLServerException - * If any errors occur. - */ - public void registerOutParameter(int index, - SQLType sqlType, - int precision, - int scale) throws SQLServerException; - - public void setObject(String sCol, - Object obj, - SQLType jdbcType) throws SQLServerException; - - public void setObject(String sCol, - Object obj, - SQLType jdbcType, - int scale) throws SQLServerException; - - /** - * Sets the value of the designated parameter with the given object. - * - * @param sCol - * the name of the parameter - * @param obj - * the object containing the input parameter value - * @param jdbcType - * the SQL type to be sent to the database - * @param scale - * scale the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. - * @param forceEncrypt - * true if force encryption is on, false if force encryption is off - * @throws SQLServerException - * If any errors occur. - */ - public void setObject(String sCol, - Object obj, - SQLType jdbcType, - int scale, - boolean forceEncrypt) throws SQLServerException; - - public void registerOutParameter(String parameterName, - SQLType sqlType, - String typeName) throws SQLServerException; - - public void registerOutParameter(String parameterName, - SQLType sqlType, - int scale) throws SQLServerException; - - /** - * Registers the parameter in ordinal position index to be of JDBC type sqlType. All OUT parameters must be registered before a stored procedure - * is executed. - *

- * The JDBC type specified by sqlType for an OUT parameter determines the Java type that must be used in the get method to read the value of that - * parameter. - * - * @param parameterName - * the name of the parameter - * @param sqlType - * the JDBC type code defined by SQLType to use to register the OUT Parameter. - * @param precision - * the sum of the desired number of digits to the left and right of the decimal point. It must be greater than or equal to zero. - * @param scale - * the desired number of digits to the right of the decimal point. It must be greater than or equal to zero. - * @throws SQLServerException - * If any errors occur. - */ - public void registerOutParameter(String parameterName, - SQLType sqlType, - int precision, - int scale) throws SQLServerException; - - public void registerOutParameter(String parameterName, - SQLType sqlType) throws SQLServerException; -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection.java index 57ea5e94a..7ebf9dcfc 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection.java @@ -1,32 +1,344 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLException; -import java.util.UUID; - -/** - * - * This interface is implemented by SQLServerConnection Class. - */ -public interface ISQLServerConnection extends java.sql.Connection { - // Transaction types. - // TRANSACTION_SNAPSHOT corresponds to -> SET TRANSACTION ISOLATION LEVEL SNAPSHOT - public final static int TRANSACTION_SNAPSHOT = 0x1000; - - /** - * Gets the connection ID of the most recent connection attempt, regardless of whether the attempt succeeded or failed. - * - * @return 16-byte GUID representing the connection ID of the most recent connection attempt. Or, NULL if there is a failure after the connection - * request is initiated and the pre-login handshake. - * @throws SQLException - * If any errors occur. - */ - public UUID getClientConnectionId() throws SQLException; -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.Statement; +import java.util.UUID; + +/** + * This interface is implemented by {@link SQLServerConnection} and {@link SQLServerConnectionPoolProxy} Classes. + */ +public interface ISQLServerConnection extends java.sql.Connection { + + // Transaction types. + // TRANSACTION_SNAPSHOT corresponds to -> SET TRANSACTION ISOLATION LEVEL SNAPSHOT + public final static int TRANSACTION_SNAPSHOT = 0x1000; + + /** + * Gets the connection ID of the most recent connection attempt, regardless of whether the attempt succeeded or failed. + * + * @return 16-byte GUID representing the connection ID of the most recent connection attempt. Or, NULL if there is a failure after the connection + * request is initiated and the pre-login handshake. + * @throws SQLServerException + * If any errors occur. + */ + public UUID getClientConnectionId() throws SQLServerException; + + /** + * Creates a Statement object that will generate ResultSet objects with the given type, concurrency, and holdability. + * This method is the same as the createStatement method above, but it allows the default result set type, concurrency, and + * holdability to be overridden. + * + * @param nType + * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, + * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE + * @param nConcur + * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or + * ResultSet.CONCUR_UPDATABLE + * @param nHold + * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or + * ResultSet.CLOSE_CURSORS_AT_COMMIT + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new Statement object that will generate ResultSet objects with the given type, concurrency, and holdability + * @throws SQLServerException + * if a database access error occurs, this method is called on a closed connection or the given parameters are not + * ResultSet constants indicating type, concurrency, and holdability + */ + public Statement createStatement(int nType, + int nConcur, + int nHold, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys. The given constant tells the + * driver whether it should make auto-generated keys available for retrieval. This parameter is ignored if the SQL statement is not an + * INSERT statement, or an SQL statement able to return auto-generated keys (the list of such statements is vendor-specific). + *

+ * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports + * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not + * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is + * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. + *

+ * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a + * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling + * {@link #getHoldability}. + * + * @param sql + * an SQL statement that may contain one or more '?' IN parameter placeholders + * @param flag + * a flag indicating whether auto-generated keys should be returned; one of Statement.RETURN_GENERATED_KEYS or + * Statement.NO_GENERATED_KEYS + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will have the capability of returning + * auto-generated keys + * @throws SQLServerException + * if a database access error occurs, this method is called on a closed connection or the given parameter is not a + * Statement constant indicating whether auto-generated keys should be returned + */ + public PreparedStatement prepareStatement(String sql, + int flag, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array + * contains the indexes of the columns in the target table that contain the auto-generated keys that should be made available. The driver will + * ignore the array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list + * of such statements is vendor-specific). + *

+ * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then + * be used to efficiently execute this statement multiple times. + *

+ * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports + * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not + * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is + * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. + *

+ * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a + * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling + * {@link #getHoldability}. + * + * @param sql + * an SQL statement that may contain one or more '?' IN parameter placeholders + * @param columnIndexes + * an array of column indexes indicating the columns that should be returned from the inserted row or rows + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated + * keys designated by the given array of column indexes + * @throws SQLServerException + * if a database access error occurs or this method is called on a closed connection + */ + public PreparedStatement prepareStatement(String sql, + int[] columnIndexes, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array + * contains the names of the columns in the target table that contain the auto-generated keys that should be returned. The driver will ignore the + * array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list of such + * statements is vendor-specific). + *

+ * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then + * be used to efficiently execute this statement multiple times. + *

+ * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports + * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not + * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is + * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. + *

+ * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a + * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling + * {@link #getHoldability}. + * + * @param sql + * an SQL statement that may contain one or more '?' IN parameter placeholders + * @param columnNames + * an array of column names indicating the columns that should be returned from the inserted row or rows + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated + * keys designated by the given array of column names + * @throws SQLServerException + * if a database access error occurs or this method is called on a closed connection + */ + public PreparedStatement prepareStatement(String sql, + String[] columnNames, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Creates a PreparedStatement object that will generate ResultSet objects with the given type, concurrency, and + * holdability. + *

+ * This method is the same as the prepareStatement method above, but it allows the default result set type, concurrency, and + * holdability to be overridden. + * + * @param sql + * a String object that is the SQL statement to be sent to the database; may contain one or more '?' IN parameters + * @param nType + * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, + * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE + * @param nConcur + * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or + * ResultSet.CONCUR_UPDATABLE + * @param resultSetHoldability + * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or + * ResultSet.CLOSE_CURSORS_AT_COMMIT + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will generate ResultSet + * objects with the given type, concurrency, and holdability + * @throws SQLServerException + * if a database access error occurs, this method is called on a closed connection or the given parameters are not + * ResultSet constants indicating type, concurrency, and holdability + */ + public PreparedStatement prepareStatement(java.lang.String sql, + int nType, + int nConcur, + int resultSetHoldability, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. This + * method is the same as the prepareCall method above, but it allows the default result set type, result set concurrency type and + * holdability to be overridden. + * + * @param sql + * a String object that is the SQL statement to be sent to the database; may contain on or more '?' parameters + * @param nType + * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, + * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE + * @param nConcur + * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or + * ResultSet.CONCUR_UPDATABLE + * @param nHold + * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or + * ResultSet.CLOSE_CURSORS_AT_COMMIT + * @param stmtColEncSetting + * Specifies how data will be sent and received when reading and writing encrypted columns. + * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will generate ResultSet + * objects with the given type, concurrency, and holdability + * @throws SQLServerException + * if a database access error occurs, this method is called on a closed connection or the given parameters are not + * ResultSet constants indicating type, concurrency, and holdability + */ + public CallableStatement prepareCall(String sql, + int nType, + int nConcur, + int nHold, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException; + + /** + * Modifies the setting of the sendTimeAsDatetime connection property. When true, java.sql.Time values will be sent to the server as SQL + * Serverdatetime values. When false, java.sql.Time values will be sent to the server as SQL Servertime values. sendTimeAsDatetime can also be + * modified programmatically with SQLServerDataSource.setSendTimeAsDatetime. The default value for this property may change in a future release. + * + * @param sendTimeAsDateTimeValue + * enables/disables setting the sendTimeAsDatetime connection property. For more information about how the Microsoft JDBC Driver for + * SQL Server configures java.sql.Time values before sending them to the server, see + * Configuring How java.sql.Time Values are Sent to the + * Server. + * + * @throws SQLServerException + * if a database access error occurs + */ + public void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) throws SQLServerException; + + /** + * Checks the sendTimeAsDatetime property. + * + * @return boolean value of sendTimeAsDatetime + * + * @throws SQLServerException + * if a database access error occurs + */ + public boolean getSendTimeAsDatetime() throws SQLServerException; + + /** + * Returns the number of currently outstanding prepared statement un-prepare actions. + * + * @return Returns the current value per the description. + */ + public int getDiscardedServerPreparedStatementCount(); + + /** + * Forces the un-prepare requests for any outstanding discarded prepared statements to be executed. + */ + public void closeUnreferencedPreparedStatementHandles(); + + /** + * Returns the behavior for a specific connection instance. If false the first execution will call sp_executesql and not prepare a statement, once + * the second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following executions will call + * sp_execute. This relieves the need for sp_unprepare on prepared statement close if the statement is only executed once. The default for this + * option can be changed by calling setDefaultEnablePrepareOnFirstPreparedStatementCall(). + * + * @return Returns the current setting per the description. + */ + public boolean getEnablePrepareOnFirstPreparedStatementCall(); + + /** + * Specifies the behavior for a specific connection instance. If value is false the first execution will call sp_executesql and not prepare a + * statement, once the second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following executions will + * call sp_execute. This relieves the need for sp_unprepare on prepared statement close if the statement is only executed once. + * + * @param value + * Changes the setting per the description. + */ + public void setEnablePrepareOnFirstPreparedStatementCall(boolean value); + + /** + * Returns the behavior for a specific connection instance. This setting controls how many outstanding prepared statement discard actions + * (sp_unprepare) can be outstanding per connection before a call to clean-up the outstanding handles on the server is executed. If the setting is + * {@literal <=} 1, unprepare actions will be executed immedietely on prepared statement close. If it is set to {@literal >} 1, these calls will + * be batched together to avoid overhead of calling sp_unprepare too often. The default for this option can be changed by calling + * getDefaultServerPreparedStatementDiscardThreshold(). + * + * @return Returns the current setting per the description. + */ + public int getServerPreparedStatementDiscardThreshold(); + + /** + * Specifies the behavior for a specific connection instance. This setting controls how many outstanding prepared statement discard actions + * (sp_unprepare) can be outstanding per connection before a call to clean-up the outstanding handles on the server is executed. If the setting is + * {@literal <=} 1 unprepare actions will be executed immedietely on prepared statement close. If it is set to {@literal >} 1 these calls will be + * batched together to avoid overhead of calling sp_unprepare too often. + * + * @param value + * Changes the setting per the description. + */ + public void setServerPreparedStatementDiscardThreshold(int value); + + /** + * Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache. + * + * @param value + * The new cache size. + * + */ + public void setStatementPoolingCacheSize(int value); + + /** + * Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache. + * + * @return Returns the current setting per the description. + */ + public int getStatementPoolingCacheSize(); + + /** + * Whether statement pooling is enabled or not for this connection. + * + * @return Returns the current setting per the description. + */ + public boolean isStatementPoolingEnabled(); + + /** + * Returns the current number of pooled prepared statement handles. + * + * @return Returns the current setting per the description. + */ + public int getStatementHandleCacheEntryCount(); + + /** + * Disable/enable statement pooling. + * + * @param value + * true to disable statement pooling, false to enable it. + */ + public void setDisableStatementPooling(boolean value); + + /** + * Determine whether statement pooling is disabled. + * + * @return true if statement pooling is disabled, false if it is enabled. + */ + public boolean getDisableStatementPooling(); +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection43.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection43.java index 1689cde87..c7dca8ee1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection43.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection43.java @@ -1,19 +1,59 @@ -package com.microsoft.sqlserver.jdbc; - -import java.sql.ShardingKey; - -public interface ISQLServerConnection43 extends ISQLServerConnection { - - public void setShardingKey(ShardingKey shardingKey) throws SQLServerException; - - public void setShardingKey(ShardingKey shardingKey, - ShardingKey superShardingKey) throws SQLServerException; - - public boolean setShardingKeyIfValid(ShardingKey shardingKey, - int timeout) throws SQLServerException; - - public boolean setShardingKeyIfValid(ShardingKey shardingKey, - ShardingKey superShardingKey, - int timeout) throws SQLServerException; - -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.sql.SQLException; + +/** + * This interface is implemented by {@link SQLServerConnection43} class. + */ +public interface ISQLServerConnection43 extends ISQLServerConnection { + + /** + * Hints to the driver that a request, an independent unit of work, is beginning on this connection. It backs up the values of the connection + * properties that are modifiable through public methods. Each request is independent of all other requests with regard to state local to the + * connection either on the client or the server. Work done between {@code beginRequest}, {@code endRequest} pairs does not depend on any other + * work done on the connection either as part of another request or outside of any request. A request may include multiple transactions. There may + * be dependencies on committed database state as that is not local to the connection. {@code beginRequest} marks the beginning of the work unit. + *

+ * Local state is defined as any state associated with a Connection that is local to the current Connection either in the client or the database + * that is not transparently reproducible. + *

+ * Calls to {@code beginRequest} and {@code endRequest} are not nested. Multiple calls to {@code beginRequest} without an intervening call to + * {@code endRequest} is not an error. The first {@code beginRequest} call marks the start of the request and subsequent calls are treated as a + * no-op It is recommended to enclose each unit of work in {@code beginRequest}, {@code endRequest} pairs such that there is no open transaction + * at the beginning or end of the request and no dependency on local state that crosses request boundaries. Committed database state is not local. + * + * This method is to be used by Connection pooling managers. + *

+ * The pooling manager should call {@code beginRequest} on the underlying connection prior to returning a connection to the caller. + *

+ * + * @throws SQLException + * if an error occurs + * @see #endRequest() + */ + @Override + public void beginRequest() throws SQLException; + + /** + * Hints to the driver that a request, an independent unit of work, has completed. It rolls back the open transactions. Resets the connection + * properties that are modifiable through public methods back to their original values. Calls to {@code beginRequest} and {@code endRequest} are + * not nested. Multiple calls to {@code endRequest} without an intervening call to {@code beginRequest} is not an error. The first + * {@code endRequest} call marks the request completed and subsequent calls are treated as a no-op. If {@code endRequest} is called without an + * initial call to {@code beginRequest} is a no-op. This method is to be used by Connection pooling managers. + *

+ * + * @throws SQLException + * if an error occurs + * @see #beginRequest() + */ + @Override + public void endRequest() throws SQLException; +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataRecord.java index 79e109b7c..a4ee9f7cd 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataRecord.java @@ -1,49 +1,51 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -/** - * The ISQLServerDataRecord interface can be used to create classes that read in data from any source (such as a file) and allow a structured type to - * be sent to SQL Server tables. - */ - -public interface ISQLServerDataRecord { - /** - * Get the column meta data - * - * @param column - * the first column is 1, the second is 2, and so on - * @return SQLServerMetaData of column - */ - public SQLServerMetaData getColumnMetaData(int column); - - /** - * Get the column count. - * - * @return Set of ordinals for the columns. - */ - public int getColumnCount(); - - /** - * Gets the data for the current row as an array of Objects. - * - * Each Object must match the Java language Type that is used to represent the indicated JDBC data type for the given column. For more - * information, see 'Understanding the JDBC Driver Data Types' for the appropriate mappings. - * - * @return The data for the row. - */ - public Object[] getRowData(); - - /** - * Advances to the next data row. - * - * @return True if rows are available; false if there are no more rows - */ - public boolean next(); -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +/** + * This interface can be used to create classes that read in data from any + * source (such as a file) and allow a structured type to be sent to SQL Server + * tables. + */ +public interface ISQLServerDataRecord { + /** + * Get the column meta data + * + * @param column + * the first column is 1, the second is 2, and so on + * @return SQLServerMetaData of column + */ + public SQLServerMetaData getColumnMetaData(int column); + + /** + * Get the column count. + * + * @return Set of ordinals for the columns. + */ + public int getColumnCount(); + + /** + * Gets the data for the current row as an array of Objects. + * + * Each Object must match the Java language Type that is used to represent + * the indicated JDBC data type for the given column. For more information, + * see 'Understanding the JDBC Driver Data Types' for the appropriate + * mappings. + * + * @return The data for the row. + */ + public Object[] getRowData(); + + /** + * Advances to the next data row. + * + * @return True if rows are available; false if there are no more rows + */ + public boolean next(); +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java index 492559244..08168cac1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java @@ -8,12 +8,15 @@ package com.microsoft.sqlserver.jdbc; -import javax.sql.CommonDataSource; +import org.ietf.jgss.GSSCredential; /** * A factory to create connections to the data source represented by this object. This interface was added in SQL Server JDBC Driver 3.0. + * + * This interface is implemented by {@link SQLServerDataSource} Class. */ -public interface ISQLServerDataSource extends CommonDataSource { +public interface ISQLServerDataSource extends javax.sql.CommonDataSource { + /** * Sets the application intent. * @@ -112,11 +115,36 @@ public interface ISQLServerDataSource extends CommonDataSource { */ public boolean getEncrypt(); + /** + * Beginning in version 6.0 of the Microsoft JDBC Driver for SQL Server, a new connection property transparentNetworkIPResolution (TNIR) is added + * for transparent connection to Always On availability groups or to a server which has multiple IP addresses associated. When + * transparentNetworkIPResolution is true, the driver attempts to connect to the first IP address available. If the first attempt fails, the + * driver tries to connect to all IP addresses in parallel until the timeout expires, discarding any pending connection attempts when one of them + * succeeds. + *

+ * transparentNetworkIPResolution is ignored if multiSubnetFailover is true + *

+ * transparentNetworkIPResolution is ignored if database mirroring is used + *

+ * transparentNetworkIPResolution is ignored if there are more than 64 IP addresses + * + * @param tnir + * if set to true, the driver attempts to connect to the first IP address available. It is true by default. + */ + public void setTransparentNetworkIPResolution(boolean tnir); + + /** + * Retrieves the TransparentNetworkIPResolution value. + * + * @return if enabled, returns true. Otherwise, false. + */ + public boolean getTransparentNetworkIPResolution(); + /** * Sets a Boolean value that indicates if the trustServerCertificate property is enabled. * * @param e - * true if the server Secure Sockets Layer (SSL) certificate should be automatically trusted when the communication layer is encrypted + * true, if the server Secure Sockets Layer (SSL) certificate should be automatically trusted when the communication layer is encrypted * using SSL. Otherwise, false. */ public void setTrustServerCertificate(boolean e); @@ -128,36 +156,51 @@ public interface ISQLServerDataSource extends CommonDataSource { */ public boolean getTrustServerCertificate(); + /** + * This parameter defines the keystore type for the trustStore. + * + * @param trustStoreType + * A String that contains the trust store type + */ + public void setTrustStoreType(String trustStoreType); + + /** + * Returns the keyStore Type for the trustStore + * + * @return trustStoreType A String that contains the trust store type + */ + public String getTrustStoreType(); + /** * Sets the path (including file name) to the certificate trustStore file. * - * @param st + * @param trustStore * A String that contains the path (including file name) to the certificate trustStore file. */ - public void setTrustStore(String st); + public void setTrustStore(String trustStore); /** * Returns the path (including file name) to the certificate trustStore file. * - * @return A String that contains the path (including file name) to the certificate trustStore file, or null if no value is set. + * @return trustStore A String that contains the path (including file name) to the certificate trustStore file, or null if no value is set. */ public String getTrustStore(); /** * Sets the password that is used to check the integrity of the trustStore data. * - * @param p + * @param trustStorePassword * A String that contains the password that is used to check the integrity of the trustStore data. */ - public void setTrustStorePassword(String p); + public void setTrustStorePassword(String trustStorePassword); /** * Sets the host name to be used in validating the SQL Server Secure Sockets Layer (SSL) certificate. * - * @param host + * @param hostName * A String that contains the host name. */ - public void setHostNameInCertificate(String host); + public void setHostNameInCertificate(String hostName); /** * Returns the host name used in validating the SQL Server Secure Sockets Layer (SSL) certificate. @@ -222,11 +265,11 @@ public interface ISQLServerDataSource extends CommonDataSource { /** * Sets the response buffering mode for connections created by using this SQLServerDataSource object. * - * @param respo + * @param bufferingMode * A String that contains the buffering and streaming mode. The valid mode can be one of the following case-insensitive Strings: full * or adaptive. */ - public void setResponseBuffering(String respo); + public void setResponseBuffering(String bufferingMode); /** * Returns the response buffering mode for this SQLServerDataSource object. @@ -267,6 +310,21 @@ public interface ISQLServerDataSource extends CommonDataSource { */ public boolean getSendStringParametersAsUnicode(); + /** + * Translates the serverName from Unicode to ASCII Compatible Encoding (ACE) + * + * @param serverNameAsACE + * if enabled the servername will be translated to ASCII Compatible Encoding (ACE) + */ + public void setServerNameAsACE(boolean serverNameAsACE); + + /** + * Retrieves if the serverName should be translated from Unicode to ASCII Compatible Encoding (ACE) + * + * @return if enabled, will return true. Otherwise, false. + */ + public boolean getServerNameAsACE(); + /** * Sets the name of the computer that is running SQL Server. * @@ -410,6 +468,21 @@ public interface ISQLServerDataSource extends CommonDataSource { */ public void setAuthenticationScheme(String authenticationScheme); + /** + * sets the authentication mode + * + * @param authentication + * the authentication mode + */ + public void setAuthentication(String authentication); + + /** + * Retrieves the authentication mode + * + * @return the authentication value + */ + public String getAuthentication(); + /** * Sets the server spn * @@ -424,4 +497,297 @@ public interface ISQLServerDataSource extends CommonDataSource { * @return A String that contains the server spn */ public String getServerSpn(); + + /** + * sets GSSCredential + * + * @param userCredential + * the credential + */ + public void setGSSCredentials(GSSCredential userCredential); + + /** + * Retrieves the GSSCredential + * + * @return GSSCredential + */ + public GSSCredential getGSSCredentials(); + + /** + * Sets the access token. + * + * @param accessToken + * to be set in the string property. + */ + public void setAccessToken(String accessToken); + + /** + * Retrieves the access token. + * + * @return the access token. + */ + public String getAccessToken(); + + /** + * Enables/disables Always Encrypted functionality for the data source object. The default is Disabled. + * + * @param columnEncryptionSetting + * Enables/disables Always Encrypted functionality for the data source object. The default is Disabled. + */ + public void setColumnEncryptionSetting(String columnEncryptionSetting); + + /** + * Retrieves the Always Encrypted functionality setting for the data source object. + * + * @return the Always Encrypted functionality setting for the data source object. + */ + public String getColumnEncryptionSetting(); + + /** + * Sets the name that identifies a key store. Only value supported is the "JavaKeyStorePassword" for identifying the Java Key Store. The default + * is null. + * + * @param keyStoreAuthentication + * the name that identifies a key store. + */ + public void setKeyStoreAuthentication(String keyStoreAuthentication); + + /** + * Gets the value of the keyStoreAuthentication setting for the data source object. + * + * @return the value of the keyStoreAuthentication setting for the data source object. + */ + public String getKeyStoreAuthentication(); + + /** + * Sets the password for the Java keystore. Note that, for Java Key Store provider the password for the keystore and the key must be the same. + * Note that, keyStoreAuthentication must be set with "JavaKeyStorePassword". + * + * @param keyStoreSecret + * the password to use for the keystore as well as for the key + */ + public void setKeyStoreSecret(String keyStoreSecret); + + /** + * Sets the location including the file name for the Java keystore. Note that, keyStoreAuthentication must be set with "JavaKeyStorePassword". + * + * @param keyStoreLocation + * the location including the file name for the Java keystore. + */ + public void setKeyStoreLocation(String keyStoreLocation); + + /** + * Retrieves the keyStoreLocation for the Java Key Store. + * + * @return the keyStoreLocation for the Java Key Store. + */ + public String getKeyStoreLocation(); + + /** + * Setting the query timeout + * + * @param queryTimeout + * The number of seconds to wait before a timeout has occurred on a query. The default value is 0, which means infinite timeout. + */ + public void setQueryTimeout(int queryTimeout); + + /** + * Getting the query timeout + * + * @return The number of seconds to wait before a timeout has occurred on a query. + */ + public int getQueryTimeout(); + + /** + * Setting the cancel timeout + * + * @param cancelQueryTimeout + * The number of seconds to wait before we wait for the query timeout to happen. + */ + public void setCancelQueryTimeout(int cancelQueryTimeout); + + /** + * Getting the cancel timeout + * + * @return the number of seconds to wait before we wait for the query timeout to happen. + */ + public int getCancelQueryTimeout(); + + /** + * If this configuration is false the first execution of a prepared statement will call sp_executesql and not prepare a statement, once the second + * execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following executions will call sp_execute. This + * relieves the need for sp_unprepare on prepared statement close if the statement is only executed once. + * + * @param enablePrepareOnFirstPreparedStatementCall + * Changes the setting per the description. + */ + public void setEnablePrepareOnFirstPreparedStatementCall(boolean enablePrepareOnFirstPreparedStatementCall); + + /** + * If this configuration returns false the first execution of a prepared statement will call sp_executesql and not prepare a statement, once the + * second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following executions will call sp_execute. + * This relieves the need for sp_unprepare on prepared statement close if the statement is only executed once. + * + * @return Returns the current setting per the description. + */ + public boolean getEnablePrepareOnFirstPreparedStatementCall(); + + /** + * This setting controls how many outstanding prepared statement discard actions (sp_unprepare) can be outstanding per connection before a call to + * clean-up the outstanding handles on the server is executed. If the setting is {@literal <=} 1 unprepare actions will be executed immedietely on + * prepared statement close. If it is set to {@literal >} 1 these calls will be batched together to avoid overhead of calling sp_unprepare too + * often. + * + * @param serverPreparedStatementDiscardThreshold + * Changes the setting per the description. + */ + public void setServerPreparedStatementDiscardThreshold(int serverPreparedStatementDiscardThreshold); + + /** + * This setting controls how many outstanding prepared statement discard actions (sp_unprepare) can be outstanding per connection before a call to + * clean-up the outstanding handles on the server is executed. If the setting is {@literal <=} 1 unprepare actions will be executed immedietely on + * prepared statement close. If it is set to {@literal >} 1 these calls will be batched together to avoid overhead of calling sp_unprepare too + * often. + * + * @return Returns the current setting per the description. + */ + public int getServerPreparedStatementDiscardThreshold(); + + /** + * Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache. + * + * @param statementPoolingCacheSize + * Changes the setting per the description. + */ + public void setStatementPoolingCacheSize(int statementPoolingCacheSize); + + /** + * Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache. + * + * @return Returns the current setting per the description. + */ + public int getStatementPoolingCacheSize(); + + /** + * Disable/enable statement pooling. + * + * @param disableStatementPooling + * true to disable statement pooling, false to enable it. + */ + public void setDisableStatementPooling(boolean disableStatementPooling); + + /** + * Determine whether statement pooling is disabled. + * + * @return true if statement pooling is disabled, false if it is enabled. + */ + public boolean getDisableStatementPooling(); + + /** + * Setting the socket timeout + * + * @param socketTimeout + * The number of milliseconds to wait before a timeout is occurred on a socket read or accept. The default value is 0, which means + * infinite timeout. + */ + public void setSocketTimeout(int socketTimeout); + + /** + * Getting the socket timeout + * + * @return The number of milliseconds to wait before a timeout is occurred on a socket read or accept. + */ + public int getSocketTimeout(); + + /** + * Sets the login configuration file for Kerberos authentication. This overrides the default configuration SQLJDBCDriver + * + * @param configurationName + * the configuration name + */ + public void setJASSConfigurationName(String configurationName); + + /** + * Retrieves the login configuration file for Kerberos authentication. + * + * @return login configuration file name + */ + public String getJASSConfigurationName(); + + /** + * Enables Fips Mode on the connection For FIPS enabled JVM this property should be true. + * + * @param fips + * Boolean property to enable/disable fips + */ + public void setFIPS(boolean fips); + + /** + * Retrieves value of connection property "fips" For FIPS enabled JVM this property should be true. + * + * @return fips boolean value + */ + public boolean getFIPS(); + + /** + * Sets the sslProtocol property for connection Set this value to specify TLS protocol keyword. + * + * Acceptable values are: TLS, TLSv1, TLSv1.1, and TLSv1.2. + * + * @param sslProtocol + * Value for SSL Protocol to be set. + */ + public void setSSLProtocol(String sslProtocol); + + /** + * Retrieves value of connection property 'sslProtocol' + * + * @return sslProtocol property value + */ + public String getSSLProtocol(); + + /** + * Sets the connection property 'trustManagerClass' on the connection + * + * @param trustManagerClass + * The fully qualified class name of a custom javax.net.ssl.TrustManager. + */ + public void setTrustManagerClass(String trustManagerClass); + + /** + * Retrieves value for the connection property 'trustManagerClass' + * + * @return trustManagerClass property value + */ + public String getTrustManagerClass(); + + /** + * Sets Constructor Arguments to be provided on constructor of 'trustManagerClass' + * + * @param trustManagerConstructorArg + * 'trustManagerClass' constructor arguments + */ + public void setTrustManagerConstructorArg(String trustManagerConstructorArg); + + /** + * Retrieves value for the connection property 'trustManagerConstructorArg' + * + * @return trustManagerConstructorArg property value + */ + public String getTrustManagerConstructorArg(); + + /** + * Getting the use Bulk Copy API for Batch Insert + * + * @return whether the driver should use Bulk Copy API for Batch Insert operations. + */ + public boolean getUseBulkCopyForBatchInsert(); + + /** + * Setting the use Bulk Copy API for Batch Insert + * + * @param useBulkCopyForBatchInsert + * indicates whether Bulk Copy API should be used for Batch Insert operations. + */ + public void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement.java index ee954f151..17fc6b558 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement.java @@ -8,8 +8,14 @@ package com.microsoft.sqlserver.jdbc; -import java.sql.SQLException; +import java.math.BigDecimal; +import java.sql.ParameterMetaData; +import java.sql.ResultSet; +import java.sql.SQLType; +/** + * This interface is implemented by {@link SQLServerPreparedStatement} class. + */ public interface ISQLServerPreparedStatement extends java.sql.PreparedStatement, ISQLServerStatement { /** * Sets the designated parameter to the given microsoft.sql.DateTimeOffset value. @@ -18,10 +24,819 @@ public interface ISQLServerPreparedStatement extends java.sql.PreparedStatement, * the first parameter is 1, the second is 2, ... * @param x * the parameter value - * @throws SQLException + * @throws SQLServerException * if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method * is called on a closed PreparedStatement */ public void setDateTimeOffset(int parameterIndex, - microsoft.sql.DateTimeOffset x) throws SQLException; + microsoft.sql.DateTimeOffset x) throws SQLServerException; + + /** + * Sets the value of the designated parameter with the given object. + * + * This method is similar to {@link #setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength)}, except that it assumes a + * scale of zero. + *

+ * The default implementation will throw {@code SQLFeatureNotSupportedException} + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the object containing the input parameter value + * @param targetSqlType + * the SQL type to be sent to the database + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method + * is called on a closed {@code PreparedStatement} + */ + public void setObject(int parameterIndex, + Object x, + SQLType targetSqlType, + Integer precision, + Integer scale) throws SQLServerException; + + /** + * Sets the value of the designated parameter with the given object. + * + * This method is similar to {@link #setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength)}, except that it assumes a + * scale of zero. + *

+ * The default implementation will throw {@code SQLFeatureNotSupportedException} + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the object containing the input parameter value + * @param targetSqlType + * the SQL type to be sent to the database + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method + * is called on a closed {@code PreparedStatement} + */ + public void setObject(int parameterIndex, + Object x, + SQLType targetSqlType, + Integer precision, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * The server handle for this prepared statement. If a value {@literal <} 1 is returned no handle has been created. + * + * @return Per the description. + * @throws SQLServerException + * when an error occurs + */ + public int getPreparedStatementHandle() throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void setBigDecimal(int parameterIndex, + BigDecimal x, + int precision, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setBigDecimal(int parameterIndex, + BigDecimal x, + int precision, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setMoney(int parameterIndex, + BigDecimal x) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setMoney(int parameterIndex, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setSmallMoney(int parameterIndex, + BigDecimal x) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setSmallMoney(int parameterIndex, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java boolean value. The driver converts this to an SQL BIT or + * BOOLEAN value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setBoolean(int parameterIndex, + boolean x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java byte value. The driver converts this to an SQL TINYINT value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setByte(int parameterIndex, + byte x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java array of bytes. The driver converts this to an SQL VARBINARY or + * LONGVARBINARY (depending on the argument's size relative to the driver's limits on VARBINARY values) when it sends it + * to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setBytes(int parameterIndex, + byte x[], + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given String. The driver converts this to an SQL GUID + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param guid + * string representation of the uniqueIdentifier value + * @throws SQLServerException + * when an error occurs + */ + public void setUniqueIdentifier(int parameterIndex, + String guid) throws SQLServerException; + + /** + * Sets the designated parameter to the given String. The driver converts this to an SQL GUID + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param guid + * string representation of the uniqueIdentifier value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setUniqueIdentifier(int parameterIndex, + String guid, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java double value. The driver converts this to an SQL DOUBLE value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setDouble(int parameterIndex, + double x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java float value. The driver converts this to an SQL REAL value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setFloat(int parameterIndex, + float x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given microsoft.sql.Geometry Class object. The driver converts this to an SQL + * REAL value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setGeometry(int parameterIndex, + Geometry x) throws SQLServerException; + + /** + * Sets the designated parameter to the given microsoft.sql.Geography Class object. The driver converts this to an SQL + * REAL value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setGeography(int parameterIndex, + Geography x) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java int value. The driver converts this to an SQL INTEGER value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setInt(int parameterIndex, + int value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java long value. The driver converts this to an SQL BIGINT value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setLong(int parameterIndex, + long x, + boolean forceEncrypt) throws SQLServerException; + + /** + *

+ * Sets the value of the designated parameter with the given object. + * + *

+ * The given Java object will be converted to the given targetSqlType before being sent to the database. + * + * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method + * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing + * Ref, Blob, Clob, NClob, Struct, java.net.URL, or + * Array, the driver should pass it to the database as a value of the corresponding SQL type. + * + *

+ * Note that this method may be used to pass database-specific abstract data types. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the object containing the input parameter value + * @param targetSqlType + * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. + * @param precision + * the precision of the column + * @param scale + * scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void setObject(int parameterIndex, + Object x, + int targetSqlType, + Integer precision, + int scale) throws SQLServerException; + + /** + *

+ * Sets the value of the designated parameter with the given object. + * + *

+ * The given Java object will be converted to the given targetSqlType before being sent to the database. + * + * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method + * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing + * Ref, Blob, Clob, NClob, Struct, java.net.URL, or + * Array, the driver should pass it to the database as a value of the corresponding SQL type. + * + *

+ * Note that this method may be used to pass database-specific abstract data types. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the object containing the input parameter value + * @param targetSqlType + * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. + * @param precision + * the precision of the column + * @param scale + * scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setObject(int parameterIndex, + Object x, + int targetSqlType, + Integer precision, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java short value. The driver converts this to an SQL SMALLINT value when + * it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setShort(int parameterIndex, + short x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or + * LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends + * it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param str + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setString(int parameterIndex, + String str, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given String object. The driver converts this to a SQL NCHAR or + * NVARCHAR or LONGNVARCHAR value (depending on the argument's size relative to the driver's limits on + * NVARCHAR values) when it sends it to the database. + * + * @param parameterIndex + * of the first parameter is 1, the second is 2, ... + * @param value + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setNString(int parameterIndex, + String value, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void setTime(int parameterIndex, + java.sql.Time x, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setTime(int parameterIndex, + java.sql.Time x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void setTimestamp(int parameterIndex, + java.sql.Timestamp x, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setTimestamp(int parameterIndex, + java.sql.Timestamp x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given microsoft.sql.DatetimeOffset value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void setDateTimeOffset(int parameterIndex, + microsoft.sql.DateTimeOffset x, + int scale) throws SQLServerException; + + /** + * Sets the designated parameter to the given microsoft.sql.DatetimeOffset value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setDateTimeOffset(int parameterIndex, + microsoft.sql.DateTimeOffset x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setDateTime(int parameterIndex, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setDateTime(int parameterIndex, + java.sql.Timestamp x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @throws SQLServerException + * when an error occurs + */ + public void setSmallDateTime(int parameterIndex, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setSmallDateTime(int parameterIndex, + java.sql.Timestamp x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Populates a table valued parameter with a data table + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param tvpName + * the name of the table valued parameter + * @param tvpDataTable + * the source datatable object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(int parameterIndex, + String tvpName, + SQLServerDataTable tvpDataTable) throws SQLServerException; + + /** + * Populates a table valued parameter with a data table + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param tvpName + * the name of the table valued parameter + * @param tvpResultSet + * the source resultset object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(int parameterIndex, + String tvpName, + ResultSet tvpResultSet) throws SQLServerException; + + /** + * Populates a table valued parameter with a data table + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param tvpName + * the name of the table valued parameter + * @param tvpBulkRecord + * an ISQLServerDataRecord object + * @throws SQLServerException + * when an error occurs + */ + public void setStructured(int parameterIndex, + String tvpName, + ISQLServerDataRecord tvpBulkRecord) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Date value, using the given Calendar object. The driver uses the + * Calendar object to construct an SQL DATE value, which the driver then sends to the database. With a + * Calendar object, the driver can calculate the date taking into account a custom timezone. If no Calendar object is + * specified, the driver uses the default timezone, which is that of the virtual machine running the application. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param cal + * the Calendar object the driver will use to construct the date + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setDate(int parameterIndex, + java.sql.Date x, + java.util.Calendar cal, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it + * sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param cal + * the Calendar object the driver will use to construct the date + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setTime(int parameterIndex, + java.sql.Time x, + java.util.Calendar cal, + boolean forceEncrypt) throws SQLServerException; + + /** + * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP + * value when it sends it to the database. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param x + * the parameter value + * @param cal + * the Calendar object the driver will use to construct the date + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void setTimestamp(int parameterIndex, + java.sql.Timestamp x, + java.util.Calendar cal, + boolean forceEncrypt) throws SQLServerException; + + /** + * Returns parameter metadata for the prepared statement. + * + * @param forceRefresh: + * If true the cache will not be used to retrieve the metadata. + * + * @return Per the description. + * + * @throws SQLServerException + * when an error occurs + */ + public ParameterMetaData getParameterMetaData(boolean forceRefresh) throws SQLServerException; + } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement42.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement42.java deleted file mode 100644 index 229af83ee..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerPreparedStatement42.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * This interface requires all the PreparedStatement methods including those are specific to JDBC 4.2 - * - */ -public interface ISQLServerPreparedStatement42 extends ISQLServerPreparedStatement { - - public void setObject(int index, - Object obj, - SQLType jdbcType) throws SQLServerException; - - public void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - int scaleOrLength) throws SQLServerException; - - /** - * Sets the value of the designated parameter with the given object. - * - * This method is similar to {@link #setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength)}, except that it assumes a - * scale of zero. - *

- * The default implementation will throw {@code SQLFeatureNotSupportedException} - * - * @param parameterIndex - * the first parameter is 1, the second is 2, ... - * @param x - * the object containing the input parameter value - * @param targetSqlType - * the SQL type to be sent to the database - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method - * is called on a closed {@code PreparedStatement} - */ - public void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale) throws SQLServerException; - - /** - * Sets the value of the designated parameter with the given object. - * - * This method is similar to {@link #setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength)}, except that it assumes a - * scale of zero. - *

- * The default implementation will throw {@code SQLFeatureNotSupportedException} - * - * @param parameterIndex - * the first parameter is 1, the second is 2, ... - * @param x - * the object containing the input parameter value - * @param targetSqlType - * the SQL type to be sent to the database - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method - * is called on a closed {@code PreparedStatement} - */ - public void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale, - boolean forceEncrypt) throws SQLServerException; -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet.java index d0bab83cf..e9fa6ccb6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet.java @@ -8,8 +8,15 @@ package com.microsoft.sqlserver.jdbc; -import java.sql.SQLException; +import java.math.BigDecimal; +import java.sql.SQLType; +import java.util.Calendar; +import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification; + +/** + * This interface is implemented by {@link SQLServerResultSet} class. + */ public interface ISQLServerResultSet extends java.sql.ResultSet { public static final int TYPE_SS_DIRECT_FORWARD_ONLY = 2003; // TYPE_FORWARD_ONLY + 1000 @@ -23,16 +30,195 @@ public interface ISQLServerResultSet extends java.sql.ResultSet { public static final int CONCUR_SS_SCROLL_LOCKS = 1009; // CONCUR_UPDATABLE + 1 public static final int CONCUR_SS_OPTIMISTIC_CCVAL = 1010; // CONCUR_UPDATABLE + 2 + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a com.microsoft.sqlserver.jdbc.Geometry object in + * the Java programming language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Geometry getGeometry(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a com.microsoft.sqlserver.jdbc.Geometry object in + * the Java programming language. + * + * @param columnName + * the name of the column + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Geometry getGeometry(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a com.microsoft.sqlserver.jdbc.Geography object in + * the Java programming language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Geography getGeography(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a com.microsoft.sqlserver.jdbc.Geography object in + * the Java programming language. + * + * @param columnName + * the name of the column + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public Geography getGeography(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a String object in the Java programming language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public String getUniqueIdentifier(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a String object in the Java programming language. + * + * @param columnLabel + * the name of the column + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public String getUniqueIdentifier(String columnLabel) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public java.sql.Timestamp getDateTime(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param columnName + * is the name of the column + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getDateTime(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does + * not store timezone information. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param cal + * the java.util.Calendar object to use in constructing the dateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getDateTime(int columnIndex, + Calendar cal) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does + * not store timezone information. + * + * @param colName + * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the + * column + * @param cal + * the java.util.Calendar object to use in constructing the dateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getDateTime(String colName, + Calendar cal) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * when an error occurs + */ + public java.sql.Timestamp getSmallDateTime(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param columnName + * is the name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getSmallDateTime(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming + * language. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param cal + * the java.util.Calendar object to use in constructing the smalldateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getSmallDateTime(int columnIndex, + Calendar cal) throws SQLServerException; + + /** + * + * @param colName + * The name of a column + * @param cal + * the java.util.Calendar object to use in constructing the smalldateTime + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public java.sql.Timestamp getSmallDateTime(String colName, + Calendar cal) throws SQLServerException; + /** * Retrieves the value of the designated column as a microsoft.sql.DateTimeOffset object, given a zero-based column ordinal. * * @param columnIndex * The zero-based ordinal of a column. * @return A DateTimeOffset Class object. - * @throws SQLException + * @throws SQLServerException * when an error occurs */ - public microsoft.sql.DateTimeOffset getDateTimeOffset(int columnIndex) throws SQLException; + public microsoft.sql.DateTimeOffset getDateTimeOffset(int columnIndex) throws SQLServerException; /** * Retrieves the value of the column specified as a microsoft.sql.DateTimeOffset object, given a column name. @@ -40,10 +226,54 @@ public interface ISQLServerResultSet extends java.sql.ResultSet { * @param columnName * The name of a column. * @return A DateTimeOffset Class object. - * @throws SQLException + * @throws SQLServerException + * when an error occurs + */ + public microsoft.sql.DateTimeOffset getDateTimeOffset(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param columnIndex + * The zero-based ordinal of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException * when an error occurs */ - public microsoft.sql.DateTimeOffset getDateTimeOffset(String columnName) throws SQLException; + public BigDecimal getMoney(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param columnName + * is the name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null. + * @throws SQLServerException + * If any errors occur. + */ + public BigDecimal getMoney(String columnName) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param columnIndex + * The zero-based ordinal of a column. + * @return the column value; if the value is SQL NULL, the value returned is null + * @throws SQLServerException + * If any errors occur. + */ + public BigDecimal getSmallMoney(int columnIndex) throws SQLServerException; + + /** + * Retrieves the value of the column specified as a java.math.BigDecimal object. + * + * @param columnName + * is the name of a column. + * @return the column value; if the value is SQL NULL, the value returned is null. + * @throws SQLServerException + * If any errors occur. + */ + public BigDecimal getSmallMoney(String columnName) throws SQLServerException; /** * Updates the value of the column specified to the DateTimeOffset Class value, given a zero-based column ordinal. @@ -52,11 +282,11 @@ public interface ISQLServerResultSet extends java.sql.ResultSet { * The zero-based ordinal of a column. * @param x * A DateTimeOffset Class object. - * @throws SQLException + * @throws SQLServerException * when an error occurs */ public void updateDateTimeOffset(int index, - microsoft.sql.DateTimeOffset x) throws SQLException; + microsoft.sql.DateTimeOffset x) throws SQLServerException; /** * Updates the value of the column specified to the DateTimeOffset Class value, given a column name. @@ -65,10 +295,1408 @@ public void updateDateTimeOffset(int index, * The name of a column. * @param x * A DateTimeOffset Class object. - * @throws SQLException + * @throws SQLServerException * when an error occurs */ public void updateDateTimeOffset(String columnName, - microsoft.sql.DateTimeOffset x) throws SQLException; + microsoft.sql.DateTimeOffset x) throws SQLServerException; + + /** + * Updates the designated column with an {@code Object} value. + * + * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying + * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateObject(int index, + Object x, + int precision, + int scale) throws SQLServerException; + + /** + * Updates the designated column with an Object value. The updater methods are used to update column values in the current row or the insert row. + * The updater methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the database. If the + * second argument is an InputStream then the stream must contain the number of bytes specified by scaleOrLength. If the second argument is a + * Reader then the reader must contain the number of characters specified by scaleOrLength. If these conditions are not true the driver will + * generate a SQLServerException when the statement is executed. The default implementation will throw SQLFeatureNotSupportedException + * + * @param index + * the first column is 1, the second is 2, ... + * @param obj + * the new column value + * @param targetSqlType + * the SQL type to be sent to the database + * @param scale + * for an object of java.math.BigDecimal , this is the number of digits after the decimal point. For Java Object types InputStream and + * Reader, this is the length of the data in the stream or reader. For all other types, this value will be ignored. + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement.If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateObject(int index, + Object obj, + SQLType targetSqlType, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * + * Updates the designated column with an Object value. The updater methods are used to update column values in the current row or the insert row. + * The updater methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the database. If the + * second argument is an InputStream then the stream must contain the number of bytes specified by scaleOrLength. If the second argument is a + * Reader then the reader must contain the number of characters specified by scaleOrLength. If these conditions are not true the driver will + * generate a SQLServerException when the statement is executed. The default implementation will throw SQLFeatureNotSupportedException + * + * @param columnName + * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the + * column + * @param obj + * the new column value + * @param targetSqlType + * the SQL type to be sent to the database + * @param scale + * for an object of java.math.BigDecimal , this is the number of digits after the decimal point. For Java Object types InputStream and + * Reader, this is the length of the data in the stream or reader. For all other types, this value will be ignored. + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement.If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateObject(String columnName, + Object obj, + SQLType targetSqlType, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a boolean value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateBoolean(int index, + boolean x, + boolean forceEncrypt) throws SQLServerException; + /** + * Updates the designated column with a byte value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateByte(int index, + byte x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a short value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateShort(int index, + short x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with an int value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateInt(int index, + int x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a long value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateLong(int index, + long x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a float value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateFloat(int index, + float x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a double value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateDouble(int index, + double x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @throws SQLServerException + * when an error occurs + */ + public void updateMoney(int index, + BigDecimal x) throws SQLServerException; + + /** + * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateMoney(int index, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * the column name + * @param x + * the new column value + * @throws SQLServerException + * If any errors occur. + */ + public void updateMoney(String columnName, + BigDecimal x) throws SQLServerException; + + /** + * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * the column name + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateMoney(String columnName, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or + * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods + * are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @throws SQLServerException + * when an error occurs + */ + public void updateSmallMoney(int index, + BigDecimal x) throws SQLServerException; + + /** + * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or + * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods + * are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateSmallMoney(int index, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or + * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods + * are called to update the database. + * + * @param columnName + * the column name + * @param x + * the new column value + * @throws SQLServerException + * If any errors occur. + */ + public void updateSmallMoney(String columnName, + BigDecimal x) throws SQLServerException; + + /** + * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or + * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods + * are called to update the database. + * + * @param columnName + * the column name + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateSmallMoney(String columnName, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.math.BigDecimal value. The updater methods are used to update column values in the + * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or + * insertRow methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateBigDecimal(int index, + BigDecimal x, + Integer precision, + Integer scale) throws SQLServerException; + + /** + * Updates the designated column with a java.math.BigDecimal value. The updater methods are used to update column values in the + * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or + * insertRow methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateBigDecimal(int index, + BigDecimal x, + Integer precision, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param stringValue + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateString(int columnIndex, + String stringValue, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a String value. It is intended for use when updating NCHAR,NVARCHAR + * and LONGNVARCHAR columns. The updater methods are used to update column values in the current row or the insert row. The updater + * methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the + * database. + * + * @param columnIndex + * the first column is 1, the second 2, ... + * @param nString + * the value for the column to be updated + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateNString(int columnIndex, + String nString, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a String value. It is intended for use when updating NCHAR,NVARCHAR + * and LONGNVARCHAR columns. The updater methods are used to update column values in the current row or the insert row. The updater + * methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the + * database. + * + * @param columnLabel + * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the + * column + * @param nString + * the value for the column to be updated + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateNString(String columnLabel, + String nString, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a byte array value. The updater methods are used to update column values in the current row or + * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods + * are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateBytes(int index, + byte x[], + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Date value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateDate(int index, + java.sql.Date x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateTime(int index, + java.sql.Time x, + Integer scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateTime(int index, + java.sql.Time x, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateTimestamp(int index, + java.sql.Timestamp x, + int scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateTimestamp(int index, + java.sql.Timestamp x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @throws SQLServerException + * when an error occurs + */ + public void updateDateTime(int index, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateDateTime(int index, + java.sql.Timestamp x, + Integer scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateDateTime(int index, + java.sql.Timestamp x, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @throws SQLServerException + * when an error occurs + */ + public void updateSmallDateTime(int index, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateSmallDateTime(int index, + java.sql.Timestamp x, + Integer scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateSmallDateTime(int index, + java.sql.Timestamp x, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the value of the column specified to the DateTimeOffset Class value, given a zero-based column ordinal. + * + * @param index + * The zero-based ordinal of a column. + * @param x + * A DateTimeOffset Class object. + * @param scale + * scale of the column + * @throws SQLServerException + * when an error occurs + */ + public void updateDateTimeOffset(int index, + microsoft.sql.DateTimeOffset x, + Integer scale) throws SQLServerException; + + /** + * Updates the value of the column specified to the DateTimeOffset Class value, given a zero-based column ordinal. + * + * @param index + * The zero-based ordinal of a column. + * @param x + * A DateTimeOffset Class object. + * @param scale + * scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateDateTimeOffset(int index, + microsoft.sql.DateTimeOffset x, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * The zero-based ordinal of a column. + * @param x + * the new column value + * @throws SQLServerException + * when an error occurs + */ + public void updateUniqueIdentifier(int index, + String x) throws SQLServerException; + + /** + * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param index + * The zero-based ordinal of a column. + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateUniqueIdentifier(int index, + String x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with an {@code Object} value. + * + * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying + * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. + * + * @param index + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateObject(int index, + Object x, + int precision, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a boolean value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * when an error occurs + */ + public void updateBoolean(String columnName, + boolean x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a byte value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateByte(String columnName, + byte x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a short value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateShort(String columnName, + short x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with an int value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateInt(String columnName, + int x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a long value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateLong(String columnName, + long x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a float value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateFloat(String columnName, + float x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a double value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateDouble(String columnName, + double x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the + * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or + * insertRow methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateBigDecimal(String columnName, + BigDecimal x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the + * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or + * insertRow methods are called to update the database. + * + * @param columnName + * is the name of the column and Always Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set + * to false, the driver will not force encryption on parameters. + * @param x + * BigDecimal value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateBigDecimal(String columnName, + BigDecimal x, + Integer precision, + Integer scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the + * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or + * insertRow methods are called to update the database. + * + * @param columnName + * is the name of the column and Always Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set + * to false, the driver will not force encryption on parameters. + * @param x + * BigDecimal value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateBigDecimal(String columnName, + BigDecimal x, + Integer precision, + Integer scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateString(String columnName, + String x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a byte array value. + * + * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying + * database; instead the updateRow or insertRow methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateBytes(String columnName, + byte x[], + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Date value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateDate(String columnName, + java.sql.Date x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateTime(String columnName, + java.sql.Time x, + int scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row + * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateTime(String columnName, + java.sql.Time x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateTimestamp(String columnName, + java.sql.Timestamp x, + int scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateTimestamp(String columnName, + java.sql.Timestamp x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @throws SQLServerException + * If any errors occur. + */ + public void updateDateTime(String columnName, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateDateTime(String columnName, + java.sql.Timestamp x, + int scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateDateTime(String columnName, + java.sql.Timestamp x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @throws SQLServerException + * If any errors occur. + */ + public void updateSmallDateTime(String columnName, + java.sql.Timestamp x) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateSmallDateTime(String columnName, + java.sql.Timestamp x, + int scale) throws SQLServerException; + + /** + * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current + * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow + * methods are called to update the database. + * + * @param columnName + * is the name of the column + * @param x + * the new column value + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateSmallDateTime(String columnName, + java.sql.Timestamp x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the value of the column specified to the DateTimeOffset Class value, given a column name. + * + * @param columnName + * The name of a column. + * @param x + * A DateTimeOffset Class object. + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateDateTimeOffset(String columnName, + microsoft.sql.DateTimeOffset x, + int scale) throws SQLServerException; + + /** + * Updates the value of the column specified to the DateTimeOffset Class value, given a column name. + * + * @param columnName + * The name of a column. + * @param x + * A DateTimeOffset Class object. + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateDateTimeOffset(String columnName, + microsoft.sql.DateTimeOffset x, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with a Stringvalue. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * The name of a column. + * @param x + * the new column value + * @throws SQLServerException + * If any errors occur. + */ + public void updateUniqueIdentifier(String columnName, + String x) throws SQLServerException; + + /** + * Updates the designated column with a Stringvalue. The updater methods are used to update column values in the current row or the + * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are + * called to update the database. + * + * @param columnName + * The name of a column. + * @param x + * the new column value + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateUniqueIdentifier(String columnName, + String x, + boolean forceEncrypt) throws SQLServerException; + + /** + * Updates the designated column with an {@code Object} value. + * + * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying + * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. + * + * @param columnName + * The name of a column. + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @throws SQLServerException + * If any errors occur. + */ + public void updateObject(String columnName, + Object x, + int precision, + int scale) throws SQLServerException; + + /** + * Updates the designated column with an {@code Object} value. + * + * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying + * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. + * + * @param columnName + * The name of a column. + * @param x + * the new column value + * @param precision + * the precision of the column + * @param scale + * the scale of the column + * @param forceEncrypt + * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always + * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force + * encryption on parameters. + * @throws SQLServerException + * If any errors occur. + */ + public void updateObject(String columnName, + Object x, + int precision, + int scale, + boolean forceEncrypt) throws SQLServerException; + + /** + * Exposes Data Classification information for the current ResultSet For SQL Servers that do not support Data Classification or results that do + * not fetch any classified columns, this data can be null + * + * @return SensitivityClassification + */ + public SensitivityClassification getSensitivityClassification(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet42.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet42.java deleted file mode 100644 index 1f75ec99f..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSet42.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * This interface requires all the ResultSet methods including those are specific to JDBC 4.2 - * - */ -public interface ISQLServerResultSet42 extends ISQLServerResultSet { - - public void updateObject(int index, - Object obj, - SQLType targetSqlType) throws SQLServerException; - - public void updateObject(int index, - Object obj, - SQLType targetSqlType, - int scale) throws SQLServerException; - - /** - * Updates the designated column with an Object value. The updater methods are used to update column values in the current row or the insert row. - * The updater methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the database. If the - * second argument is an InputStream then the stream must contain the number of bytes specified by scaleOrLength. If the second argument is a - * Reader then the reader must contain the number of characters specified by scaleOrLength. If these conditions are not true the driver will - * generate a SQLException when the statement is executed. The default implementation will throw SQLFeatureNotSupportedException - * - * @param index - * the first column is 1, the second is 2, ... - * @param obj - * the new column value - * @param targetSqlType - * the SQL type to be sent to the database - * @param scale - * for an object of java.math.BigDecimal , this is the number of digits after the decimal point. For Java Object types InputStream and - * Reader, this is the length of the data in the stream or reader. For all other types, this value will be ignored. - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement.If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ - public void updateObject(int index, - Object obj, - SQLType targetSqlType, - int scale, - boolean forceEncrypt) throws SQLServerException; - - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType, - int scale) throws SQLServerException; - - /** - * - * Updates the designated column with an Object value. The updater methods are used to update column values in the current row or the insert row. - * The updater methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the database. If the - * second argument is an InputStream then the stream must contain the number of bytes specified by scaleOrLength. If the second argument is a - * Reader then the reader must contain the number of characters specified by scaleOrLength. If these conditions are not true the driver will - * generate a SQLException when the statement is executed. The default implementation will throw SQLFeatureNotSupportedException - * - * @param columnName - * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the - * column - * @param obj - * the new column value - * @param targetSqlType - * the SQL type to be sent to the database - * @param scale - * for an object of java.math.BigDecimal , this is the number of digits after the decimal point. For Java Object types InputStream and - * Reader, this is the length of the data in the stream or reader. For all other types, this value will be ignored. - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement.If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType, - int scale, - boolean forceEncrypt) throws SQLServerException; - - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType) throws SQLServerException; -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java new file mode 100644 index 000000000..25f88d733 --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java @@ -0,0 +1,29 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.sql.ResultSetMetaData; + +/** + * This interface is implemented by {@link SQLServerResultSetMetaData} class. + */ +public interface ISQLServerResultSetMetaData extends ResultSetMetaData { + + /** + * Returns true if the column is a SQLServer SparseColumnSet + * + * @param column + * The column number + * @return true if a column in a result set is a sparse column set, otherwise false. + * @throws SQLServerException + * when an error occurs + */ + public boolean isSparseColumnSet(int column) throws SQLServerException; + +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java new file mode 100644 index 000000000..4fd4dbb1a --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java @@ -0,0 +1,39 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.sql.Savepoint; + +/** + * This interface is implemented by {@link SQLServerSavepoint} class. + */ +public interface ISQLServerSavepoint extends Savepoint { + + /** + * Get the savepoint name + * + * @return the name of savepoint + */ + public String getSavepointName() throws SQLServerException; + + /** + * Get the savepoint label + * + * @return the label for Savepoint + */ + public String getLabel(); + + /** + * Checks if the savepoint label is null + * + * @return true is the savepoint is named. Otherwise, false. + */ + public boolean isNamed(); + +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java index 518a74cb2..a1ba642a7 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java @@ -1,39 +1,62 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -public interface ISQLServerStatement extends java.sql.Statement { - /** - * Sets the response buffering mode for this SQLServerStatement object to case-insensitive String full or adaptive. - *

- * Response buffering controls the driver's buffering of responses from SQL Server. - *

- * Possible values are: - *

- * "full" - Fully buffer the response at execution time. - *

- * "adaptive" - Data Pipe adaptive buffering - * - * @param value - * A String that contains the response buffering mode. The valid mode can be one of the following case-insensitive Strings: full or - * adaptive. - * @throws SQLServerException - * If there are any errors in setting the response buffering mode. - */ - public void setResponseBuffering(String value) throws SQLServerException; - - /** - * Retrieves the response buffering mode for this SQLServerStatement object. - * - * @return A String that contains a lower-case full or adaptive. - * @throws SQLServerException - * If there are any errors in retrieving the response buffering mode. - */ - public String getResponseBuffering() throws SQLServerException; -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +/** + * This interface is implemented by {@link SQLServerStatement} class. + */ +public interface ISQLServerStatement extends java.sql.Statement { + /** + * Sets the response buffering mode for this SQLServerStatement object to case-insensitive String full or adaptive. + *

+ * Response buffering controls the driver's buffering of responses from SQL Server. + *

+ * Possible values are: + *

+ * "full" - Fully buffer the response at execution time. + *

+ * "adaptive" - Data Pipe adaptive buffering + * + * @param value + * A String that contains the response buffering mode. The valid mode can be one of the following case-insensitive Strings: full or + * adaptive. + * @throws SQLServerException + * If there are any errors in setting the response buffering mode. + */ + public void setResponseBuffering(String value) throws SQLServerException; + + /** + * Retrieves the response buffering mode for this SQLServerStatement object. + * + * @return A String that contains a lower-case full or adaptive. + * @throws SQLServerException + * If there are any errors in retrieving the response buffering mode. + */ + public String getResponseBuffering() throws SQLServerException; + + /** + * Retrieves the cancelQueryTimeout property set on this SQLServerStatement object. + * + * @return cancelQueryTimeout Time duration in seconds. + * @throws SQLServerException + * if any error occurs + */ + public int getCancelQueryTimeout() throws SQLServerException; + + /** + * Sets the cancelQueryTimeout property on this SQLServerStatement object to cancel queryTimeout set on Connection or + * Statement level. + * + * @param seconds + * Time duration in seconds. + * @throws SQLServerException + * if any error occurs + */ + public void setCancelQueryTimeout(int seconds) throws SQLServerException; +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/InternalSpatialDatatype.java b/src/main/java/com/microsoft/sqlserver/jdbc/InternalSpatialDatatype.java index a4fc6edfb..003e30f5d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/InternalSpatialDatatype.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/InternalSpatialDatatype.java @@ -1,3 +1,11 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + package com.microsoft.sqlserver.jdbc; public enum InternalSpatialDatatype { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java b/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java index 6f861c4bb..f2e312008 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java @@ -1,3 +1,11 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + package com.microsoft.sqlserver.jdbc; import java.io.IOException; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java index b614ad5fe..2a9c757d0 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java @@ -415,6 +415,10 @@ Object getValue(JDBCType jdbcType, // statement level), cryptoMeta would be null. return getterDTV.getValue(jdbcType, outScale, getterArgs, cal, typeInfo, cryptoMeta, tdsReader); } + + Object getSetterValue() { + return setterDTV.getSetterValue(); + } int getInt(TDSReader tdsReader) throws SQLServerException { Integer value = (Integer) getValue(JDBCType.INTEGER, null, null, tdsReader); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java index d89a95e11..6dcf58cf6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java @@ -35,10 +35,16 @@ */ final class SQLCollation implements java.io.Serializable { - private final int info; // First 4 bytes of TDS collation. + /** + * + */ + private static final long serialVersionUID = 6748833280721312349L; + + private final int info; // First 4 bytes of TDS collation. private int langID() { return info & 0x0000FFFF; } private final int sortId; // 5th byte of TDS collation. private final Encoding encoding; + private static final int UTF8_IN_TDSCOLLATION = 0x4000000; // Utility methods for getting details of this collation's encoding final Charset getCharset() throws SQLServerException { return encoding.charset(); } @@ -77,8 +83,13 @@ int getCollationSortID() { */ info = tdsReader.readInt(); // 4 bytes, contains: LCID ColFlags Version sortId = tdsReader.readUnsignedByte(); // 1 byte, contains: SortId - // For a SortId==0 collation, the LCID bits correspond to a LocaleId - encoding = (0 == sortId) ? encodingFromLCID() : encodingFromSortId(); + if (UTF8_IN_TDSCOLLATION == (info & UTF8_IN_TDSCOLLATION)) { + encoding = Encoding.UTF8; + } + else { + // For a SortId==0 collation, the LCID bits correspond to a LocaleId + encoding = (0 == sortId) ? encodingFromLCID() : encodingFromSortId(); + } } /** @@ -549,6 +560,7 @@ private Encoding encodingFromSortId() throws UnsupportedEncodingException { enum Encoding { UNICODE ("UTF-16LE", true, false), + UTF8 ("UTF-8", true, false), CP437 ("Cp437", false, false), CP850 ("Cp850", false, false), CP874 ("MS874", true, true), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java index 964bb7ec9..41028eb8e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java @@ -11,6 +11,6 @@ final class SQLJdbcVersion { static final int major = 6; static final int minor = 5; - static final int patch = 3; + static final int patch = 4; static final int build = 0; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java index 096543ffd..a04b98296 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java @@ -1,3 +1,11 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + package com.microsoft.sqlserver.jdbc; import java.io.IOException; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java index f0d18eabb..3631e2374 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java @@ -12,9 +12,7 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -import java.sql.Blob; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -26,6 +24,9 @@ */ public final class SQLServerBlob extends SQLServerLob implements java.sql.Blob, java.io.Serializable { + /** + * Always refresh SerialVersionUID when prompted + */ private static final long serialVersionUID = -3526170228097889085L; // The value of the BLOB that this Blob object represents. @@ -38,15 +39,17 @@ public final class SQLServerBlob extends SQLServerLob implements java.sql.Blob, // Active streams which must be closed when the Blob is closed // // Initial size of the array is based on an assumption that a Blob object is - // typically used either for input or output, and then only once. The array size + // typically used either for input or output, and then only once. The array + // size // grows automatically if multiple streams are used. ArrayList activeStreams = new ArrayList<>(1); static private final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerBlob"); - static private final AtomicInteger baseID = new AtomicInteger(0); // Unique id generator for each instance (used for logging). + // Unique id generator for each instance (use for logging). + static private final AtomicInteger baseID = new AtomicInteger(0); final private String traceID; - + final public String toString() { return traceID; } @@ -63,7 +66,7 @@ private static int nextInstanceID() { * the database connection this blob is implemented on * @param data * the BLOB's data - * @deprecated Use {@link SQLServerConnection#createBlob()} instead. + * @deprecated Use {@link SQLServerConnection#createBlob()} instead. */ @Deprecated public SQLServerBlob(SQLServerConnection connection, @@ -71,8 +74,10 @@ public SQLServerBlob(SQLServerConnection connection, traceID = " SQLServerBlob:" + nextInstanceID(); con = connection; - // Disallow Blobs with internal null values. We throw a NullPointerException here - // because the method signature of the public constructor does not permit a SQLException + // Disallow Blobs with internal null values. We throw a + // NullPointerException here + // because the method signature of the public constructor does not + // permit a SQLException // to be thrown. if (null == data) throw new NullPointerException(SQLServerException.getErrString("R_cantSetNull")); @@ -100,15 +105,11 @@ public SQLServerBlob(SQLServerConnection connection, logger.fine(toString() + " created by (null connection)"); } - /** - * Frees this Blob object and releases the resources that it holds. - *

- * After free() has been called, any attempt to invoke a method other than free() will result in a SQLException being thrown. If free() is called - * multiple times, the subsequent calls to free are treated as a no-op. - */ + @Override public void free() throws SQLException { if (!isClosed) { - // Close active streams, ignoring any errors, since nothing can be done with them after that point anyway. + // Close active streams, ignoring any errors, since nothing can be + // done with them after that point anyway. if (null != activeStreams) { for (Closeable stream : activeStreams) { try { @@ -123,7 +124,6 @@ public void free() throws SQLException { // Discard the value value = null; - isClosed = true; } } @@ -138,9 +138,9 @@ private void checkClosed() throws SQLServerException { } } + @Override public InputStream getBinaryStream() throws SQLException { checkClosed(); - if (null == value && !activeStreams.isEmpty()) { InputStream stream = (InputStream) activeStreams.get(0); try { @@ -159,10 +159,11 @@ public InputStream getBinaryStream() throws SQLException { } } + @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { - // Not implemented - partial materialization - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwFeatureNotSupportedException(); + return null; } private InputStream getBinaryStreamInternal(int pos, @@ -177,19 +178,7 @@ private InputStream getBinaryStreamInternal(int pos, return getterStream; } - /** - * Retrieves all or part of the BLOB value that this Blob object represents, as an array of bytes. This byte array contains up to length - * consecutive bytes starting at position pos. - * - * @param pos - * - the ordinal position of the first byte in the BLOB value to be extracted; the first byte is at position 1 - * @param length - * - the number of consecutive bytes to be copied; the value for length must be 0 or greater - * @return a byte array containing up to length consecutive bytes from the BLOB value designated by this Blob object, starting with the byte at - * position pos - * @throws SQLException - * - if there is an error accessing the BLOB value; if pos is less than 1 or length is less than 0 - */ + @Override public byte[] getBytes(long pos, int length) throws SQLException { checkClosed(); @@ -223,34 +212,26 @@ public byte[] getBytes(long pos, return bTemp; } - /** - * Return the length of the BLOB - * - * @throws SQLException - * when an error occurs - * @return the data length - */ + @Override public long length() throws SQLException { checkClosed(); if (value == null && activeStreams.get(0) instanceof PLPInputStream) { - return (long)((PLPInputStream)activeStreams.get(0)).payloadLength; + return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength; } getBytesFromStream(); return value.length; } - - /** - * Function for the result set to maintain blobs it has created - * @throws SQLException - */ + + @Override void fillFromStream() throws SQLException { - if(!isClosed) { - getBytesFromStream(); - } + if (!isClosed) { + getBytesFromStream(); + } } - + /** * Converts stream to byte[] + * * @throws SQLServerException */ private void getBytesFromStream() throws SQLServerException { @@ -266,21 +247,11 @@ private void getBytesFromStream() throws SQLServerException { } } - /** - * Retrieves the byte position in the BLOB value designated by this Blob object at which pattern begins. The search begins at position start. - * - * @param pattern - * - the Blob object designating the BLOB value for which to search - * @param start - * - the position in the BLOB value at which to begin searching; the first position is 1 - * @return the postion at which the pattern begins, else -1 - * @throws SQLException - * - if there is an error accessing the BLOB value or if start is less than 1 - */ - public long position(Blob pattern, + @Override + public long position(java.sql.Blob pattern, long start) throws SQLException { checkClosed(); - + getBytesFromStream(); if (start < 1) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidPositionIndex")); @@ -294,18 +265,7 @@ public long position(Blob pattern, return position(pattern.getBytes((long) 1, (int) pattern.length()), start); } - /** - * Retrieves the byte position at which the specified byte array pattern begins within the BLOB value that this Blob object represents. The search - * for pattern begins at position start. - * - * @param bPattern - * - the byte array for which to search - * @param start - * - the position at which to begin searching; the first position is 1 - * @return the position at which the pattern appears, else -1 - * @throws SQLException - * - if there is an error accessing the BLOB or if start is less than 1 - */ + @Override public long position(byte[] bPattern, long start) throws SQLException { checkClosed(); @@ -316,7 +276,8 @@ public long position(byte[] bPattern, SQLServerException.makeFromDriverError(con, null, form.format(msgArgs), null, true); } - // Back compat: Handle null search string as not found rather than throw an exception. + // Back compat: Handle null search string as not found rather than throw + // an exception. // JDBC spec doesn't describe the behavior for a null pattern. if (null == bPattern) return -1; @@ -342,20 +303,11 @@ public long position(byte[] bPattern, return -1; } - /* JDBC 3.0 methods */ - - /** - * Truncate a BLOB - * - * @param len - * the new length for the BLOB - * @throws SQLException - * when an error occurs - */ + @Override public void truncate(long len) throws SQLException { checkClosed(); getBytesFromStream(); - + if (len < 0) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidLength")); Object[] msgArgs = {len}; @@ -369,15 +321,7 @@ public void truncate(long len) throws SQLException { } } - /** - * Retrieves a stream that can be used to write to the BLOB value that this Blob object represents - * - * @param pos - * - the position in the BLOB value at which to start writing; the first position is 1 - * @return a java.io.OutputStream object to which data can be written - * @throws SQLException - * - if there is an error accessing the BLOB value or if pos is less than 1 - */ + @Override public java.io.OutputStream setBinaryStream(long pos) throws SQLException { checkClosed(); @@ -389,21 +333,11 @@ public java.io.OutputStream setBinaryStream(long pos) throws SQLException { return new SQLServerBlobOutputStream(this, pos); } - /** - * Writes the given array of bytes into the Blob starting at position pos, and returns the number of bytes written. - * - * @param pos - * the position (1 based) in the Blob object at which to start writing the data. - * @param bytes - * the array of bytes to be written into the Blob. - * @throws SQLException - * if there is an error accessing the BLOB value. - * @return the number of bytes written. - */ + @Override public int setBytes(long pos, byte[] bytes) throws SQLException { checkClosed(); - + getBytesFromStream(); if (null == bytes) SQLServerException.makeFromDriverError(con, null, SQLServerException.getErrString("R_cantSetNull"), null, true); @@ -411,26 +345,7 @@ public int setBytes(long pos, return setBytes(pos, bytes, 0, bytes.length); } - /** - * Writes all or part of the given byte array to the BLOB value that this Blob object represents and returns the number of bytes written. Writing - * starts at position pos in the BLOB value; len bytes from the given byte wrray are written. The array of bytes will overwrite the existing bytes - * in the Blob object starting at the position pos. If the end of the Blob value is reached while writing the array bytes, then the length of the - * Blob value will be increased to accomodate the extra bytes. - * - * SQL Server behavior: If the value specified for pos is greater than the length+1 of the BLOB value then a SQLException is thrown. - * - * @param pos - * - the position in the BLOB object at which to start writing; the first position is 1 - * @param bytes - * - the array of bytes to be written to this BLOB object. - * @param offset - * - the offset (0-based) into the array bytes at which to start reading the bytes to set - * @param len - * - the number of bytes to be written to the BLOB value from the array of bytes bytes - * @return the number of bytes written. - * @throws SQLException - * - if there is an error accessing the BLOB value or if pos is less than 1 - */ + @Override public int setBytes(long pos, byte[] bytes, int offset, @@ -469,7 +384,8 @@ public int setBytes(long pos, // Overwrite past end of value case. if (len >= value.length - pos) { - // Make sure the new value length wouldn't exceed the maximum allowed + // Make sure the new value length wouldn't exceed the maximum + // allowed DataTypes.getCheckedLength(con, JDBCType.BLOB, pos + len, false); assert pos + len <= Integer.MAX_VALUE; @@ -506,14 +422,14 @@ final class SQLServerBlobOutputStream extends java.io.OutputStream { this.currentPos = startPos; } - // java.io.OutputStream interface methods. - + @Override public void write(byte[] b) throws IOException { if (null == b) return; write(b, 0, b.length); } + @Override public void write(byte[] b, int off, int len) throws IOException { @@ -529,6 +445,7 @@ public void write(byte[] b, } } + @Override public void write(int b) throws java.io.IOException { byte[] bTemp = new byte[1]; bTemp[0] = (byte) (b & 0xFF); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java new file mode 100644 index 000000000..8ded138ac --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java @@ -0,0 +1,482 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Types; +import java.text.DecimalFormat; +import java.text.MessageFormat; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import java.util.Set; + +/** + * A simple implementation of the ISQLServerBulkRecord interface that can be + * used to read in the basic Java data types from an ArrayList of Parameters + * that were provided by pstmt/cstmt. + */ +public class SQLServerBulkBatchInsertRecord extends SQLServerBulkCommon { + + private List batchParam; + private int batchParamIndex = -1; + private List columnList; + private List valueList; + + /* + * Class name for logging. + */ + private static final String loggerClassName = "com.microsoft.sqlserver.jdbc.SQLServerBulkBatchInsertRecord"; + + /* + * Logger + */ + private static final java.util.logging.Logger loggerExternal = java.util.logging.Logger + .getLogger(loggerClassName); + + public SQLServerBulkBatchInsertRecord(ArrayList batchParam, + ArrayList columnList, ArrayList valueList, + String encoding) throws SQLServerException { + loggerExternal.entering(loggerClassName, + "SQLServerBulkBatchInsertRecord", + new Object[]{batchParam, encoding}); + + if (null == batchParam) { + throwInvalidArgument("batchParam"); + } + + if (null == valueList) { + throwInvalidArgument("valueList"); + } + + this.batchParam = batchParam; + this.columnList = columnList; + this.valueList = valueList; + columnMetadata = new HashMap<>(); + + loggerExternal.exiting(loggerClassName, + "SQLServerBulkBatchInsertRecord"); + } + + @Override + public DateTimeFormatter getColumnDateTimeFormatter(int column) { + return columnMetadata.get(column).dateTimeFormatter; + } + + @Override + public Set getColumnOrdinals() { + return columnMetadata.keySet(); + } + + @Override + public String getColumnName(int column) { + return columnMetadata.get(column).columnName; + } + + @Override + public int getColumnType(int column) { + return columnMetadata.get(column).columnType; + } + + @Override + public int getPrecision(int column) { + return columnMetadata.get(column).precision; + } + + @Override + public int getScale(int column) { + return columnMetadata.get(column).scale; + } + + @Override + public boolean isAutoIncrement(int column) { + return false; + } + + private Object convertValue(ColumnMetadata cm, Object data) + throws SQLServerException { + switch (cm.columnType) { + case Types.INTEGER : { + // Formatter to remove the decimal part as SQL Server floors the + // decimal in integer types + DecimalFormat decimalFormatter = new DecimalFormat("#"); + decimalFormatter.setRoundingMode(RoundingMode.DOWN); + String formatedfInput = decimalFormatter + .format(Double.parseDouble(data.toString())); + return Integer.valueOf(formatedfInput); + } + + case Types.TINYINT : + case Types.SMALLINT : { + // Formatter to remove the decimal part as SQL Server floors the + // decimal in integer types + DecimalFormat decimalFormatter = new DecimalFormat("#"); + decimalFormatter.setRoundingMode(RoundingMode.DOWN); + String formatedfInput = decimalFormatter + .format(Double.parseDouble(data.toString())); + return Short.valueOf(formatedfInput); + } + + case Types.BIGINT : { + BigDecimal bd = new BigDecimal(data.toString().trim()); + try { + return bd.setScale(0, RoundingMode.DOWN).longValueExact(); + } catch (ArithmeticException ex) { + String value = "'" + data + "'"; + MessageFormat form = new MessageFormat(SQLServerException + .getErrString("R_errorConvertingValue")); + throw new SQLServerException(form.format( + new Object[]{value, JDBCType.of(cm.columnType)}), + null, 0, ex); + } + } + + case Types.DECIMAL : + case Types.NUMERIC : { + BigDecimal bd = new BigDecimal(data.toString().trim()); + return bd.setScale(cm.scale, RoundingMode.HALF_UP); + } + + case Types.BIT : { + // "true" => 1, "false" => 0 + // Any non-zero value (integer/double) => 1, 0/0.0 => 0 + try { + return (0 == Double.parseDouble(data.toString())) + ? Boolean.FALSE + : Boolean.TRUE; + } catch (NumberFormatException e) { + return Boolean.parseBoolean(data.toString()); + } + } + + case Types.REAL : { + return Float.parseFloat(data.toString()); + } + + case Types.DOUBLE : { + return Double.parseDouble(data.toString()); + } + + case Types.BINARY : + case Types.VARBINARY : + case Types.LONGVARBINARY : + case Types.BLOB : { + // Strip off 0x if present. + String binData = data.toString().trim(); + if (binData.startsWith("0x") || binData.startsWith("0X")) { + return binData.substring(2); + } else { + return binData; + } + } + + case java.sql.Types.TIME_WITH_TIMEZONE : { + OffsetTime offsetTimeValue; + + // The per-column DateTimeFormatter gets priority. + if (null != cm.dateTimeFormatter) + offsetTimeValue = OffsetTime.parse(data.toString(), + cm.dateTimeFormatter); + else if (timeFormatter != null) + offsetTimeValue = OffsetTime.parse(data.toString(), + timeFormatter); + else + offsetTimeValue = OffsetTime.parse(data.toString()); + + return offsetTimeValue; + } + + case java.sql.Types.TIMESTAMP_WITH_TIMEZONE : { + OffsetDateTime offsetDateTimeValue; + + // The per-column DateTimeFormatter gets priority. + if (null != cm.dateTimeFormatter) + offsetDateTimeValue = OffsetDateTime.parse(data.toString(), + cm.dateTimeFormatter); + else if (dateTimeFormatter != null) + offsetDateTimeValue = OffsetDateTime.parse(data.toString(), + dateTimeFormatter); + else + offsetDateTimeValue = OffsetDateTime.parse(data.toString()); + + return offsetDateTimeValue; + } + + case Types.NULL : { + return null; + } + + case Types.DATE : + case Types.CHAR : + case Types.NCHAR : + case Types.VARCHAR : + case Types.NVARCHAR : + case Types.LONGVARCHAR : + case Types.LONGNVARCHAR : + case Types.CLOB : + default : { + // The string is copied as is. + return data; + } + } + } + + private String removeSingleQuote(String s) { + int len = s.length(); + return (s.charAt(0) == '\'' && s.charAt(len - 1) == '\'') + ? s.substring(1, len - 1) + : s; + } + + @Override + public Object[] getRowData() throws SQLServerException { + Object[] data = new Object[columnMetadata.size()]; + int valueIndex = 0; + String valueData; + Object rowData; + int columnListIndex = 0; + + // check if the size of the list of values = size of the list of columns + // (which is optional) + if (null != columnList && columnList.size() != valueList.size()) { + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_DataSchemaMismatch")); + Object[] msgArgs = {}; + throw new SQLServerException(form.format(msgArgs), + SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); + } + + for (Entry pair : columnMetadata.entrySet()) { + int index = pair.getKey() - 1; + + // To explain what each variable represents: + // columnMetadata = map containing the ENTIRE list of columns in the + // table. + // columnList = the *optional* list of columns the user can provide. + // For example, the (c1, c3) part of this query: INSERT into t1 (c1, + // c3) values (?, ?) + // valueList = the *mandatory* list of columns the user needs + // provide. This is the (?, ?) part of the previous query. The size + // of this valueList will always equal the number of + // the entire columns in the table IF columnList has NOT been + // provided. If columnList HAS been provided, then this valueList + // may be smaller than the list of all columns (which is + // columnMetadata). + + // case when the user has not provided the optional list of column + // names. + if (null == columnList || columnList.size() == 0) { + valueData = valueList.get(index); + // if the user has provided a wildcard for this column, fetch + // the set value from the batchParam. + if (valueData.equalsIgnoreCase("?")) { + rowData = batchParam.get(batchParamIndex)[valueIndex++] + .getSetterValue(); + } else if (valueData.equalsIgnoreCase("null")) { + rowData = null; + } + // if the user has provided a hardcoded value for this column, + // rowData is simply set to the hardcoded value. + else { + rowData = removeSingleQuote(valueData); + } + } + // case when the user has provided the optional list of column + // names. + else { + // columnListIndex is a separate counter we need to keep track + // of for each time we've processed a column + // that the user provided. + // for example, if the user provided an optional columnList of + // (c1, c3, c5, c7) in a table that has 8 columns (c1~c8), + // then the columnListIndex would increment only when we're + // dealing with the four columns inside columnMetadata. + // compare the list of the optional list of column names to the + // table's metadata, and match each other, so we assign the + // correct value to each column. + if (columnList.size() > columnListIndex + && columnList.get(columnListIndex).equalsIgnoreCase( + columnMetadata.get(index + 1).columnName)) { + valueData = valueList.get(columnListIndex); + if (valueData.equalsIgnoreCase("?")) { + rowData = batchParam.get(batchParamIndex)[valueIndex++] + .getSetterValue(); + } else if (valueData.equalsIgnoreCase("null")) { + rowData = null; + } else { + rowData = removeSingleQuote(valueData); + } + columnListIndex++; + } else { + rowData = null; + } + } + + try { + if (null == rowData) { + data[index] = null; + continue; + } else if (0 == rowData.toString().length()) { + data[index] = ""; + continue; + } + data[index] = convertValue(pair.getValue(), rowData); + } catch (IllegalArgumentException e) { + String value = "'" + rowData + "'"; + MessageFormat form = new MessageFormat(SQLServerException + .getErrString("R_errorConvertingValue")); + throw new SQLServerException( + form.format(new Object[]{value, + JDBCType.of(pair.getValue().columnType)}), + null, 0, e); + } catch (ArrayIndexOutOfBoundsException e) { + throw new SQLServerException( + SQLServerException.getErrString("R_DataSchemaMismatch"), + e); + } + } + return data; + } + + @Override + void addColumnMetadataInternal(int positionInSource, String name, + int jdbcType, int precision, int scale, + DateTimeFormatter dateTimeFormatter) throws SQLServerException { + loggerExternal.entering(loggerClassName, "addColumnMetadata", + new Object[]{positionInSource, name, jdbcType, precision, + scale}); + + String colName = ""; + + if (0 >= positionInSource) { + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_invalidColumnOrdinal")); + Object[] msgArgs = {positionInSource}; + throw new SQLServerException(form.format(msgArgs), + SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); + } + + if (null != name) + colName = name.trim(); + else if ((null != columnNames) + && (columnNames.length >= positionInSource)) + colName = columnNames[positionInSource - 1]; + + if ((null != columnNames) && (positionInSource > columnNames.length)) { + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_invalidColumn")); + Object[] msgArgs = {positionInSource}; + throw new SQLServerException(form.format(msgArgs), + SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); + } + + checkDuplicateColumnName(positionInSource, name); + switch (jdbcType) { + /* + * SQL Server supports numerous string literal formats for temporal + * types, hence sending them as varchar with approximate + * precision(length) needed to send supported string literals. + * string literal formats supported by temporal types are available + * in MSDN page on data types. + */ + case java.sql.Types.DATE : + case java.sql.Types.TIME : + case java.sql.Types.TIMESTAMP : + case microsoft.sql.Types.DATETIMEOFFSET : + columnMetadata.put(positionInSource, new ColumnMetadata(colName, + jdbcType, precision, scale, dateTimeFormatter)); + break; + + // Redirect SQLXML as LONGNVARCHAR + // SQLXML is not valid type in TDS + case java.sql.Types.SQLXML : + columnMetadata.put(positionInSource, + new ColumnMetadata(colName, java.sql.Types.LONGNVARCHAR, + precision, scale, dateTimeFormatter)); + break; + + // Redirecting Float as Double based on data type mapping + // https://msdn.microsoft.com/en-us/library/ms378878%28v=sql.110%29.aspx + case java.sql.Types.FLOAT : + columnMetadata.put(positionInSource, + new ColumnMetadata(colName, java.sql.Types.DOUBLE, + precision, scale, dateTimeFormatter)); + break; + + // redirecting BOOLEAN as BIT + case java.sql.Types.BOOLEAN : + columnMetadata.put(positionInSource, + new ColumnMetadata(colName, java.sql.Types.BIT, + precision, scale, dateTimeFormatter)); + break; + + default : + columnMetadata.put(positionInSource, new ColumnMetadata(colName, + jdbcType, precision, scale, dateTimeFormatter)); + } + + loggerExternal.exiting(loggerClassName, "addColumnMetadata"); + } + + @Override + public void setTimestampWithTimezoneFormat(String dateTimeFormat) { + loggerExternal.entering(loggerClassName, + "setTimestampWithTimezoneFormat", dateTimeFormat); + + super.setTimestampWithTimezoneFormat(dateTimeFormat); + + loggerExternal.exiting(loggerClassName, + "setTimestampWithTimezoneFormat"); + } + + @Override + public void setTimestampWithTimezoneFormat( + DateTimeFormatter dateTimeFormatter) { + loggerExternal.entering(loggerClassName, + "setTimestampWithTimezoneFormat", + new Object[]{dateTimeFormatter}); + + super.setTimestampWithTimezoneFormat(dateTimeFormatter); + + loggerExternal.exiting(loggerClassName, + "setTimestampWithTimezoneFormat"); + } + + @Override + public void setTimeWithTimezoneFormat(String timeFormat) { + loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", + timeFormat); + + super.setTimeWithTimezoneFormat(timeFormat); + + loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); + } + + @Override + public void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { + loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", + new Object[]{dateTimeFormatter}); + + super.setTimeWithTimezoneFormat(dateTimeFormatter); + + loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); + } + + @Override + public boolean next() throws SQLServerException { + batchParamIndex++; + return batchParamIndex < batchParam.size(); + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index cce49a416..31e101463 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -23,38 +23,15 @@ import java.time.OffsetTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; -import java.util.Map; import java.util.Map.Entry; + import java.util.Set; /** * A simple implementation of the ISQLServerBulkRecord interface that can be used to read in the basic Java data types from a delimited file where * each line represents a row of data. */ -public class SQLServerBulkCSVFileRecord implements ISQLServerBulkRecord, java.lang.AutoCloseable { - /* - * Class to represent the column metadata - */ - private class ColumnMetadata { - String columnName; - int columnType; - int precision; - int scale; - DateTimeFormatter dateTimeFormatter = null; - - ColumnMetadata(String name, - int type, - int precision, - int scale, - DateTimeFormatter dateTimeFormatter) { - columnName = name; - columnType = type; - this.precision = precision; - this.scale = scale; - this.dateTimeFormatter = dateTimeFormatter; - } - } - +public class SQLServerBulkCSVFileRecord extends SQLServerBulkCommon implements java.lang.AutoCloseable { /* * Resources associated with reading in the file */ @@ -62,12 +39,6 @@ private class ColumnMetadata { private InputStreamReader sr; private FileInputStream fis; - /* - * Metadata to represent the columns in the file. Each column should be mapped to its corresponding position within the file (from position 1 and - * onwards) - */ - private Map columnMetadata; - /* * Current line of data to parse. */ @@ -78,21 +49,6 @@ private class ColumnMetadata { */ private final String delimiter; - /* - * Contains all the column names if firstLineIsColumnNames is true - */ - private String[] columnNames = null; - - /* - * Contains the format that java.sql.Types.TIMESTAMP_WITH_TIMEZONE data should be read in as. - */ - private DateTimeFormatter dateTimeFormatter = null; - - /* - * Contains the format that java.sql.Types.TIME_WITH_TIMEZONE data should be read in as. - */ - private DateTimeFormatter timeFormatter = null; - /* * Class name for logging. */ @@ -162,7 +118,7 @@ else if (null == delimiter) { loggerExternal.exiting(loggerClassName, "SQLServerBulkCSVFileRecord"); } - + /** * Creates a simple reader to parse data from a delimited file with the given encoding. * @@ -253,199 +209,6 @@ public SQLServerBulkCSVFileRecord(String fileToParse, this(fileToParse, null, ",", firstLineIsColumnNames); } - /** - * Adds metadata for the given column in the file. - * - * @param positionInFile - * Indicates which column the metadata is for. Columns start at 1. - * @param name - * Name for the column (optional if only using column ordinal in a mapping for SQLServerBulkCopy operation) - * @param jdbcType - * JDBC data type of the column - * @param precision - * Precision for the column (ignored for the appropriate data types) - * @param scale - * Scale for the column (ignored for the appropriate data types) - * @param dateTimeFormatter - * format to parse data that is sent - * @throws SQLServerException - * when an error occurs - */ - public void addColumnMetadata(int positionInFile, - String name, - int jdbcType, - int precision, - int scale, - DateTimeFormatter dateTimeFormatter) throws SQLServerException { - addColumnMetadataInternal(positionInFile, name, jdbcType, precision, scale, dateTimeFormatter); - } - - /** - * Adds metadata for the given column in the file. - * - * @param positionInFile - * Indicates which column the metadata is for. Columns start at 1. - * @param name - * Name for the column (optional if only using column ordinal in a mapping for SQLServerBulkCopy operation) - * @param jdbcType - * JDBC data type of the column - * @param precision - * Precision for the column (ignored for the appropriate data types) - * @param scale - * Scale for the column (ignored for the appropriate data types) - * @throws SQLServerException - * when an error occurs - */ - public void addColumnMetadata(int positionInFile, - String name, - int jdbcType, - int precision, - int scale) throws SQLServerException { - addColumnMetadataInternal(positionInFile, name, jdbcType, precision, scale, null); - } - - /** - * Adds metadata for the given column in the file. - * - * @param positionInFile - * Indicates which column the metadata is for. Columns start at 1. - * @param name - * Name for the column (optional if only using column ordinal in a mapping for SQLServerBulkCopy operation) - * @param jdbcType - * JDBC data type of the column - * @param precision - * Precision for the column (ignored for the appropriate data types) - * @param scale - * Scale for the column (ignored for the appropriate data types) - * @param dateTimeFormatter - * format to parse data that is sent - * @throws SQLServerException - * when an error occurs - */ - void addColumnMetadataInternal(int positionInFile, - String name, - int jdbcType, - int precision, - int scale, - DateTimeFormatter dateTimeFormatter) throws SQLServerException { - loggerExternal.entering(loggerClassName, "addColumnMetadata", new Object[] {positionInFile, name, jdbcType, precision, scale}); - - String colName = ""; - - if (0 >= positionInFile) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidColumnOrdinal")); - Object[] msgArgs = {positionInFile}; - throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); - } - - if (null != name) - colName = name.trim(); - else if ((columnNames != null) && (columnNames.length >= positionInFile)) - colName = columnNames[positionInFile - 1]; - - if ((columnNames != null) && (positionInFile > columnNames.length)) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidColumn")); - Object[] msgArgs = {positionInFile}; - throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); - } - - checkDuplicateColumnName(positionInFile, name); - switch (jdbcType) { - /* - * SQL Server supports numerous string literal formats for temporal types, hence sending them as varchar with approximate - * precision(length) needed to send supported string literals. string literal formats supported by temporal types are available in MSDN - * page on data types. - */ - case java.sql.Types.DATE: - case java.sql.Types.TIME: - case java.sql.Types.TIMESTAMP: - case microsoft.sql.Types.DATETIMEOFFSET: - // The precision is just a number long enough to hold all types of temporal data, doesn't need to be exact precision. - columnMetadata.put(positionInFile, new ColumnMetadata(colName, jdbcType, 50, scale, dateTimeFormatter)); - break; - - // Redirect SQLXML as LONGNVARCHAR - // SQLXML is not valid type in TDS - case java.sql.Types.SQLXML: - columnMetadata.put(positionInFile, new ColumnMetadata(colName, java.sql.Types.LONGNVARCHAR, precision, scale, dateTimeFormatter)); - break; - - // Redirecting Float as Double based on data type mapping - // https://msdn.microsoft.com/en-us/library/ms378878%28v=sql.110%29.aspx - case java.sql.Types.FLOAT: - columnMetadata.put(positionInFile, new ColumnMetadata(colName, java.sql.Types.DOUBLE, precision, scale, dateTimeFormatter)); - break; - - // redirecting BOOLEAN as BIT - case java.sql.Types.BOOLEAN: - columnMetadata.put(positionInFile, new ColumnMetadata(colName, java.sql.Types.BIT, precision, scale, dateTimeFormatter)); - break; - - default: - columnMetadata.put(positionInFile, new ColumnMetadata(colName, jdbcType, precision, scale, dateTimeFormatter)); - } - - loggerExternal.exiting(loggerClassName, "addColumnMetadata"); - } - - /** - * Set the format for reading in dates from the file. - * - * @param dateTimeFormat - * format to parse data sent as java.sql.Types.TIMESTAMP_WITH_TIMEZONE - */ - public void setTimestampWithTimezoneFormat(String dateTimeFormat) { - DriverJDBCVersion.checkSupportsJDBC42(); - loggerExternal.entering(loggerClassName, "setTimestampWithTimezoneFormat", dateTimeFormat); - - this.dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat); - - loggerExternal.exiting(loggerClassName, "setTimestampWithTimezoneFormat"); - } - - /** - * Set the format for reading in dates from the file. - * - * @param dateTimeFormatter - * format to parse data sent as java.sql.Types.TIMESTAMP_WITH_TIMEZONE - */ - public void setTimestampWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { - loggerExternal.entering(loggerClassName, "setTimestampWithTimezoneFormat", new Object[] {dateTimeFormatter}); - - this.dateTimeFormatter = dateTimeFormatter; - - loggerExternal.exiting(loggerClassName, "setTimestampWithTimezoneFormat"); - } - - /** - * Set the format for reading in dates from the file. - * - * @param timeFormat - * format to parse data sent as java.sql.Types.TIME_WITH_TIMEZONE - */ - public void setTimeWithTimezoneFormat(String timeFormat) { - DriverJDBCVersion.checkSupportsJDBC42(); - loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", timeFormat); - - this.timeFormatter = DateTimeFormatter.ofPattern(timeFormat); - - loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); - } - - /** - * Set the format for reading in dates from the file. - * - * @param dateTimeFormatter - * format to parse data sent as java.sql.Types.TIME_WITH_TIMEZONE - */ - public void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { - loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", new Object[] {dateTimeFormatter}); - - this.timeFormatter = dateTimeFormatter; - - loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); - } - /** * Releases any resources associated with the file reader. * @@ -478,6 +241,7 @@ public void close() throws SQLServerException { loggerExternal.exiting(loggerClassName, "close"); } + @Override public DateTimeFormatter getColumnDateTimeFormatter(int column) { return columnMetadata.get(column).dateTimeFormatter; } @@ -518,11 +282,13 @@ public Object[] getRowData() throws SQLServerException { return null; else { // Binary data may be corrupted - // The limit in split() function should be a negative value, otherwise trailing empty strings are discarded. + // The limit in split() function should be a negative value, + // otherwise trailing empty strings are discarded. // Empty string is returned if there is no value. String[] data = currentLine.split(delimiter, -1); - // Cannot go directly from String[] to Object[] and expect it to act as an array. + // Cannot go directly from String[] to Object[] and expect it to act + // as an array. Object[] dataRow = new Object[data.length]; for (Entry pair : columnMetadata.entrySet()) { @@ -538,7 +304,7 @@ public Object[] getRowData() throws SQLServerException { // Source header has more columns than current line read if (columnNames != null && (columnNames.length > data.length)) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_CSVDataSchemaMismatch")); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_DataSchemaMismatch")); Object[] msgArgs = {}; throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); } @@ -555,8 +321,10 @@ public Object[] getRowData() throws SQLServerException { * inserted into an numeric column. Our implementation does the same. */ case Types.INTEGER: { - // Formatter to remove the decimal part as SQL Server floors the decimal in integer types + // Formatter to remove the decimal part as SQL + // Server floors the decimal in integer types DecimalFormat decimalFormatter = new DecimalFormat("#"); + decimalFormatter.setRoundingMode(RoundingMode.DOWN); String formatedfInput = decimalFormatter.format(Double.parseDouble(data[pair.getKey() - 1])); dataRow[pair.getKey() - 1] = Integer.valueOf(formatedfInput); break; @@ -564,8 +332,10 @@ public Object[] getRowData() throws SQLServerException { case Types.TINYINT: case Types.SMALLINT: { - // Formatter to remove the decimal part as SQL Server floors the decimal in integer types + // Formatter to remove the decimal part as SQL + // Server floors the decimal in integer types DecimalFormat decimalFormatter = new DecimalFormat("#"); + decimalFormatter.setRoundingMode(RoundingMode.DOWN); String formatedfInput = decimalFormatter.format(Double.parseDouble(data[pair.getKey() - 1])); dataRow[pair.getKey() - 1] = Short.valueOf(formatedfInput); break; @@ -575,10 +345,11 @@ public Object[] getRowData() throws SQLServerException { BigDecimal bd = new BigDecimal(data[pair.getKey() - 1].trim()); try { dataRow[pair.getKey() - 1] = bd.setScale(0, RoundingMode.DOWN).longValueExact(); - } catch (ArithmeticException ex) { + } + catch (ArithmeticException ex) { String value = "'" + data[pair.getKey() - 1] + "'"; MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[]{value, JDBCType.of(cm.columnType)}), null, 0, ex); + throw new SQLServerException(form.format(new Object[] {value, JDBCType.of(cm.columnType)}), null, 0, ex); } break; } @@ -592,10 +363,12 @@ public Object[] getRowData() throws SQLServerException { case Types.BIT: { // "true" => 1, "false" => 0 - // Any non-zero value (integer/double) => 1, 0/0.0 => 0 + // Any non-zero value (integer/double) => 1, 0/0.0 + // => 0 try { dataRow[pair.getKey() - 1] = (0 == Double.parseDouble(data[pair.getKey() - 1])) ? Boolean.FALSE : Boolean.TRUE; - } catch (NumberFormatException e) { + } + catch (NumberFormatException e) { dataRow[pair.getKey() - 1] = Boolean.parseBoolean(data[pair.getKey() - 1]); } break; @@ -620,21 +393,20 @@ public Object[] getRowData() throws SQLServerException { * 'BULK INSERT' except that we will allow 0x prefix whereas 'BULK INSERT' command does not allow 0x prefix. A BULK INSERT * example: A sample csv file containing data for 2 binary columns and 1 row: 61,62 Table definition: create table t1(c1 * varbinary(10), c2 varbinary(10)) BULK INSERT command: bulk insert t1 from 'C:\in.csv' - * with(DATAFILETYPE='char',firstrow=1,FIELDTERMINATOR=',') select * from t1 shows 1 row with columns: 0x61, 0x62 + * with(DATAFILETYPE='char',firstrow=1, FIELDTERMINATOR=',') select * from t1 shows 1 row with columns: 0x61, 0x62 */ // Strip off 0x if present. String binData = data[pair.getKey() - 1].trim(); if (binData.startsWith("0x") || binData.startsWith("0X")) { dataRow[pair.getKey() - 1] = binData.substring(2); - } else { + } + else { dataRow[pair.getKey() - 1] = binData; } break; } - case 2013: // java.sql.Types.TIME_WITH_TIMEZONE - { - DriverJDBCVersion.checkSupportsJDBC42(); + case java.sql.Types.TIME_WITH_TIMEZONE: { OffsetTime offsetTimeValue; // The per-column DateTimeFormatter gets priority. @@ -649,9 +421,7 @@ else if (timeFormatter != null) break; } - case 2014: // java.sql.Types.TIMESTAMP_WITH_TIMEZONE - { - DriverJDBCVersion.checkSupportsJDBC42(); + case java.sql.Types.TIMESTAMP_WITH_TIMEZONE: { OffsetDateTime offsetDateTimeValue; // The per-column DateTimeFormatter gets priority. @@ -691,18 +461,20 @@ else if (dateTimeFormatter != null) * * Handling delimiters in data: Excel allows comma in data when data is surrounded with quotes. For example, * "Hello, world" is treated as one cell. BCP and BULK INSERT deos not allow field terminators in data: - * https://technet.microsoft.com/en-us/library/aa196735%28v=sql.80%29.aspx?f=255&MSPPError=-2147217396 + * https://technet.microsoft.com/en-us/library/ aa196735%28v=sql.80%29.aspx?f=255&MSPPError=- 2147217396 */ dataRow[pair.getKey() - 1] = data[pair.getKey() - 1]; break; } } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { String value = "'" + data[pair.getKey() - 1] + "'"; MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[]{value, JDBCType.of(cm.columnType)}), null, 0, e); - } catch (ArrayIndexOutOfBoundsException e) { - throw new SQLServerException(SQLServerException.getErrString("R_CSVDataSchemaMismatch"), e); + throw new SQLServerException(form.format(new Object[] {value, JDBCType.of(cm.columnType)}), null, 0, e); + } + catch (ArrayIndexOutOfBoundsException e) { + throw new SQLServerException(SQLServerException.getErrString("R_DataSchemaMismatch"), e); } } @@ -711,42 +483,115 @@ else if (dateTimeFormatter != null) } @Override - public boolean next() throws SQLServerException { - try { - currentLine = fileReader.readLine(); + void addColumnMetadataInternal(int positionInSource, + String name, + int jdbcType, + int precision, + int scale, + DateTimeFormatter dateTimeFormatter) throws SQLServerException { + loggerExternal.entering(loggerClassName, "addColumnMetadata", new Object[] {positionInSource, name, jdbcType, precision, scale}); + + String colName = ""; + + if (0 >= positionInSource) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidColumnOrdinal")); + Object[] msgArgs = {positionInSource}; + throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); } - catch (IOException e) { - throw new SQLServerException(e.getMessage(), null, 0, e); + + if (null != name) + colName = name.trim(); + else if ((null != columnNames) && (columnNames.length >= positionInSource)) + colName = columnNames[positionInSource - 1]; + + if ((null != columnNames) && (positionInSource > columnNames.length)) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidColumn")); + Object[] msgArgs = {positionInSource}; + throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND, DriverError.NOT_SET, null); } - return (null != currentLine); + + checkDuplicateColumnName(positionInSource, name); + switch (jdbcType) { + /* + * SQL Server supports numerous string literal formats for temporal types, hence sending them as varchar with approximate + * precision(length) needed to send supported string literals. string literal formats supported by temporal types are available in MSDN + * page on data types. + */ + case java.sql.Types.DATE: + case java.sql.Types.TIME: + case java.sql.Types.TIMESTAMP: + case microsoft.sql.Types.DATETIMEOFFSET: + columnMetadata.put(positionInSource, new ColumnMetadata(colName, jdbcType, 50, scale, dateTimeFormatter)); + break; + + // Redirect SQLXML as LONGNVARCHAR + // SQLXML is not valid type in TDS + case java.sql.Types.SQLXML: + columnMetadata.put(positionInSource, new ColumnMetadata(colName, java.sql.Types.LONGNVARCHAR, precision, scale, dateTimeFormatter)); + break; + + // Redirecting Float as Double based on data type mapping + // https://msdn.microsoft.com/en-us/library/ms378878%28v=sql.110%29.aspx + case java.sql.Types.FLOAT: + columnMetadata.put(positionInSource, new ColumnMetadata(colName, java.sql.Types.DOUBLE, precision, scale, dateTimeFormatter)); + break; + + // redirecting BOOLEAN as BIT + case java.sql.Types.BOOLEAN: + columnMetadata.put(positionInSource, new ColumnMetadata(colName, java.sql.Types.BIT, precision, scale, dateTimeFormatter)); + break; + + default: + columnMetadata.put(positionInSource, new ColumnMetadata(colName, jdbcType, precision, scale, dateTimeFormatter)); + } + + loggerExternal.exiting(loggerClassName, "addColumnMetadata"); } - /* - * Helper method to throw a SQLServerExeption with the invalidArgument message and given argument. - */ - private void throwInvalidArgument(String argument) throws SQLServerException { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidArgument")); - Object[] msgArgs = {argument}; - SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false); + @Override + public void setTimestampWithTimezoneFormat(String dateTimeFormat) { + loggerExternal.entering(loggerClassName, "setTimestampWithTimezoneFormat", dateTimeFormat); + + super.setTimestampWithTimezoneFormat(dateTimeFormat); + + loggerExternal.exiting(loggerClassName, "setTimestampWithTimezoneFormat"); } - /* - * Method to throw a SQLServerExeption for duplicate column names - */ - private void checkDuplicateColumnName(int positionInFile, - String colName) throws SQLServerException { - - if (null != colName && colName.trim().length() != 0) { - for (Entry entry : columnMetadata.entrySet()) { - // duplicate check is not performed in case of same positionInFile value - if (null != entry && entry.getKey() != positionInFile) { - if (null != entry.getValue() && colName.trim().equalsIgnoreCase(entry.getValue().columnName)) { - throw new SQLServerException(SQLServerException.getErrString("R_BulkCSVDataDuplicateColumn"), null); - } - } + @Override + public void setTimestampWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { + loggerExternal.entering(loggerClassName, "setTimestampWithTimezoneFormat", new Object[] {dateTimeFormatter}); - } - } + super.setTimestampWithTimezoneFormat(dateTimeFormatter); + + loggerExternal.exiting(loggerClassName, "setTimestampWithTimezoneFormat"); + } + + @Override + public void setTimeWithTimezoneFormat(String timeFormat) { + loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", timeFormat); + + super.setTimeWithTimezoneFormat(timeFormat); + + loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); + } + + @Override + public void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { + loggerExternal.entering(loggerClassName, "setTimeWithTimezoneFormat", new Object[] {dateTimeFormatter}); + + super.setTimeWithTimezoneFormat(dateTimeFormatter); + + loggerExternal.exiting(loggerClassName, "setTimeWithTimezoneFormat"); + } + @Override + public boolean next() throws SQLServerException { + try { + currentLine = fileReader.readLine(); + } + catch (IOException e) { + throw new SQLServerException(e.getMessage(), null, 0, e); + } + return (null != currentLine); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java new file mode 100644 index 000000000..dee5350cc --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java @@ -0,0 +1,159 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.text.MessageFormat; +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.Map.Entry; + +abstract class SQLServerBulkCommon implements ISQLServerBulkRecord { + + /* + * Class to represent the column metadata + */ + protected class ColumnMetadata { + String columnName; + int columnType; + int precision; + int scale; + DateTimeFormatter dateTimeFormatter = null; + + ColumnMetadata(String name, int type, int precision, int scale, + DateTimeFormatter dateTimeFormatter) { + columnName = name; + columnType = type; + this.precision = precision; + this.scale = scale; + this.dateTimeFormatter = dateTimeFormatter; + } + } + + /* + * Contains all the column names if firstLineIsColumnNames is true + */ + protected String[] columnNames = null; + + /* + * Metadata to represent the columns in the batch/file. Each column should + * be mapped to its corresponding position within the parameter (from + * position 1 and onwards) + */ + protected Map columnMetadata; + + /* + * Contains the format that java.sql.Types.TIMESTAMP_WITH_TIMEZONE data + * should be read in as. + */ + protected DateTimeFormatter dateTimeFormatter = null; + + /* + * Contains the format that java.sql.Types.TIME_WITH_TIMEZONE data should be + * read in as. + */ + protected DateTimeFormatter timeFormatter = null; + + @Override + public void addColumnMetadata(int positionInSource, String name, + int jdbcType, int precision, int scale, + DateTimeFormatter dateTimeFormatter) throws SQLServerException { + addColumnMetadataInternal(positionInSource, name, jdbcType, precision, + scale, dateTimeFormatter); + } + + @Override + public void addColumnMetadata(int positionInSource, String name, + int jdbcType, int precision, int scale) throws SQLServerException { + addColumnMetadataInternal(positionInSource, name, jdbcType, precision, + scale, null); + } + + /** + * Adds metadata for the given column in the batch/file. + * + * @param positionInSource + * Indicates which column the metadata is for. Columns start at + * 1. + * @param name + * Name for the column (optional if only using column ordinal in + * a mapping for SQLServerBulkCopy operation) + * @param jdbcType + * JDBC data type of the column + * @param precision + * Precision for the column (ignored for the appropriate data + * types) + * @param scale + * Scale for the column (ignored for the appropriate data types) + * @param dateTimeFormatter + * format to parse data that is sent + * @throws SQLServerException + * when an error occurs + */ + void addColumnMetadataInternal(int positionInSource, String name, + int jdbcType, int precision, int scale, + DateTimeFormatter dateTimeFormatter) throws SQLServerException { + } + + @Override + public void setTimestampWithTimezoneFormat(String dateTimeFormat) { + this.dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat); + } + + @Override + public void setTimestampWithTimezoneFormat( + DateTimeFormatter dateTimeFormatter) { + this.dateTimeFormatter = dateTimeFormatter; + } + + @Override + public void setTimeWithTimezoneFormat(String timeFormat) { + this.timeFormatter = DateTimeFormatter.ofPattern(timeFormat); + } + + @Override + public void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) { + this.timeFormatter = dateTimeFormatter; + } + + /* + * Helper method to throw a SQLServerExeption with the invalidArgument + * message and given argument. + */ + protected void throwInvalidArgument(String argument) + throws SQLServerException { + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_invalidArgument")); + Object[] msgArgs = {argument}; + SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), + null, false); + } + + /* + * Method to throw a SQLServerExeption for duplicate column names + */ + protected void checkDuplicateColumnName(int positionInTable, String colName) + throws SQLServerException { + + if (null != colName && colName.trim().length() != 0) { + for (Entry entry : columnMetadata + .entrySet()) { + // duplicate check is not performed in case of same + // positionInTable value + if (null != entry && entry.getKey() != positionInTable) { + if (null != entry.getValue() && colName.trim() + .equalsIgnoreCase(entry.getValue().columnName)) { + throw new SQLServerException(SQLServerException + .getErrString("R_BulkDataDuplicateColumn"), + null); + } + } + } + } + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java index c5ad97c9a..9122c44fa 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java @@ -26,9 +26,12 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.text.MessageFormat; +import java.time.DateTimeException; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; @@ -46,6 +49,8 @@ import javax.sql.RowSet; +import microsoft.sql.DateTimeOffset; + /** * Lets you efficiently bulk load a SQL Server table with data from another source.
*
@@ -55,8 +60,13 @@ * The SQLServerBulkCopy class can be used to write data only to SQL Server tables. However, the data source is not limited to SQL Server; any data * source can be used, as long as the data can be read with a ResultSet or ISQLServerBulkRecord instance. */ -public class SQLServerBulkCopy implements java.lang.AutoCloseable { - /* +public class SQLServerBulkCopy implements java.lang.AutoCloseable, java.io.Serializable { + /** + * + */ + private static final long serialVersionUID = 1989903904654306244L; + + /* * Class to represent the column mappings between the source and destination table */ private class ColumnMapping { @@ -153,6 +163,11 @@ private class ColumnMapping { /* The CekTable for the destination table. */ private CekTable destCekTable = null; + /* Statement level encryption setting needed for querying against encrypted columns. */ + private SQLServerStatementColumnEncryptionSetting stmtColumnEncriptionSetting = SQLServerStatementColumnEncryptionSetting.UseConnectionSetting; + + private ResultSet destinationTableMetadata; + /* * Metadata for the destination table columns */ @@ -1490,7 +1505,12 @@ private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerExce if (null != destType && (destType.toLowerCase(Locale.ENGLISH).trim().startsWith("char") || destType.toLowerCase(Locale.ENGLISH).trim().startsWith("varchar"))) addCollate = " COLLATE " + columnCollation; } - bulkCmd.append("[" + colMapping.destinationColumnName + "] " + destType + addCollate + endColumn); + if (colMapping.destinationColumnName.contains("]")) { + String escapedColumnName = colMapping.destinationColumnName.replaceAll("]", "]]"); + bulkCmd.append("[" + escapedColumnName + "] " + destType + addCollate + endColumn); + } else { + bulkCmd.append("[" + colMapping.destinationColumnName + "] " + destType + addCollate + endColumn); + } } if (true == copyOptions.isCheckConstraints()) { @@ -1740,11 +1760,19 @@ private void getDestinationMetadata() throws SQLServerException { SQLServerResultSet rs = null; SQLServerResultSet rsMoreMetaData = null; - + SQLServerStatement stmt = null; + try { - // Get destination metadata - rs = ((SQLServerStatement) connection.createStatement()) - .executeQueryInternal("SET FMTONLY ON SELECT * FROM " + destinationTableName + " SET FMTONLY OFF "); + if (null != destinationTableMetadata) { + rs = (SQLServerResultSet) destinationTableMetadata; + } + else { + stmt = (SQLServerStatement) connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, + connection.getHoldability(), stmtColumnEncriptionSetting); + + // Get destination metadata + rs = stmt.executeQueryInternal("sp_executesql N'SET FMTONLY ON SELECT * FROM " + destinationTableName + " '"); + } destColumnCount = rs.getMetaData().getColumnCount(); destColumnMetadata = new HashMap<>(); @@ -1783,6 +1811,8 @@ private void getDestinationMetadata() throws SQLServerException { finally { if (null != rs) rs.close(); + if (null != stmt) + stmt.close(); if (null != rsMoreMetaData) rsMoreMetaData.close(); } @@ -3059,12 +3089,63 @@ protected Object getTemporalObjectFromCSVWithFormatter(String valueStrUntrimmed, int srcJdbcType, int srcColOrdinal, DateTimeFormatter dateTimeFormatter) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - SQLServerBulkCopy42Helper.getTemporalObjectFromCSVWithFormatter(valueStrUntrimmed, srcJdbcType, srcColOrdinal, dateTimeFormatter, connection, - this); - - return null; + try { + TemporalAccessor ta = dateTimeFormatter.parse(valueStrUntrimmed); + + int taHour, taMin, taSec, taYear, taMonth, taDay, taNano, taOffsetSec; + taHour = taMin = taSec = taYear = taMonth = taDay = taNano = taOffsetSec = 0; + if (ta.isSupported(ChronoField.NANO_OF_SECOND)) + taNano = ta.get(ChronoField.NANO_OF_SECOND); + if (ta.isSupported(ChronoField.OFFSET_SECONDS)) + taOffsetSec = ta.get(ChronoField.OFFSET_SECONDS); + if (ta.isSupported(ChronoField.HOUR_OF_DAY)) + taHour = ta.get(ChronoField.HOUR_OF_DAY); + if (ta.isSupported(ChronoField.MINUTE_OF_HOUR)) + taMin = ta.get(ChronoField.MINUTE_OF_HOUR); + if (ta.isSupported(ChronoField.SECOND_OF_MINUTE)) + taSec = ta.get(ChronoField.SECOND_OF_MINUTE); + if (ta.isSupported(ChronoField.DAY_OF_MONTH)) + taDay = ta.get(ChronoField.DAY_OF_MONTH); + if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) + taMonth = ta.get(ChronoField.MONTH_OF_YEAR); + if (ta.isSupported(ChronoField.YEAR)) + taYear = ta.get(ChronoField.YEAR); + + Calendar cal = new GregorianCalendar(new SimpleTimeZone(taOffsetSec * 1000, "")); + cal.clear(); + cal.set(Calendar.HOUR_OF_DAY, taHour); + cal.set(Calendar.MINUTE, taMin); + cal.set(Calendar.SECOND, taSec); + cal.set(Calendar.DATE, taDay); + cal.set(Calendar.MONTH, taMonth - 1); + cal.set(Calendar.YEAR, taYear); + int fractionalSecondsLength = Integer.toString(taNano).length(); + for (int i = 0; i < (9 - fractionalSecondsLength); i++) + taNano *= 10; + Timestamp ts = new Timestamp(cal.getTimeInMillis()); + ts.setNanos(taNano); + + switch (srcJdbcType) { + case java.sql.Types.TIMESTAMP: + return ts; + case java.sql.Types.TIME: + // Time is returned as Timestamp to preserve nano seconds. + cal.set(connection.baseYear(), Calendar.JANUARY, 01); + ts = new java.sql.Timestamp(cal.getTimeInMillis()); + ts.setNanos(taNano); + return new java.sql.Timestamp(ts.getTime()); + case java.sql.Types.DATE: + return new java.sql.Date(ts.getTime()); + case microsoft.sql.Types.DATETIMEOFFSET: + return DateTimeOffset.valueOf(ts, taOffsetSec / 60); + } + } + catch (DateTimeException | ArithmeticException e) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ParsingError")); + Object[] msgArgs = {JDBCType.of(srcJdbcType)}; + throw new SQLServerException(this, form.format(msgArgs), null, 0, false); + } + return valueStrUntrimmed; } private Object getTemporalObjectFromCSV(Object value, @@ -3573,4 +3654,12 @@ private boolean writeBatchData(TDSWriter tdsWriter, } } } + + protected void setStmtColumnEncriptionSetting(SQLServerStatementColumnEncryptionSetting stmtColumnEncriptionSetting) { + this.stmtColumnEncriptionSetting = stmtColumnEncriptionSetting; + } + + protected void setDestinationTableMetadata(SQLServerResultSet rs) { + destinationTableMetadata = rs; + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy42Helper.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy42Helper.java deleted file mode 100644 index ea9ff510f..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy42Helper.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.Timestamp; -import java.text.MessageFormat; -import java.time.DateTimeException; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoField; -import java.time.temporal.TemporalAccessor; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.SimpleTimeZone; - -import microsoft.sql.DateTimeOffset; - -/** - * - * This class is separated from SQLServerBulkCopy class to resolve run-time error of missing Java 8 types when running with Java 7 - * - */ -class SQLServerBulkCopy42Helper { - static Object getTemporalObjectFromCSVWithFormatter(String valueStrUntrimmed, - int srcJdbcType, - int srcColOrdinal, - DateTimeFormatter dateTimeFormatter, - SQLServerConnection connection, - SQLServerBulkCopy sqlServerBC) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - try { - TemporalAccessor ta = dateTimeFormatter.parse(valueStrUntrimmed); - - int taHour, taMin, taSec, taYear, taMonth, taDay, taNano, taOffsetSec; - taHour = taMin = taSec = taYear = taMonth = taDay = taNano = taOffsetSec = 0; - if (ta.isSupported(ChronoField.NANO_OF_SECOND)) - taNano = ta.get(ChronoField.NANO_OF_SECOND); - if (ta.isSupported(ChronoField.OFFSET_SECONDS)) - taOffsetSec = ta.get(ChronoField.OFFSET_SECONDS); - if (ta.isSupported(ChronoField.HOUR_OF_DAY)) - taHour = ta.get(ChronoField.HOUR_OF_DAY); - if (ta.isSupported(ChronoField.MINUTE_OF_HOUR)) - taMin = ta.get(ChronoField.MINUTE_OF_HOUR); - if (ta.isSupported(ChronoField.SECOND_OF_MINUTE)) - taSec = ta.get(ChronoField.SECOND_OF_MINUTE); - if (ta.isSupported(ChronoField.DAY_OF_MONTH)) - taDay = ta.get(ChronoField.DAY_OF_MONTH); - if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) - taMonth = ta.get(ChronoField.MONTH_OF_YEAR); - if (ta.isSupported(ChronoField.YEAR)) - taYear = ta.get(ChronoField.YEAR); - - Calendar cal = new GregorianCalendar(new SimpleTimeZone(taOffsetSec * 1000, "")); - cal.clear(); - cal.set(Calendar.HOUR_OF_DAY, taHour); - cal.set(Calendar.MINUTE, taMin); - cal.set(Calendar.SECOND, taSec); - cal.set(Calendar.DATE, taDay); - cal.set(Calendar.MONTH, taMonth - 1); - cal.set(Calendar.YEAR, taYear); - int fractionalSecondsLength = Integer.toString(taNano).length(); - for (int i = 0; i < (9 - fractionalSecondsLength); i++) - taNano *= 10; - Timestamp ts = new Timestamp(cal.getTimeInMillis()); - ts.setNanos(taNano); - - switch (srcJdbcType) { - case java.sql.Types.TIMESTAMP: - return ts; - case java.sql.Types.TIME: - // Time is returned as Timestamp to preserve nano seconds. - cal.set(connection.baseYear(), Calendar.JANUARY, 01); - ts = new java.sql.Timestamp(cal.getTimeInMillis()); - ts.setNanos(taNano); - return new java.sql.Timestamp(ts.getTime()); - case java.sql.Types.DATE: - return new java.sql.Date(ts.getTime()); - case microsoft.sql.Types.DATETIMEOFFSET: - return DateTimeOffset.valueOf(ts, taOffsetSec / 60); - } - } - catch (DateTimeException | ArithmeticException e) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ParsingError")); - Object[] msgArgs = {JDBCType.of(srcJdbcType)}; - throw new SQLServerException(sqlServerBC, form.format(msgArgs), null, 0, false); - } - // unreachable code. Need to do to compile from Eclipse. - return valueStrUntrimmed; - } -} \ No newline at end of file diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java index c30eab2fa..57da43fff 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java @@ -22,11 +22,10 @@ import java.sql.ResultSet; import java.sql.RowId; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; -import java.sql.Types; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Calendar; @@ -43,7 +42,7 @@ public class SQLServerCallableStatement extends SQLServerPreparedStatement implements ISQLServerCallableStatement { /** the call param names */ - private ArrayList paramNames; + private ArrayList parameterNames; /** Number of registered OUT parameters */ int nOutParams = 0; @@ -87,6 +86,7 @@ String getClassNameInternal() { super(connection, sql, nRSType, nRSConcur, stmtColEncSetting); } + @Override public void registerOutParameter(int index, int sqlType) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -343,7 +343,8 @@ boolean onRetValue(TDSReader tdsReader) throws SQLServerException { } } - /* L0 */ public void registerOutParameter(int index, + @Override + public void registerOutParameter(int index, int sqlType, String typeName) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -356,12 +357,12 @@ boolean onRetValue(TDSReader tdsReader) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } - /* L0 */ public void registerOutParameter(int index, + @Override + public void registerOutParameter(int index, int sqlType, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", - new Object[] {index, sqlType, scale}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType, scale}); checkClosed(); @@ -371,13 +372,13 @@ boolean onRetValue(TDSReader tdsReader) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } + @Override public void registerOutParameter(int index, int sqlType, int precision, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", - new Object[] {index, sqlType, scale, precision}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType, scale, precision}); checkClosed(); @@ -453,6 +454,7 @@ private Object getSQLXMLInternal(int parameterIndex) throws SQLServerException { return value; } + @Override public int getInt(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getInt", index); checkClosed(); @@ -461,14 +463,16 @@ public int getInt(int index) throws SQLServerException { return null != value ? value : 0; } - public int getInt(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getInt", sCol); + @Override + public int getInt(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getInt", parameterName); checkClosed(); - Integer value = (Integer) getValue(findColumn(sCol), JDBCType.INTEGER); + Integer value = (Integer) getValue(findColumn(parameterName), JDBCType.INTEGER); loggerExternal.exiting(getClassNameLogging(), "getInt", value); return null != value ? value : 0; } + @Override public String getString(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getString", index); checkClosed(); @@ -480,12 +484,13 @@ public String getString(int index) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "getString", value); return value; } - - public String getString(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getString", sCol); + + @Override + public String getString(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getString", parameterName); checkClosed(); String value = null; - Object objectValue = getValue(findColumn(sCol), JDBCType.CHAR); + Object objectValue = getValue(findColumn(parameterName), JDBCType.CHAR); if (null != objectValue) { value = objectValue.toString(); } @@ -493,6 +498,7 @@ public String getString(String sCol) throws SQLServerException { return value; } + @Override public final String getNString(int parameterIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNString", parameterIndex); checkClosed(); @@ -501,6 +507,7 @@ public final String getNString(int parameterIndex) throws SQLException { return value; } + @Override public final String getNString(String parameterName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNString", parameterName); checkClosed(); @@ -510,6 +517,7 @@ public final String getNString(String parameterName) throws SQLException { } @Deprecated + @Override public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -523,8 +531,9 @@ public BigDecimal getBigDecimal(int parameterIndex, } @Deprecated + @Override public BigDecimal getBigDecimal(String parameterName, - int scale) throws SQLException { + int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getBigDecimal", new Object[] {parameterName, scale}); checkClosed(); @@ -535,6 +544,7 @@ public BigDecimal getBigDecimal(String parameterName, return value; } + @Override public boolean getBoolean(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBoolean", index); checkClosed(); @@ -543,14 +553,16 @@ public boolean getBoolean(int index) throws SQLServerException { return null != value ? value : false; } - public boolean getBoolean(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBoolean", sCol); + @Override + public boolean getBoolean(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBoolean", parameterName); checkClosed(); - Boolean value = (Boolean) getValue(findColumn(sCol), JDBCType.BIT); + Boolean value = (Boolean) getValue(findColumn(parameterName), JDBCType.BIT); loggerExternal.exiting(getClassNameLogging(), "getBoolean", value); return null != value ? value : false; } + @Override public byte getByte(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getByte", index); checkClosed(); @@ -560,15 +572,17 @@ public byte getByte(int index) throws SQLServerException { return byteValue; } - public byte getByte(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getByte", sCol); + @Override + public byte getByte(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getByte", parameterName); checkClosed(); - Short shortValue = (Short) getValue(findColumn(sCol), JDBCType.TINYINT); + Short shortValue = (Short) getValue(findColumn(parameterName), JDBCType.TINYINT); byte byteValue = (null != shortValue) ? shortValue.byteValue() : 0; loggerExternal.exiting(getClassNameLogging(), "getByte", byteValue); return byteValue; } + @Override public byte[] getBytes(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBytes", index); checkClosed(); @@ -577,14 +591,16 @@ public byte[] getBytes(int index) throws SQLServerException { return value; } - public byte[] getBytes(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBytes", sCol); + @Override + public byte[] getBytes(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBytes", parameterName); checkClosed(); - byte[] value = (byte[]) getValue(findColumn(sCol), JDBCType.BINARY); + byte[] value = (byte[]) getValue(findColumn(parameterName), JDBCType.BINARY); loggerExternal.exiting(getClassNameLogging(), "getBytes", value); return value; } + @Override public Date getDate(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDate", index); checkClosed(); @@ -593,14 +609,16 @@ public Date getDate(int index) throws SQLServerException { return value; } - public Date getDate(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getDate", sCol); + @Override + public Date getDate(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getDate", parameterName); checkClosed(); - java.sql.Date value = (java.sql.Date) getValue(findColumn(sCol), JDBCType.DATE); + java.sql.Date value = (java.sql.Date) getValue(findColumn(parameterName), JDBCType.DATE); loggerExternal.exiting(getClassNameLogging(), "getDate", value); return value; } + @Override public Date getDate(int index, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -611,16 +629,18 @@ public Date getDate(int index, return value; } - public Date getDate(String sCol, + @Override + public Date getDate(String parameterName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "getDate", new Object[] {sCol, cal}); + loggerExternal.entering(getClassNameLogging(), "getDate", new Object[] {parameterName, cal}); checkClosed(); - java.sql.Date value = (java.sql.Date) getValue(findColumn(sCol), JDBCType.DATE, cal); + java.sql.Date value = (java.sql.Date) getValue(findColumn(parameterName), JDBCType.DATE, cal); loggerExternal.exiting(getClassNameLogging(), "getDate", value); return value; } + @Override public double getDouble(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDouble", index); checkClosed(); @@ -629,14 +649,16 @@ public double getDouble(int index) throws SQLServerException { return null != value ? value : 0; } - public double getDouble(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getDouble", sCol); + @Override + public double getDouble(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getDouble", parameterName); checkClosed(); - Double value = (Double) getValue(findColumn(sCol), JDBCType.DOUBLE); + Double value = (Double) getValue(findColumn(parameterName), JDBCType.DOUBLE); loggerExternal.exiting(getClassNameLogging(), "getDouble", value); return null != value ? value : 0; } + @Override public float getFloat(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", index); checkClosed(); @@ -645,15 +667,17 @@ public float getFloat(int index) throws SQLServerException { return null != value ? value : 0; } - public float getFloat(String sCol) throws SQLServerException { + @Override + public float getFloat(String parameterName) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getFloat", sCol); + loggerExternal.entering(getClassNameLogging(), "getFloat", parameterName); checkClosed(); - Float value = (Float) getValue(findColumn(sCol), JDBCType.REAL); + Float value = (Float) getValue(findColumn(parameterName), JDBCType.REAL); loggerExternal.exiting(getClassNameLogging(), "getFloat", value); return null != value ? value : 0; } + @Override public long getLong(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getLong", index); @@ -663,14 +687,16 @@ public long getLong(int index) throws SQLServerException { return null != value ? value : 0; } - public long getLong(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getLong", sCol); + @Override + public long getLong(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getLong", parameterName); checkClosed(); - Long value = (Long) getValue(findColumn(sCol), JDBCType.BIGINT); + Long value = (Long) getValue(findColumn(parameterName), JDBCType.BIGINT); loggerExternal.exiting(getClassNameLogging(), "getLong", value); return null != value ? value : 0; } + @Override public Object getObject(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getObject", index); @@ -681,6 +707,7 @@ public Object getObject(int index) throws SQLServerException { return value; } + @Override public T getObject(int index, Class type) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getObject", index); @@ -763,26 +790,30 @@ else if (type == Double.class) { return type.cast(returnValue); } - public Object getObject(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getObject", sCol); + @Override + public Object getObject(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getObject", parameterName); checkClosed(); - int parameterIndex = findColumn(sCol); - Object value = getValue(parameterIndex, getterGetParam(parameterIndex).getJdbcTypeSetByUser() != null - ? getterGetParam(parameterIndex).getJdbcTypeSetByUser() : getterGetParam(parameterIndex).getJdbcType()); + int parameterIndex = findColumn(parameterName); + Object value = getValue(parameterIndex, + getterGetParam(parameterIndex).getJdbcTypeSetByUser() != null ? getterGetParam(parameterIndex).getJdbcTypeSetByUser() + : getterGetParam(parameterIndex).getJdbcType()); loggerExternal.exiting(getClassNameLogging(), "getObject", value); return value; } - public T getObject(String sCol, + @Override + public T getObject(String parameterName, Class type) throws SQLException { - loggerExternal.entering(getClassNameLogging(), "getObject", sCol); + loggerExternal.entering(getClassNameLogging(), "getObject", parameterName); checkClosed(); - int parameterIndex = findColumn(sCol); + int parameterIndex = findColumn(parameterName); T value = getObject(parameterIndex, type); loggerExternal.exiting(getClassNameLogging(), "getObject", value); return value; } + @Override public short getShort(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getShort", index); @@ -792,14 +823,16 @@ public short getShort(int index) throws SQLServerException { return null != value ? value : 0; } - public short getShort(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getShort", sCol); + @Override + public short getShort(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getShort", parameterName); checkClosed(); - Short value = (Short) getValue(findColumn(sCol), JDBCType.SMALLINT); + Short value = (Short) getValue(findColumn(parameterName), JDBCType.SMALLINT); loggerExternal.exiting(getClassNameLogging(), "getShort", value); return null != value ? value : 0; } + @Override public Time getTime(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTime", index); @@ -809,14 +842,16 @@ public Time getTime(int index) throws SQLServerException { return value; } - public Time getTime(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getTime", sCol); + @Override + public Time getTime(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getTime", parameterName); checkClosed(); - java.sql.Time value = (java.sql.Time) getValue(findColumn(sCol), JDBCType.TIME); + java.sql.Time value = (java.sql.Time) getValue(findColumn(parameterName), JDBCType.TIME); loggerExternal.exiting(getClassNameLogging(), "getTime", value); return value; } + @Override public Time getTime(int index, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -827,16 +862,18 @@ public Time getTime(int index, return value; } - public Time getTime(String sCol, + @Override + public Time getTime(String parameterName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "getTime", new Object[] {sCol, cal}); + loggerExternal.entering(getClassNameLogging(), "getTime", new Object[] {parameterName, cal}); checkClosed(); - java.sql.Time value = (java.sql.Time) getValue(findColumn(sCol), JDBCType.TIME, cal); + java.sql.Time value = (java.sql.Time) getValue(findColumn(parameterName), JDBCType.TIME, cal); loggerExternal.exiting(getClassNameLogging(), "getTime", value); return value; } + @Override public Timestamp getTimestamp(int index) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getTimestamp", index); @@ -846,14 +883,16 @@ public Timestamp getTimestamp(int index) throws SQLServerException { return value; } - public Timestamp getTimestamp(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getTimestamp", sCol); + @Override + public Timestamp getTimestamp(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getTimestamp", parameterName); checkClosed(); - java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(sCol), JDBCType.TIMESTAMP); + java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(parameterName), JDBCType.TIMESTAMP); loggerExternal.exiting(getClassNameLogging(), "getTimestamp", value); return value; } + @Override public Timestamp getTimestamp(int index, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -864,6 +903,7 @@ public Timestamp getTimestamp(int index, return value; } + @Override public Timestamp getTimestamp(String name, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -874,16 +914,7 @@ public Timestamp getTimestamp(String name, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param index - * the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getDateTime(int index) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getDateTime", index); @@ -893,38 +924,16 @@ public Timestamp getDateTime(int index) throws SQLServerException { return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param sCol - * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the - * column - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ - public Timestamp getDateTime(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getDateTime", sCol); + @Override + public Timestamp getDateTime(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getDateTime", parameterName); checkClosed(); - java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(sCol), JDBCType.DATETIME); + java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(parameterName), JDBCType.DATETIME); loggerExternal.exiting(getClassNameLogging(), "getDateTime", value); return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does - * not store timezone information. - * - * @param index - * the first column is 1, the second is 2, ... - * @param cal - * the java.util.Calendar object to use in constructing the dateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getDateTime(int index, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -935,19 +944,7 @@ public Timestamp getDateTime(int index, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does - * not store timezone information. - * - * @param name - * the name of the column - * @param cal - * the java.util.Calendar object to use in constructing the dateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getDateTime(String name, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -958,16 +955,7 @@ public Timestamp getDateTime(String name, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param index - * the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getSmallDateTime(int index) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getSmallDateTime", index); @@ -977,36 +965,16 @@ public Timestamp getSmallDateTime(int index) throws SQLServerException { return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param sCol - * The name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ - public Timestamp getSmallDateTime(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getSmallDateTime", sCol); + @Override + public Timestamp getSmallDateTime(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getSmallDateTime", parameterName); checkClosed(); - java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(sCol), JDBCType.SMALLDATETIME); + java.sql.Timestamp value = (java.sql.Timestamp) getValue(findColumn(parameterName), JDBCType.SMALLDATETIME); loggerExternal.exiting(getClassNameLogging(), "getSmallDateTime", value); return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param index - * the first column is 1, the second is 2, ... - * @param cal - * the java.util.Calendar object to use in constructing the smalldateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getSmallDateTime(int index, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1017,16 +985,7 @@ public Timestamp getSmallDateTime(int index, return value; } - /** - * - * @param name - * The name of a column - * @param cal - * the java.util.Calendar object to use in constructing the smalldateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public Timestamp getSmallDateTime(String name, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1037,7 +996,8 @@ public Timestamp getSmallDateTime(String name, return value; } - public microsoft.sql.DateTimeOffset getDateTimeOffset(int index) throws SQLException { + @Override + public microsoft.sql.DateTimeOffset getDateTimeOffset(int index) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getDateTimeOffset", index); checkClosed(); @@ -1052,8 +1012,9 @@ public microsoft.sql.DateTimeOffset getDateTimeOffset(int index) throws SQLExcep return value; } - public microsoft.sql.DateTimeOffset getDateTimeOffset(String sCol) throws SQLException { - loggerExternal.entering(getClassNameLogging(), "getDateTimeOffset", sCol); + @Override + public microsoft.sql.DateTimeOffset getDateTimeOffset(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getDateTimeOffset", parameterName); checkClosed(); // DateTimeOffset is not supported with SQL Server versions earlier than Katmai @@ -1061,12 +1022,13 @@ public microsoft.sql.DateTimeOffset getDateTimeOffset(String sCol) throws SQLExc throw new SQLServerException(SQLServerException.getErrString("R_notSupported"), SQLState.DATA_EXCEPTION_NOT_SPECIFIC, DriverError.NOT_SET, null); - microsoft.sql.DateTimeOffset value = (microsoft.sql.DateTimeOffset) getValue(findColumn(sCol), JDBCType.DATETIMEOFFSET); + microsoft.sql.DateTimeOffset value = (microsoft.sql.DateTimeOffset) getValue(findColumn(parameterName), JDBCType.DATETIMEOFFSET); loggerExternal.exiting(getClassNameLogging(), "getDateTimeOffset", value); return value; } - /* L0 */ public boolean wasNull() throws SQLServerException { + @Override + public boolean wasNull() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "wasNull"); checkClosed(); boolean bWasNull = false; @@ -1077,213 +1039,124 @@ public microsoft.sql.DateTimeOffset getDateTimeOffset(String sCol) throws SQLExc return bWasNull; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. The - * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARCHAR values. - * The JDBC driver will do any necessary conversion from the database format into ASCII. - * - *

- * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method - * implicitly closes the stream. Also, a stream may return 0 when the method InputStream.available is called whether - * there is data available or not. - * - * @param paramIndex - * the first column is 1, the second is 2, ... - * @return a Java input stream that delivers the database column value as a stream of one-byte ASCII characters; if the value is SQL - * NULL, the value returned is null - * @throws SQLServerException - * if the columnIndex is not valid; if a database access error occurs or this method is called on a closed result set - */ - public final java.io.InputStream getAsciiStream(int paramIndex) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getAsciiStream", paramIndex); + @Override + public final java.io.InputStream getAsciiStream(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getAsciiStream", parameterIndex); checkClosed(); - InputStream value = (InputStream) getStream(paramIndex, StreamType.ASCII); + InputStream value = (InputStream) getStream(parameterIndex, StreamType.ASCII); loggerExternal.exiting(getClassNameLogging(), "getAsciiStream", value); return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. The - * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARCHAR values. - * The JDBC driver will do any necessary conversion from the database format into ASCII. - * - *

- * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method - * implicitly closes the stream. Also, a stream may return 0 when the method available is called whether there is data - * available or not. - * - * @param paramName - * the name of the parameter - * @return a Java input stream that delivers the database column value as a stream of one-byte ASCII characters. If the value is SQL - * NULL, the value returned is null. - * @throws SQLServerException - * if the columnLabel is not valid; if a database access error occurs or this method is called on a closed result set - */ - public final java.io.InputStream getAsciiStream(String paramName) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getAsciiStream", paramName); + @Override + public final java.io.InputStream getAsciiStream(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getAsciiStream", parameterName); checkClosed(); - InputStream value = (InputStream) getStream(findColumn(paramName), StreamType.ASCII); + InputStream value = (InputStream) getStream(findColumn(parameterName), StreamType.ASCII); loggerExternal.exiting(getClassNameLogging(), "getAsciiStream", value); return value; } - public BigDecimal getBigDecimal(int index) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBigDecimal", index); + @Override + public BigDecimal getBigDecimal(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBigDecimal", parameterIndex); checkClosed(); - BigDecimal value = (BigDecimal) getValue(index, JDBCType.DECIMAL); + BigDecimal value = (BigDecimal) getValue(parameterIndex, JDBCType.DECIMAL); loggerExternal.exiting(getClassNameLogging(), "getBigDecimal", value); return value; } - public BigDecimal getBigDecimal(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBigDecimal", sCol); + @Override + public BigDecimal getBigDecimal(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBigDecimal", parameterName); checkClosed(); - BigDecimal value = (BigDecimal) getValue(findColumn(sCol), JDBCType.DECIMAL); + BigDecimal value = (BigDecimal) getValue(findColumn(parameterName), JDBCType.DECIMAL); loggerExternal.exiting(getClassNameLogging(), "getBigDecimal", value); return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param index - * The zero-based ordinal of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ - public BigDecimal getMoney(int index) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getMoney", index); + @Override + public BigDecimal getMoney(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getMoney", parameterIndex); checkClosed(); - BigDecimal value = (BigDecimal) getValue(index, JDBCType.MONEY); + BigDecimal value = (BigDecimal) getValue(parameterIndex, JDBCType.MONEY); loggerExternal.exiting(getClassNameLogging(), "getMoney", value); return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param sCol - * The name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null. - * @throws SQLServerException - * when an error occurs - */ - public BigDecimal getMoney(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getMoney", sCol); + @Override + public BigDecimal getMoney(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getMoney", parameterName); checkClosed(); - BigDecimal value = (BigDecimal) getValue(findColumn(sCol), JDBCType.MONEY); + BigDecimal value = (BigDecimal) getValue(findColumn(parameterName), JDBCType.MONEY); loggerExternal.exiting(getClassNameLogging(), "getMoney", value); return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param index - * The zero-based ordinal of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ - public BigDecimal getSmallMoney(int index) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getSmallMoney", index); + @Override + public BigDecimal getSmallMoney(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getSmallMoney", parameterIndex); checkClosed(); - BigDecimal value = (BigDecimal) getValue(index, JDBCType.SMALLMONEY); + BigDecimal value = (BigDecimal) getValue(parameterIndex, JDBCType.SMALLMONEY); loggerExternal.exiting(getClassNameLogging(), "getSmallMoney", value); return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param sCol - * The name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null. - * @throws SQLServerException - * when an error occurs - */ - public BigDecimal getSmallMoney(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getSmallMoney", sCol); + @Override + public BigDecimal getSmallMoney(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getSmallMoney", parameterName); checkClosed(); - BigDecimal value = (BigDecimal) getValue(findColumn(sCol), JDBCType.SMALLMONEY); + BigDecimal value = (BigDecimal) getValue(findColumn(parameterName), JDBCType.SMALLMONEY); loggerExternal.exiting(getClassNameLogging(), "getSmallMoney", value); return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of uninterpreted bytes. The - * value can then be read in chunks from the stream. This method is particularly suitable for retrieving large LONGVARBINARY values. - * - *

- * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method - * implicitly closes the stream. Also, a stream may return 0 when the method InputStream.available is called whether - * there is data available or not. - * - * @param paramIndex - * the first column is 1, the second is 2, ... - * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the value is SQL NULL, - * the value returned is null - * @throws SQLServerException - * if the columnIndex is not valid; if a database access error occurs or this method is called on a closed result set - */ - public final java.io.InputStream getBinaryStream(int paramIndex) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBinaryStream", paramIndex); + @Override + public final java.io.InputStream getBinaryStream(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBinaryStream", parameterIndex); checkClosed(); - InputStream value = (InputStream) getStream(paramIndex, StreamType.BINARY); + InputStream value = (InputStream) getStream(parameterIndex, StreamType.BINARY); loggerExternal.exiting(getClassNameLogging(), "getBinaryStream", value); return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of uninterpreted - * bytes. The value can then be read in chunks from the stream. This method is particularly suitable for retrieving large - * LONGVARBINARY values. - * - *

- * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next call to a getter method - * implicitly closes the stream. Also, a stream may return 0 when the method available is called whether there is data - * available or not. - * - * @param paramName - * the name of the parameter - * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the value is SQL NULL, - * the result is null - * @throws SQLServerException - * if the columnLabel is not valid; if a database access error occurs or this method is called on a closed result set - */ - public final java.io.InputStream getBinaryStream(String paramName) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBinaryStream", paramName); + @Override + public final java.io.InputStream getBinaryStream(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBinaryStream", parameterName); checkClosed(); - InputStream value = (InputStream) getStream(findColumn(paramName), StreamType.BINARY); + InputStream value = (InputStream) getStream(findColumn(parameterName), StreamType.BINARY); loggerExternal.exiting(getClassNameLogging(), "getBinaryStream", value); return value; } - public Blob getBlob(int index) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBlob", index); + @Override + public Blob getBlob(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBlob", parameterIndex); checkClosed(); - Blob value = (Blob) getValue(index, JDBCType.BLOB); + Blob value = (Blob) getValue(parameterIndex, JDBCType.BLOB); loggerExternal.exiting(getClassNameLogging(), "getBlob", value); return value; } - public Blob getBlob(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getBlob", sCol); + @Override + public Blob getBlob(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getBlob", parameterName); checkClosed(); - Blob value = (Blob) getValue(findColumn(sCol), JDBCType.BLOB); + Blob value = (Blob) getValue(findColumn(parameterName), JDBCType.BLOB); loggerExternal.exiting(getClassNameLogging(), "getBlob", value); return value; } - public final java.io.Reader getCharacterStream(int paramIndex) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getCharacterStream", paramIndex); + @Override + public final java.io.Reader getCharacterStream(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getCharacterStream", parameterIndex); checkClosed(); - Reader reader = (Reader) getStream(paramIndex, StreamType.CHARACTER); + Reader reader = (Reader) getStream(parameterIndex, StreamType.CHARACTER); loggerExternal.exiting(getClassNameLogging(), "getCharacterStream", reader); return reader; } + @Override public final java.io.Reader getCharacterStream(String parameterName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getCharacterStream", parameterName); checkClosed(); @@ -1292,6 +1165,7 @@ public final java.io.Reader getCharacterStream(String parameterName) throws SQLE return reader; } + @Override public final java.io.Reader getNCharacterStream(int parameterIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNCharacterStream", parameterIndex); checkClosed(); @@ -1300,6 +1174,7 @@ public final java.io.Reader getNCharacterStream(int parameterIndex) throws SQLEx return reader; } + @Override public final java.io.Reader getNCharacterStream(String parameterName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNCharacterStream", parameterName); checkClosed(); @@ -1322,22 +1197,25 @@ void closeActiveStream() throws SQLServerException { } } - public Clob getClob(int index) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getClob", index); + @Override + public Clob getClob(int parameterIndex) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getClob", parameterIndex); checkClosed(); - Clob clob = (Clob) getValue(index, JDBCType.CLOB); + Clob clob = (Clob) getValue(parameterIndex, JDBCType.CLOB); loggerExternal.exiting(getClassNameLogging(), "getClob", clob); return clob; } - public Clob getClob(String sCol) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "getClob", sCol); + @Override + public Clob getClob(String parameterName) throws SQLServerException { + loggerExternal.entering(getClassNameLogging(), "getClob", parameterName); checkClosed(); - Clob clob = (Clob) getValue(findColumn(sCol), JDBCType.CLOB); + Clob clob = (Clob) getValue(findColumn(parameterName), JDBCType.CLOB); loggerExternal.exiting(getClassNameLogging(), "getClob", clob); return clob; } + @Override public NClob getNClob(int parameterIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNClob", parameterIndex); checkClosed(); @@ -1346,6 +1224,7 @@ public NClob getNClob(int parameterIndex) throws SQLException { return nClob; } + @Override public NClob getNClob(String parameterName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNClob", parameterName); checkClosed(); @@ -1354,36 +1233,42 @@ public NClob getNClob(String parameterName) throws SQLException { return nClob; } - /* L0 */ public Object getObject(int index, - java.util.Map> map) throws SQLServerException { - NotImplemented(); + @Override + public Object getObject(int parameterIndex, + java.util.Map> map) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); return null; } - /* L3 */ public Object getObject(String sCol, - java.util.Map> m) throws SQLServerException { + @Override + public Object getObject(String parameterName, + java.util.Map> m) throws SQLException { checkClosed(); - return getObject(findColumn(sCol), m); + return getObject(findColumn(parameterName), m); } - /* L0 */ public Ref getRef(int i) throws SQLServerException { - NotImplemented(); + @Override + public Ref getRef(int parameterIndex) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); return null; } - /* L3 */ public Ref getRef(String sCol) throws SQLServerException { + @Override + public Ref getRef(String parameterName) throws SQLException { checkClosed(); - return getRef(findColumn(sCol)); + return getRef(findColumn(parameterName)); } - /* L0 */ public java.sql.Array getArray(int i) throws SQLServerException { - NotImplemented(); + @Override + public java.sql.Array getArray(int parameterIndex) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); return null; } - /* L3 */ public java.sql.Array getArray(String sCol) throws SQLServerException { + @Override + public java.sql.Array getArray(String parameterName) throws SQLException { checkClosed(); - return getArray(findColumn(sCol)); + return getArray(findColumn(parameterName)); } /* JDBC 3.0 */ @@ -1397,14 +1282,13 @@ public NClob getNClob(String parameterName) throws SQLException { * when an error occurs * @return the index */ - /* L3 */ private int findColumn(String columnName) throws SQLServerException { - if (paramNames == null) { - SQLServerStatement s = null; - try { + private int findColumn(String columnName) throws SQLServerException { + if (parameterNames == null) { + try (SQLServerStatement s = (SQLServerStatement) connection.createStatement()) { // Note we are concatenating the information from the passed in sql, not any arguments provided by the user // if the user can execute the sql, any fragments of it is potentially executed via the meta data call through injection // is not a security issue. - s = (SQLServerStatement) connection.createStatement(); + ThreePartName threePartName = ThreePartName.parse(procedureName); StringBuilder metaQuery = new StringBuilder("exec sp_sproc_columns "); if (null != threePartName.getDatabasePart()) { @@ -1424,7 +1308,7 @@ public NClob getNClob(String parameterName) throws SQLException { metaQuery.append(" , @ODBCVer=3"); } else { - // This should rarely happen, this will only happen if we cant find the stored procedure name + // This should rarely happen, this will only happen if we can't find the stored procedure name // invalidly formatted call syntax. MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_parameterNotDefinedForProcedure")); Object[] msgArgs = {columnName, ""}; @@ -1432,36 +1316,34 @@ public NClob getNClob(String parameterName) throws SQLException { } ResultSet rs = s.executeQueryInternal(metaQuery.toString()); - paramNames = new ArrayList<>(); + parameterNames = new ArrayList<>(); while (rs.next()) { - String sCol = rs.getString(4); - paramNames.add(sCol.trim()); + String parameterName = rs.getString(4); + parameterNames.add(parameterName.trim()); } } catch (SQLException e) { SQLServerException.makeFromDriverError(connection, this, e.toString(), null, false); } - finally { - if (null != s) - s.close(); - } + } int l = 0; - if (paramNames != null) - l = paramNames.size(); - if (l == 0)//Server didn't return anything, user might not have access - return 1;//attempting to look up the first column will return no access exception + if (parameterNames != null) + l = parameterNames.size(); + if (l == 0)// Server didn't return anything, user might not have access + return 1;// attempting to look up the first column will return no access exception - // handle `@name` as well as `name`, since `@name` is what's returned + // handle `@name` as well as `name`, since `@name` is what's returned // by DatabaseMetaData#getProcedureColumns String columnNameWithoutAtSign = null; if (columnName.startsWith("@")) { columnNameWithoutAtSign = columnName.substring(1, columnName.length()); - } else { + } + else { columnNameWithoutAtSign = columnName; } - + // In order to be as accurate as possible when locating parameter name // indexes, as well as be deterministic when running on various client // locales, we search for parameter names using the following scheme: @@ -1474,7 +1356,7 @@ public NClob getNClob(String parameterName) throws SQLException { // Search using case-sensitive, non-locale specific (binary) compare. // If the user supplies a true match for the parameter name, we will find it here. for (i = 0; i < l; i++) { - String sParam = paramNames.get(i); + String sParam = parameterNames.get(i); sParam = sParam.substring(1, sParam.length()); if (sParam.equals(columnNameWithoutAtSign)) { matchPos = i; @@ -1486,7 +1368,7 @@ public NClob getNClob(String parameterName) throws SQLException { // Check for case-insensitive match using a non-locale aware method. // Use VM supplied String.equalsIgnoreCase to do the "case-insensitive search". for (i = 0; i < l; i++) { - String sParam = paramNames.get(i); + String sParam = parameterNames.get(i); sParam = sParam.substring(1, sParam.length()); if (sParam.equalsIgnoreCase(columnNameWithoutAtSign)) { matchPos = i; @@ -1500,6 +1382,7 @@ public NClob getNClob(String parameterName) throws SQLException { Object[] msgArgs = {columnName, procedureName}; SQLServerException.makeFromDriverError(connection, this, form.format(msgArgs), "07009", false); } + // @RETURN_VALUE is always in the list. If the user uses return value ?=call(@p1) syntax then // @p1 is index 2 otherwise its index 1. if (bReturnValueSyntax) // 3.2717 @@ -1508,130 +1391,76 @@ public NClob getNClob(String parameterName) throws SQLException { return matchPos; } - public void setTimestamp(String sCol, - java.sql.Timestamp x, - Calendar c) throws SQLServerException { + @Override + public void setTimestamp(String parameterName, + java.sql.Timestamp value, + Calendar calendar) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTimeStamp", new Object[] {sCol, x, c}); + loggerExternal.entering(getClassNameLogging(), "setTimeStamp", new Object[] {parameterName, value, calendar}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIMESTAMP, x, JavaType.TIMESTAMP, c, false); + setValue(findColumn(parameterName), JDBCType.TIMESTAMP, value, JavaType.TIMESTAMP, calendar, false); loggerExternal.exiting(getClassNameLogging(), "setTimeStamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @param c - * a java.util.Calendar - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTimestamp - */ - public void setTimestamp(String sCol, - java.sql.Timestamp x, - Calendar c, + @Override + public void setTimestamp(String parameterName, + java.sql.Timestamp value, + Calendar calendar, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTimeStamp", new Object[] {sCol, x, c, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setTimeStamp", new Object[] {parameterName, value, calendar, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIMESTAMP, x, JavaType.TIMESTAMP, c, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.TIMESTAMP, value, JavaType.TIMESTAMP, calendar, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setTimeStamp"); } - public void setTime(String sCol, - java.sql.Time x, - Calendar c) throws SQLServerException { + @Override + public void setTime(String parameterName, + java.sql.Time value, + Calendar calendar) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {sCol, x, c}); + loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {parameterName, value, calendar}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIME, x, JavaType.TIME, c, false); + setValue(findColumn(parameterName), JDBCType.TIME, value, JavaType.TIME, calendar, false); loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value, using the given Calendar object. The driver uses the - * Calendar object to construct an SQL TIME value, which the driver then sends to the database. With a a - * Calendar object, the driver can calculate the time taking into account a custom timezone. If no Calendar object is - * specified, the driver uses the default timezone, which is that of the virtual machine running the application. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @param c - * the Calendar object the driver will use to construct the time - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTime - */ - public void setTime(String sCol, - java.sql.Time x, - Calendar c, + @Override + public void setTime(String parameterName, + java.sql.Time value, + Calendar calendar, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {sCol, x, c, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {parameterName, value, calendar, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIME, x, JavaType.TIME, c, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.TIME, value, JavaType.TIME, calendar, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setTime"); } - public void setDate(String sCol, - java.sql.Date x, - Calendar c) throws SQLServerException { + @Override + public void setDate(String parameterName, + java.sql.Date value, + Calendar calendar) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {sCol, x, c}); + loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {parameterName, value, calendar}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATE, x, JavaType.DATE, c, false); + setValue(findColumn(parameterName), JDBCType.DATE, value, JavaType.DATE, calendar, false); loggerExternal.exiting(getClassNameLogging(), "setDate"); } - /** - * Sets the designated parameter to the given java.sql.Date value, using the given Calendar object. The driver uses the - * Calendar object to construct an SQL DATE value, which the driver then sends to the database. With a a - * Calendar object, the driver can calculate the date taking into account a custom timezone. If no Calendar object is - * specified, the driver uses the default timezone, which is that of the virtual machine running the application. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @param c - * the Calendar object the driver will use to construct the date - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getDate - */ - public void setDate(String sCol, - java.sql.Date x, - Calendar c, + @Override + public void setDate(String parameterName, + java.sql.Date value, + Calendar calendar, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {sCol, x, c, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {parameterName, value, calendar, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATE, x, JavaType.DATE, c, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.DATE, value, JavaType.DATE, calendar, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setDate"); } + @Override public final void setCharacterStream(String parameterName, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1641,6 +1470,7 @@ public final void setCharacterStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setCharacterStream(String parameterName, Reader value, int length) throws SQLException { @@ -1651,6 +1481,7 @@ public final void setCharacterStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { @@ -1662,6 +1493,7 @@ public final void setCharacterStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setNCharacterStream(String parameterName, Reader value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1671,6 +1503,7 @@ public final void setNCharacterStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNCharacterStream"); } + @Override public final void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { @@ -1681,15 +1514,17 @@ public final void setNCharacterStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNCharacterStream"); } + @Override public final void setClob(String parameterName, - Clob x) throws SQLException { + Clob value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setClob", new Object[] {parameterName, x}); + loggerExternal.entering(getClassNameLogging(), "setClob", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(parameterName), JDBCType.CLOB, x, JavaType.CLOB, false); + setValue(findColumn(parameterName), JDBCType.CLOB, value, JavaType.CLOB, false); loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setClob(String parameterName, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1699,6 +1534,7 @@ public final void setClob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setClob(String parameterName, Reader value, long length) throws SQLException { @@ -1709,6 +1545,7 @@ public final void setClob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setNClob(String parameterName, NClob value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1718,6 +1555,7 @@ public final void setNClob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } + @Override public final void setNClob(String parameterName, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1727,6 +1565,7 @@ public final void setNClob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } + @Override public final void setNClob(String parameterName, Reader reader, long length) throws SQLException { @@ -1737,6 +1576,7 @@ public final void setNClob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } + @Override public final void setNString(String parameterName, String value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1746,26 +1586,10 @@ public final void setNString(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNString"); } - /** - * Sets the designated parameter to the given String object. The driver converts this to a SQL NCHAR or - * NVARCHAR or LONGNVARCHAR - * - * @param parameterName - * the name of the parameter to be set - * @param value - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * if parameterName does not correspond to a named parameter; if the driver does not support national character sets; if the driver - * can detect that a data conversion error could occur; if a database access error occurs or this method is called on a closed - * CallableStatement - */ + @Override public final void setNString(String parameterName, String value, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setNString", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); @@ -1773,131 +1597,77 @@ public final void setNString(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setNString"); } - public void setObject(String sCol, - Object o) throws SQLServerException { + @Override + public void setObject(String parameterName, + Object value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, o}); + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value}); checkClosed(); - setObjectNoType(findColumn(sCol), o, false); + setObjectNoType(findColumn(parameterName), value, false); loggerExternal.exiting(getClassNameLogging(), "setObject"); } - public void setObject(String sCol, - Object o, - int n) throws SQLServerException { + @Override + public void setObject(String parameterName, + Object value, + int sqlType) throws SQLServerException { String tvpName = null; if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, o, n}); + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, sqlType}); checkClosed(); - if (microsoft.sql.Types.STRUCTURED == n) { - tvpName = getTVPNameIfNull(findColumn(sCol), null); - setObject(setterGetParam(findColumn(sCol)), o, JavaType.TVP, JDBCType.TVP, null, null, false, findColumn(sCol), tvpName); + if (microsoft.sql.Types.STRUCTURED == sqlType) { + tvpName = getTVPNameIfNull(findColumn(parameterName), null); + setObject(setterGetParam(findColumn(parameterName)), value, JavaType.TVP, JDBCType.TVP, null, null, false, findColumn(parameterName), + tvpName); } else - setObject(setterGetParam(findColumn(sCol)), o, JavaType.of(o), JDBCType.of(n), null, null, false, findColumn(sCol), tvpName); + setObject(setterGetParam(findColumn(parameterName)), value, JavaType.of(value), JDBCType.of(sqlType), null, null, false, + findColumn(parameterName), tvpName); loggerExternal.exiting(getClassNameLogging(), "setObject"); } - public void setObject(String sCol, - Object o, - int n, - int m) throws SQLServerException { + @Override + public void setObject(String parameterName, + Object value, + int sqlType, + int decimals) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, o, n, m}); + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, sqlType, decimals}); checkClosed(); - - setObject(setterGetParam(findColumn(sCol)), o, JavaType.of(o), JDBCType.of(n), m, null, false, findColumn(sCol), null); - + setObject(setterGetParam(findColumn(parameterName)), value, JavaType.of(value), JDBCType.of(sqlType), decimals, null, false, + findColumn(parameterName), null); loggerExternal.exiting(getClassNameLogging(), "setObject"); } - /** - * Sets the value of the designated parameter with the given object. - * - *

- * The given Java object will be converted to the given targetSqlType before being sent to the database. - * - * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method - * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing - * Ref, Blob, Clob, NClob, Struct, java.net.URL, or - * Array, the driver should pass it to the database as a value of the corresponding SQL type. - *

- * Note that this method may be used to pass datatabase- specific abstract data types. - * - * @param sCol - * the name of the parameter - * @param o - * the object containing the input parameter value - * @param n - * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. - * @param m - * for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types, this is the number of digits after the decimal point. For all other - * types, this value will be ignored. - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see Types - * @see #getObject - */ - public void setObject(String sCol, - Object o, - int n, - int m, + @Override + public void setObject(String parameterName, + Object value, + int sqlType, + int decimals, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, o, n, m, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, sqlType, decimals, forceEncrypt}); checkClosed(); // scale - for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types, // this is the number of digits after the decimal point. // For all other types, this value will be ignored. - setObject(setterGetParam(findColumn(sCol)), o, JavaType.of(o), JDBCType.of(n), - (java.sql.Types.NUMERIC == n || java.sql.Types.DECIMAL == n) ? m : null, null, forceEncrypt, findColumn(sCol), null); + setObject(setterGetParam(findColumn(parameterName)), value, JavaType.of(value), JDBCType.of(sqlType), + (java.sql.Types.NUMERIC == sqlType || java.sql.Types.DECIMAL == sqlType) ? decimals : null, null, forceEncrypt, + findColumn(parameterName), null); loggerExternal.exiting(getClassNameLogging(), "setObject"); } - /** - * Sets the value of the designated parameter with the given object. - * - *

- * The given Java object will be converted to the given targetSqlType before being sent to the database. - * - * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method - * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing - * Ref, Blob, Clob, NClob, Struct, java.net.URL, or - * Array, the driver should pass it to the database as a value of the corresponding SQL type. - *

- * Note that this method may be used to pass datatabase- specific abstract data types. - * - * @param sCol - * the name of the parameter - * @param x - * the object containing the input parameter value - * @param targetSqlType - * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. - * @param precision - * the precision of the column. - * @param scale - * the scale of the column. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see Types - * @see #getObject - */ - public final void setObject(String sCol, - Object x, + @Override + public final void setObject(String parameterName, + Object value, int targetSqlType, Integer precision, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, x, targetSqlType, precision, scale}); + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, targetSqlType, precision, scale}); checkClosed(); // scale - for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types, @@ -1905,23 +1675,25 @@ public final void setObject(String sCol, // InputStream and Reader, this is the length of the data in the stream or reader. // For all other types, this value will be ignored. - setObject(setterGetParam(findColumn(sCol)), x, JavaType.of(x), - JDBCType.of(targetSqlType), (java.sql.Types.NUMERIC == targetSqlType || java.sql.Types.DECIMAL == targetSqlType - || InputStream.class.isInstance(x) || Reader.class.isInstance(x)) ? scale : null, - precision, false, findColumn(sCol), null); + setObject(setterGetParam(findColumn(parameterName)), value, JavaType.of(value), JDBCType.of(targetSqlType), + (java.sql.Types.NUMERIC == targetSqlType || java.sql.Types.DECIMAL == targetSqlType || InputStream.class.isInstance(value) + || Reader.class.isInstance(value)) ? scale : null, + precision, false, findColumn(parameterName), null); loggerExternal.exiting(getClassNameLogging(), "setObject"); } + @Override public final void setAsciiStream(String parameterName, - InputStream x) throws SQLException { + InputStream value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setAsciiStream", new Object[] {parameterName, x}); + loggerExternal.entering(getClassNameLogging(), "setAsciiStream", new Object[] {parameterName, value}); checkClosed(); - setStream(findColumn(parameterName), StreamType.ASCII, x, JavaType.INPUTSTREAM, DataTypes.UNKNOWN_STREAM_LENGTH); + setStream(findColumn(parameterName), StreamType.ASCII, value, JavaType.INPUTSTREAM, DataTypes.UNKNOWN_STREAM_LENGTH); loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } + @Override public final void setAsciiStream(String parameterName, InputStream value, int length) throws SQLException { @@ -1932,26 +1704,29 @@ public final void setAsciiStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } + @Override public final void setAsciiStream(String parameterName, - InputStream x, + InputStream value, long length) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setAsciiStream", new Object[] {parameterName, x, length}); + loggerExternal.entering(getClassNameLogging(), "setAsciiStream", new Object[] {parameterName, value, length}); checkClosed(); - setStream(findColumn(parameterName), StreamType.ASCII, x, JavaType.INPUTSTREAM, length); + setStream(findColumn(parameterName), StreamType.ASCII, value, JavaType.INPUTSTREAM, length); loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } + @Override public final void setBinaryStream(String parameterName, - InputStream x) throws SQLException { + InputStream value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBinaryStream", new Object[] {parameterName, x}); + loggerExternal.entering(getClassNameLogging(), "setBinaryStream", new Object[] {parameterName, value}); checkClosed(); - setStream(findColumn(parameterName), StreamType.BINARY, x, JavaType.INPUTSTREAM, DataTypes.UNKNOWN_STREAM_LENGTH); + setStream(findColumn(parameterName), StreamType.BINARY, value, JavaType.INPUTSTREAM, DataTypes.UNKNOWN_STREAM_LENGTH); loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBinaryStream(String parameterName, InputStream value, int length) throws SQLException { @@ -1962,16 +1737,18 @@ public final void setBinaryStream(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBinaryStream(String parameterName, - InputStream x, + InputStream value, long length) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBinaryStream", new Object[] {parameterName, x, length}); + loggerExternal.entering(getClassNameLogging(), "setBinaryStream", new Object[] {parameterName, value, length}); checkClosed(); - setStream(findColumn(parameterName), StreamType.BINARY, x, JavaType.INPUTSTREAM, length); + setStream(findColumn(parameterName), StreamType.BINARY, value, JavaType.INPUTSTREAM, length); loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBlob(String parameterName, Blob inputStream) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1981,9 +1758,9 @@ public final void setBlob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } + @Override public final void setBlob(String parameterName, InputStream value) throws SQLException { - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setBlob", new Object[] {parameterName, value}); checkClosed(); @@ -1991,6 +1768,7 @@ public final void setBlob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } + @Override public final void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { @@ -2001,928 +1779,525 @@ public final void setBlob(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } - public void setTimestamp(String sCol, - java.sql.Timestamp t) throws SQLServerException { + @Override + public void setTimestamp(String parameterName, + java.sql.Timestamp value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIMESTAMP, t, JavaType.TIMESTAMP, false); + setValue(findColumn(parameterName), JDBCType.TIMESTAMP, value, JavaType.TIMESTAMP, false); loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param t - * the parameter value - * @param scale - * the scale of the parameter - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTimestamp - */ - public void setTimestamp(String sCol, - java.sql.Timestamp t, + @Override + public void setTimestamp(String parameterName, + java.sql.Timestamp value, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIMESTAMP, t, JavaType.TIMESTAMP, null, scale, false); + setValue(findColumn(parameterName), JDBCType.TIMESTAMP, value, JavaType.TIMESTAMP, null, scale, false); loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param t - * the parameter value - * @param scale - * the scale of the parameter - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTimestamp - */ - public void setTimestamp(String sCol, - java.sql.Timestamp t, + @Override + public void setTimestamp(String parameterName, + java.sql.Timestamp value, int scale, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {sCol, t, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setTimestamp", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIMESTAMP, t, JavaType.TIMESTAMP, null, scale, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.TIMESTAMP, value, JavaType.TIMESTAMP, null, scale, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - public void setDateTimeOffset(String sCol, - microsoft.sql.DateTimeOffset t) throws SQLException { + @Override + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATETIMEOFFSET, t, JavaType.DATETIMEOFFSET, false); + setValue(findColumn(parameterName), JDBCType.DATETIMEOFFSET, value, JavaType.DATETIMEOFFSET, false); loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } - /** - * Sets parameter parameterName to DateTimeOffset x - * - * @param sCol - * the name of the parameter - * @param t - * DateTimeOffset value - * @param scale - * the scale of the parameter - * @throws SQLException - * if an error occurs - */ - public void setDateTimeOffset(String sCol, - microsoft.sql.DateTimeOffset t, - int scale) throws SQLException { + @Override + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value, + int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATETIMEOFFSET, t, JavaType.DATETIMEOFFSET, null, scale, false); + setValue(findColumn(parameterName), JDBCType.DATETIMEOFFSET, value, JavaType.DATETIMEOFFSET, null, scale, false); loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } - /** - * Sets parameter parameterName to DateTimeOffset x - * - * @param sCol - * the name of the parameter - * @param t - * DateTimeOffset value - * @param scale - * the scale of the parameter - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * if an error occurs - */ - public void setDateTimeOffset(String sCol, - microsoft.sql.DateTimeOffset t, + @Override + public void setDateTimeOffset(String parameterName, + microsoft.sql.DateTimeOffset value, int scale, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {sCol, t, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATETIMEOFFSET, t, JavaType.DATETIMEOFFSET, null, scale, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.DATETIMEOFFSET, value, JavaType.DATETIMEOFFSET, null, scale, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } - public void setDate(String sCol, - java.sql.Date d) throws SQLServerException { + @Override + public void setDate(String parameterName, + java.sql.Date value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {sCol, d}); + loggerExternal.entering(getClassNameLogging(), "setDate", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATE, d, JavaType.DATE, false); + setValue(findColumn(parameterName), JDBCType.DATE, value, JavaType.DATE, false); loggerExternal.exiting(getClassNameLogging(), "setDate"); } - public void setTime(String sCol, - java.sql.Time t) throws SQLServerException { + @Override + public void setTime(String parameterName, + java.sql.Time value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIME, t, JavaType.TIME, false); + setValue(findColumn(parameterName), JDBCType.TIME, value, JavaType.TIME, false); loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param t - * the parameter value - * @param scale - * the scale of the column - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTime - */ - public void setTime(String sCol, - java.sql.Time t, + @Override + public void setTime(String parameterName, + java.sql.Time value, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {sCol, t}); + loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIME, t, JavaType.TIME, null, scale, false); + setValue(findColumn(parameterName), JDBCType.TIME, value, JavaType.TIME, null, scale, false); loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param t - * the parameter value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - * @see #getTime - */ - public void setTime(String sCol, - java.sql.Time t, + @Override + public void setTime(String parameterName, + java.sql.Time value, int scale, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {sCol, t, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setTime", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TIME, t, JavaType.TIME, null, scale, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.TIME, value, JavaType.TIME, null, scale, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL DATETIME - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setDateTime(String sCol, - java.sql.Timestamp x) throws SQLServerException { + @Override + public void setDateTime(String parameterName, + java.sql.Timestamp value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDateTime", new Object[] {sCol, x}); + loggerExternal.entering(getClassNameLogging(), "setDateTime", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATETIME, x, JavaType.TIMESTAMP, false); + setValue(findColumn(parameterName), JDBCType.DATETIME, value, JavaType.TIMESTAMP, false); loggerExternal.exiting(getClassNameLogging(), "setDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL DATETIME - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setDateTime(String sCol, - java.sql.Timestamp x, + @Override + public void setDateTime(String parameterName, + java.sql.Timestamp value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDateTime", new Object[] {sCol, x, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setDateTime", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DATETIME, x, JavaType.TIMESTAMP, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.DATETIME, value, JavaType.TIMESTAMP, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL SMALLDATETIME - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setSmallDateTime(String sCol, - java.sql.Timestamp x) throws SQLServerException { + @Override + public void setSmallDateTime(String parameterName, + java.sql.Timestamp value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setSmallDateTime", new Object[] {sCol, x}); + loggerExternal.entering(getClassNameLogging(), "setSmallDateTime", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLDATETIME, x, JavaType.TIMESTAMP, false); + setValue(findColumn(parameterName), JDBCType.SMALLDATETIME, value, JavaType.TIMESTAMP, false); loggerExternal.exiting(getClassNameLogging(), "setSmallDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL SMALLDATETIME - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setSmallDateTime(String sCol, - java.sql.Timestamp x, + @Override + public void setSmallDateTime(String parameterName, + java.sql.Timestamp value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setSmallDateTime", new Object[] {sCol, x, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setSmallDateTime", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLDATETIME, x, JavaType.TIMESTAMP, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.SMALLDATETIME, value, JavaType.TIMESTAMP, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setSmallDateTime"); } - /** - * Sets the designated parameter to the given String value. The driver converts this to an SQL uniqueIdentifier value - * when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param guid - * the parameter value - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setUniqueIdentifier(String sCol, + @Override + public void setUniqueIdentifier(String parameterName, String guid) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setUniqueIdentifier", new Object[] {sCol, guid}); + loggerExternal.entering(getClassNameLogging(), "setUniqueIdentifier", new Object[] {parameterName, guid}); checkClosed(); - setValue(findColumn(sCol), JDBCType.GUID, guid, JavaType.STRING, false); + setValue(findColumn(parameterName), JDBCType.GUID, guid, JavaType.STRING, false); loggerExternal.exiting(getClassNameLogging(), "setUniqueIdentifier"); } - /** - * Sets the designated parameter to the given String value. The driver converts this to an SQL uniqueIdentifier value - * when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param guid - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setUniqueIdentifier(String sCol, + @Override + public void setUniqueIdentifier(String parameterName, String guid, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setUniqueIdentifier", new Object[] {sCol, guid, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setUniqueIdentifier", new Object[] {parameterName, guid, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.GUID, guid, JavaType.STRING, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.GUID, guid, JavaType.STRING, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setUniqueIdentifier"); } - public void setBytes(String sCol, - byte[] b) throws SQLServerException { + @Override + public void setBytes(String parameterName, + byte[] value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBytes", new Object[] {sCol, b}); + loggerExternal.entering(getClassNameLogging(), "setBytes", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BINARY, b, JavaType.BYTEARRAY, false); + setValue(findColumn(parameterName), JDBCType.BINARY, value, JavaType.BYTEARRAY, false); loggerExternal.exiting(getClassNameLogging(), "setBytes"); } - /** - * Sets the designated parameter to the given Java array of bytes. The driver converts this to an SQL VARBINARY or - * LONGVARBINARY (depending on the argument's size relative to the driver's limits on VARBINARY values) when it sends it - * to the database. - * - * @param sCol - * the name of the parameter - * @param b - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setBytes(String sCol, - byte[] b, + @Override + public void setBytes(String parameterName, + byte[] value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBytes", new Object[] {sCol, b, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setBytes", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BINARY, b, JavaType.BYTEARRAY, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.BINARY, value, JavaType.BYTEARRAY, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setBytes"); } - public void setByte(String sCol, - byte b) throws SQLServerException { + @Override + public void setByte(String parameterName, + byte value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setByte", new Object[] {sCol, b}); + loggerExternal.entering(getClassNameLogging(), "setByte", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TINYINT, b, JavaType.BYTE, false); + setValue(findColumn(parameterName), JDBCType.TINYINT, value, JavaType.BYTE, false); loggerExternal.exiting(getClassNameLogging(), "setByte"); } - /** - * Sets the designated parameter to the given Java byte value. The driver converts this to an SQL TINYINT value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param b - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setByte(String sCol, - byte b, + @Override + public void setByte(String parameterName, + byte value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setByte", new Object[] {sCol, b, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setByte", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TINYINT, b, JavaType.BYTE, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.TINYINT, value, JavaType.BYTE, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setByte"); } - public void setString(String sCol, - String s) throws SQLServerException { + @Override + public void setString(String parameterName, + String value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setString", new Object[] {sCol, s}); + loggerExternal.entering(getClassNameLogging(), "setString", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.VARCHAR, s, JavaType.STRING, false); + setValue(findColumn(parameterName), JDBCType.VARCHAR, value, JavaType.STRING, false); loggerExternal.exiting(getClassNameLogging(), "setString"); } - /** - * Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or - * LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends - * it to the database. - * - * @param sCol - * the name of the parameter - * @param s - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setString(String sCol, - String s, + @Override + public void setString(String parameterName, + String value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setString", new Object[] {sCol, s, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setString", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.VARCHAR, s, JavaType.STRING, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.VARCHAR, value, JavaType.STRING, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setString"); } - /** - * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL Money - * value. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setMoney(String sCol, - BigDecimal bd) throws SQLServerException { + @Override + public void setMoney(String parameterName, + BigDecimal value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setMoney", new Object[] {sCol, bd}); + loggerExternal.entering(getClassNameLogging(), "setMoney", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.MONEY, bd, JavaType.BIGDECIMAL, false); + setValue(findColumn(parameterName), JDBCType.MONEY, value, JavaType.BIGDECIMAL, false); loggerExternal.exiting(getClassNameLogging(), "setMoney"); } - /** - * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL Money - * value. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setMoney(String sCol, - BigDecimal bd, + @Override + public void setMoney(String parameterName, + BigDecimal value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setMoney", new Object[] {sCol, bd, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setMoney", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.MONEY, bd, JavaType.BIGDECIMAL, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.MONEY, value, JavaType.BIGDECIMAL, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setMoney"); } - /** - * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL - * smallMoney value. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setSmallMoney(String sCol, - BigDecimal bd) throws SQLServerException { + @Override + public void setSmallMoney(String parameterName, + BigDecimal value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setSmallMoney", new Object[] {sCol, bd}); + loggerExternal.entering(getClassNameLogging(), "setSmallMoney", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLMONEY, bd, JavaType.BIGDECIMAL, false); + setValue(findColumn(parameterName), JDBCType.SMALLMONEY, value, JavaType.BIGDECIMAL, false); loggerExternal.exiting(getClassNameLogging(), "setSmallMoney"); } - /** - * Sets the designated parameter to the given Java java.math.BigDecimal value. The driver converts this to an SQL - * smallMoney value. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setSmallMoney(String sCol, - BigDecimal bd, + @Override + public void setSmallMoney(String parameterName, + BigDecimal value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setSmallMoney", new Object[] {sCol, bd, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setSmallMoney", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLMONEY, bd, JavaType.BIGDECIMAL, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.SMALLMONEY, value, JavaType.BIGDECIMAL, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setSmallMoney"); } - public void setBigDecimal(String sCol, - BigDecimal bd) throws SQLServerException { + @Override + public void setBigDecimal(String parameterName, + BigDecimal value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {sCol, bd}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DECIMAL, bd, JavaType.BIGDECIMAL, false); + setValue(findColumn(parameterName), JDBCType.DECIMAL, value, JavaType.BIGDECIMAL, false); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setBigDecimal(String sCol, - BigDecimal bd, + @Override + public void setBigDecimal(String parameterName, + BigDecimal value, int precision, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {sCol, bd, precision, scale}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {parameterName, value, precision, scale}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DECIMAL, bd, JavaType.BIGDECIMAL, precision, scale, false); + setValue(findColumn(parameterName), JDBCType.DECIMAL, value, JavaType.BIGDECIMAL, precision, scale, false); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param bd - * the parameter value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setBigDecimal(String sCol, - BigDecimal bd, + @Override + public void setBigDecimal(String parameterName, + BigDecimal value, int precision, int scale, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {sCol, bd, precision, scale, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {parameterName, value, precision, scale, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DECIMAL, bd, JavaType.BIGDECIMAL, precision, scale, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.DECIMAL, value, JavaType.BIGDECIMAL, precision, scale, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - public void setDouble(String sCol, - double d) throws SQLServerException { + @Override + public void setDouble(String parameterName, + double value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDouble", new Object[] {sCol, d}); + loggerExternal.entering(getClassNameLogging(), "setDouble", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DOUBLE, d, JavaType.DOUBLE, false); + setValue(findColumn(parameterName), JDBCType.DOUBLE, value, JavaType.DOUBLE, false); loggerExternal.exiting(getClassNameLogging(), "setDouble"); } - /** - * Sets the designated parameter to the given Java double value. The driver converts this to an SQL DOUBLE value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param d - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setDouble(String sCol, - double d, + @Override + public void setDouble(String parameterName, + double value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setDouble", new Object[] {sCol, d, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setDouble", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.DOUBLE, d, JavaType.DOUBLE, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.DOUBLE, value, JavaType.DOUBLE, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setDouble"); } - public void setFloat(String sCol, - float f) throws SQLServerException { + @Override + public void setFloat(String parameterName, + float value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setFloat", new Object[] {sCol, f}); + loggerExternal.entering(getClassNameLogging(), "setFloat", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.REAL, f, JavaType.FLOAT, false); + setValue(findColumn(parameterName), JDBCType.REAL, value, JavaType.FLOAT, false); loggerExternal.exiting(getClassNameLogging(), "setFloat"); } - /** - * Sets the designated parameter to the given Java float value. The driver converts this to an SQL FLOAT value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param f - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setFloat(String sCol, - float f, + @Override + public void setFloat(String parameterName, + float value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setFloat", new Object[] {sCol, f, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setFloat", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.REAL, f, JavaType.FLOAT, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.REAL, value, JavaType.FLOAT, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setFloat"); } - public void setInt(String sCol, - int i) throws SQLServerException { + @Override + public void setInt(String parameterName, + int value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setInt", new Object[] {sCol, i}); + loggerExternal.entering(getClassNameLogging(), "setInt", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.INTEGER, i, JavaType.INTEGER, false); + setValue(findColumn(parameterName), JDBCType.INTEGER, value, JavaType.INTEGER, false); loggerExternal.exiting(getClassNameLogging(), "setInt"); } - /** - * Sets the designated parameter to the given Java int value. The driver converts this to an SQL INTEGER value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param i - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setInt(String sCol, - int i, + @Override + public void setInt(String parameterName, + int value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setInt", new Object[] {sCol, i, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setInt", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.INTEGER, i, JavaType.INTEGER, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.INTEGER, value, JavaType.INTEGER, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setInt"); } - public void setLong(String sCol, - long l) throws SQLServerException { + @Override + public void setLong(String parameterName, + long value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setLong", new Object[] {sCol, l}); + loggerExternal.entering(getClassNameLogging(), "setLong", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BIGINT, l, JavaType.LONG, false); + setValue(findColumn(parameterName), JDBCType.BIGINT, value, JavaType.LONG, false); loggerExternal.exiting(getClassNameLogging(), "setLong"); } - /** - * Sets the designated parameter to the given Java long value. The driver converts this to an SQL BIGINT value when it - * sends it to the database. - * - * @param sCol - * the name of the parameter - * @param l - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setLong(String sCol, - long l, + @Override + public void setLong(String parameterName, + long value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setLong", new Object[] {sCol, l, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setLong", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BIGINT, l, JavaType.LONG, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.BIGINT, value, JavaType.LONG, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setLong"); } - public void setShort(String sCol, - short s) throws SQLServerException { + @Override + public void setShort(String parameterName, + short value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setShort", new Object[] {sCol, s}); + loggerExternal.entering(getClassNameLogging(), "setShort", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLINT, s, JavaType.SHORT, false); + setValue(findColumn(parameterName), JDBCType.SMALLINT, value, JavaType.SHORT, false); loggerExternal.exiting(getClassNameLogging(), "setShort"); } - /** - * Sets the designated parameter to the given Java short value. The driver converts this to an SQL SMALLINT value when - * it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param s - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setShort(String sCol, - short s, + @Override + public void setShort(String parameterName, + short value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setShort", new Object[] {sCol, s, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setShort", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.SMALLINT, s, JavaType.SHORT, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.SMALLINT, value, JavaType.SHORT, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setShort"); } - public void setBoolean(String sCol, - boolean b) throws SQLServerException { + @Override + public void setBoolean(String parameterName, + boolean value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBoolean", new Object[] {sCol, b}); + loggerExternal.entering(getClassNameLogging(), "setBoolean", new Object[] {parameterName, value}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BIT, b, JavaType.BOOLEAN, false); + setValue(findColumn(parameterName), JDBCType.BIT, value, JavaType.BOOLEAN, false); loggerExternal.exiting(getClassNameLogging(), "setBoolean"); } - /** - * Sets the designated parameter to the given Java boolean value. The driver converts this to an SQL BIT or - * BOOLEAN value when it sends it to the database. - * - * @param sCol - * the name of the parameter - * @param b - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * if parameterName does not correspond to a named parameter; if a database access error occurs or this method is called on a closed - * CallableStatement - */ - public void setBoolean(String sCol, - boolean b, + @Override + public void setBoolean(String parameterName, + boolean value, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBoolean", new Object[] {sCol, b, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setBoolean", new Object[] {parameterName, value, forceEncrypt}); checkClosed(); - setValue(findColumn(sCol), JDBCType.BIT, b, JavaType.BOOLEAN, forceEncrypt); + setValue(findColumn(parameterName), JDBCType.BIT, value, JavaType.BOOLEAN, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setBoolean"); } - public void setNull(String sCol, + @Override + public void setNull(String parameterName, int nType) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setNull", new Object[] {sCol, nType}); + loggerExternal.entering(getClassNameLogging(), "setNull", new Object[] {parameterName, nType}); checkClosed(); - setObject(setterGetParam(findColumn(sCol)), null, JavaType.OBJECT, JDBCType.of(nType), null, null, false, findColumn(sCol), null); + setObject(setterGetParam(findColumn(parameterName)), null, JavaType.OBJECT, JDBCType.of(nType), null, null, false, findColumn(parameterName), + null); loggerExternal.exiting(getClassNameLogging(), "setNull"); } - public void setNull(String sCol, + @Override + public void setNull(String parameterName, int nType, String sTypeName) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setNull", new Object[] {sCol, nType, sTypeName}); + loggerExternal.entering(getClassNameLogging(), "setNull", new Object[] {parameterName, nType, sTypeName}); checkClosed(); - setObject(setterGetParam(findColumn(sCol)), null, JavaType.OBJECT, JDBCType.of(nType), null, null, false, findColumn(sCol), sTypeName); + setObject(setterGetParam(findColumn(parameterName)), null, JavaType.OBJECT, JDBCType.of(nType), null, null, false, findColumn(parameterName), + sTypeName); loggerExternal.exiting(getClassNameLogging(), "setNull"); } - public void setURL(String sCol, - URL u) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "setURL", sCol); + @Override + public void setURL(String parameterName, + URL url) throws SQLException { + loggerExternal.entering(getClassNameLogging(), "setURL", parameterName); checkClosed(); - setURL(findColumn(sCol), u); + setURL(findColumn(parameterName), url); loggerExternal.exiting(getClassNameLogging(), "setURL"); } - /** - * Populates a table valued parameter passed to a stored procedure with a data table. - * - * @param sCol - * the name of the parameter - * @param tvpName - * the name of the type TVP - * @param tvpDataTable - * the data table object - * @throws SQLServerException - * when an error occurs - */ - public final void setStructured(String sCol, + @Override + public final void setStructured(String parameterName, String tvpName, SQLServerDataTable tvpDataTable) throws SQLServerException { - tvpName = getTVPNameIfNull(findColumn(sCol), tvpName); + tvpName = getTVPNameIfNull(findColumn(parameterName), tvpName); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {sCol, tvpName, tvpDataTable}); + loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {parameterName, tvpName, tvpDataTable}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TVP, tvpDataTable, JavaType.TVP, tvpName); + setValue(findColumn(parameterName), JDBCType.TVP, tvpDataTable, JavaType.TVP, tvpName); loggerExternal.exiting(getClassNameLogging(), "setStructured"); } - /** - * Populates a table valued parameter passed to a stored procedure with a ResultSet retrieved from another table - * - * @param sCol - * the name of the parameter - * @param tvpName - * the name of the type TVP - * @param tvpResultSet - * the source result set object - * @throws SQLServerException - * when an error occurs - */ - public final void setStructured(String sCol, + @Override + public final void setStructured(String parameterName, String tvpName, ResultSet tvpResultSet) throws SQLServerException { - tvpName = getTVPNameIfNull(findColumn(sCol), tvpName); + tvpName = getTVPNameIfNull(findColumn(parameterName), tvpName); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {sCol, tvpName, tvpResultSet}); + loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {parameterName, tvpName, tvpResultSet}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TVP, tvpResultSet, JavaType.TVP, tvpName); + setValue(findColumn(parameterName), JDBCType.TVP, tvpResultSet, JavaType.TVP, tvpName); loggerExternal.exiting(getClassNameLogging(), "setStructured"); } - /** - * Populates a table valued parameter passed to a stored procedure with an ISQLServerDataRecord object. - * - * @param sCol - * the name of the parameter - * @param tvpName - * the name of the type TVP - * @param tvpDataRecord - * ISQLServerDataRecord is used for streaming data and the user decides how to use it. tvpDataRecord is an ISQLServerDataRecord - * object.the source result set object - * @throws SQLServerException - * when an error occurs - */ - public final void setStructured(String sCol, + @Override + public final void setStructured(String parameterName, String tvpName, ISQLServerDataRecord tvpDataRecord) throws SQLServerException { - tvpName = getTVPNameIfNull(findColumn(sCol), tvpName); + tvpName = getTVPNameIfNull(findColumn(parameterName), tvpName); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {sCol, tvpName, tvpDataRecord}); + loggerExternal.entering(getClassNameLogging(), "setStructured", new Object[] {parameterName, tvpName, tvpDataRecord}); checkClosed(); - setValue(findColumn(sCol), JDBCType.TVP, tvpDataRecord, JavaType.TVP, tvpName); + setValue(findColumn(parameterName), JDBCType.TVP, tvpDataRecord, JavaType.TVP, tvpName); loggerExternal.exiting(getClassNameLogging(), "setStructured"); } - public URL getURL(int n) throws SQLServerException { - NotImplemented(); + @Override + public URL getURL(int parameterIndex) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); return null; } - public URL getURL(String s) throws SQLServerException { - NotImplemented(); + @Override + public URL getURL(String parameterName) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); return null; } + @Override public final void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2932,6 +2307,7 @@ public final void setSQLXML(String parameterName, loggerExternal.exiting(getClassNameLogging(), "setSQLXML"); } + @Override public final SQLXML getSQLXML(int parameterIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getSQLXML", parameterIndex); checkClosed(); @@ -2940,6 +2316,7 @@ public final SQLXML getSQLXML(int parameterIndex) throws SQLException { return value; } + @Override public final SQLXML getSQLXML(String parameterName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getSQLXML", parameterName); checkClosed(); @@ -2948,65 +2325,211 @@ public final SQLXML getSQLXML(String parameterName) throws SQLException { return value; } + @Override public final void setRowId(String parameterName, - RowId x) throws SQLException { - - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + RowId value) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final RowId getRowId(int parameterIndex) throws SQLException { - - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(connection, this); + return null; } + @Override public final RowId getRowId(String parameterName) throws SQLException { - - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(connection, this); + return null; } - public void registerOutParameter(String s, - int n, - String s1) throws SQLServerException { + @Override + public void registerOutParameter(String parameterName, + int sqlType, + String typeName) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {s, n, s1}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, typeName}); checkClosed(); - registerOutParameter(findColumn(s), n, s1); + registerOutParameter(findColumn(parameterName), sqlType, typeName); loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } + @Override public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", - new Object[] {parameterName, sqlType, scale}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); checkClosed(); registerOutParameter(findColumn(parameterName), sqlType, scale); loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } + @Override public void registerOutParameter(String parameterName, int sqlType, int precision, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", - new Object[] {parameterName, sqlType, scale}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); checkClosed(); registerOutParameter(findColumn(parameterName), sqlType, precision, scale); loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } - public void registerOutParameter(String s, - int n) throws SQLServerException { + @Override + public void registerOutParameter(String parameterName, + int sqlType) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {s, n}); + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType}); checkClosed(); - registerOutParameter(findColumn(s), n); + registerOutParameter(findColumn(parameterName), sqlType); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(int paramterIndex, + SQLType sqlType) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {paramterIndex, sqlType}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(paramterIndex, sqlType.getVendorTypeNumber()); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(int paramterIndex, + SQLType sqlType, + String typeName) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {paramterIndex, sqlType, typeName}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(paramterIndex, sqlType.getVendorTypeNumber(), typeName); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(int paramterIndex, + SQLType sqlType, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {paramterIndex, sqlType, scale}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(paramterIndex, sqlType.getVendorTypeNumber(), scale); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(int paramterIndex, + SQLType sqlType, + int precision, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {paramterIndex, sqlType, scale}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(paramterIndex, sqlType.getVendorTypeNumber(), precision, scale); loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); } + @Override + public void setObject(String parameterName, + Object value, + SQLType jdbcType) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, jdbcType}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + setObject(parameterName, value, jdbcType.getVendorTypeNumber()); + loggerExternal.exiting(getClassNameLogging(), "setObject"); + } + + @Override + public void setObject(String parameterName, + Object value, + SQLType jdbcType, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, jdbcType, scale}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + setObject(parameterName, value, jdbcType.getVendorTypeNumber(), scale); + loggerExternal.exiting(getClassNameLogging(), "setObject"); + } + + @Override + public void setObject(String parameterName, + Object value, + SQLType jdbcType, + int scale, + boolean forceEncrypt) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {parameterName, value, jdbcType, scale, forceEncrypt}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + setObject(parameterName, value, jdbcType.getVendorTypeNumber(), scale, forceEncrypt); + loggerExternal.exiting(getClassNameLogging(), "setObject"); + } + + @Override + public void registerOutParameter(String parameterName, + SQLType sqlType, + String typeName) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, typeName}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), typeName); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(String parameterName, + SQLType sqlType, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), scale); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(String parameterName, + SQLType sqlType, + int precision, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), precision, scale); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } + + @Override + public void registerOutParameter(String parameterName, + SQLType sqlType) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType}); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + registerOutParameter(parameterName, sqlType.getVendorTypeNumber()); + loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement42.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement42.java deleted file mode 100644 index cf5e1f246..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement42.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * - * This class is separated from SQLServerCallableStatement class in order to resolve compiling error of missing Java 8 Types when running with Java 7. - * - * This class will be initialized instead of SQLServerCallableStatement when Java 8 and JDBC 4.2 are used. - * - * It shares the same PreparedStatement implementation with SQLServerPreparedStatement42. - * - */ -public class SQLServerCallableStatement42 extends SQLServerCallableStatement implements ISQLServerCallableStatement42 { - - SQLServerCallableStatement42(SQLServerConnection connection, - String sql, - int nRSType, - int nRSConcur, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - super(connection, sql, nRSType, nRSConcur, stmtColEncSetting); - } - - public void registerOutParameter(int index, - SQLType sqlType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(index, sqlType.getVendorTypeNumber()); - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(int index, - SQLType sqlType, - String typeName) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType, typeName}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(index, sqlType.getVendorTypeNumber(), typeName); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(int index, - SQLType sqlType, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(index, sqlType.getVendorTypeNumber(), scale); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(int index, - SQLType sqlType, - int precision, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {index, sqlType, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(index, sqlType.getVendorTypeNumber(), precision, scale); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void setObject(String sCol, - Object obj, - SQLType jdbcType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, obj, jdbcType}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - setObject(sCol, obj, jdbcType.getVendorTypeNumber()); - - loggerExternal.exiting(getClassNameLogging(), "setObject"); - } - - public void setObject(String sCol, - Object obj, - SQLType jdbcType, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, obj, jdbcType, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - setObject(sCol, obj, jdbcType.getVendorTypeNumber(), scale); - - loggerExternal.exiting(getClassNameLogging(), "setObject"); - } - - public void setObject(String sCol, - Object obj, - SQLType jdbcType, - int scale, - boolean forceEncrypt) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setObject", new Object[] {sCol, obj, jdbcType, scale, forceEncrypt}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - setObject(sCol, obj, jdbcType.getVendorTypeNumber(), scale, forceEncrypt); - - loggerExternal.exiting(getClassNameLogging(), "setObject"); - } - - public void registerOutParameter(String parameterName, - SQLType sqlType, - String typeName) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, typeName}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), typeName); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(String parameterName, - SQLType sqlType, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), scale); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(String parameterName, - SQLType sqlType, - int precision, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(parameterName, sqlType.getVendorTypeNumber(), precision, scale); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public void registerOutParameter(String parameterName, - SQLType sqlType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "registerOutParameter", new Object[] {parameterName, sqlType}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - registerOutParameter(parameterName, sqlType.getVendorTypeNumber()); - - loggerExternal.exiting(getClassNameLogging(), "registerOutParameter"); - } - - public final void setObject(int index, - Object obj, - SQLType jdbcType) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, index, obj, jdbcType); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - int scaleOrLength) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, scaleOrLength); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, precision, scale); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale, - boolean forceEncrypt) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, precision, scale, forceEncrypt); - } - -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 137361dcb..31b8d0837 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -17,10 +17,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.Reader; import java.io.Serializable; import java.io.StringReader; import java.io.UnsupportedEncodingException; +import java.io.Writer; import java.sql.Clob; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; @@ -35,9 +37,13 @@ */ public class SQLServerClob extends SQLServerClobBase implements Clob { + /** + * Always refresh SerialVersionUID when prompted + */ private static final long serialVersionUID = 2872035282200133865L; - - // Loggers should be class static to avoid lock contention with multiple threads + + // Loggers should be class static to avoid lock contention with multiple + // threads private static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerClob"); /** @@ -67,12 +73,94 @@ public SQLServerClob(SQLServerConnection connection, super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo); } + @Override + public void free() throws SQLException { + super.free(); + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return super.getAsciiStream(); + } + + @Override + public Reader getCharacterStream() throws SQLException { + return super.getCharacterStream(); + } + + @Override + public Reader getCharacterStream(long pos, + long length) throws SQLException { + return super.getCharacterStream(pos, length); + } + + @Override + public String getSubString(long pos, + int length) throws SQLException { + return super.getSubString(pos, length); + } + + @Override + public long length() throws SQLException { + return super.length(); + } + + @Override + void fillFromStream() throws SQLException { + super.fillFromStream(); + } + + @Override + public long position(Clob searchstr, + long start) throws SQLException { + return super.position(searchstr, start); + } + + @Override + public long position(String searchstr, + long start) throws SQLException { + return super.position(searchstr, start); + } + + @Override + public void truncate(long len) throws SQLException { + super.truncate(len); + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + return super.setAsciiStream(pos); + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + return super.setCharacterStream(pos); + } + + @Override + public int setString(long pos, + String s) throws SQLException { + return super.setString(pos, s); + } + + @Override + public int setString(long pos, + String str, + int offset, + int len) throws SQLException { + return super.setString(pos, str, offset, len); + } + + @Override final JDBCType getJdbcType() { return JDBCType.CLOB; } } abstract class SQLServerClobBase extends SQLServerLob implements Serializable { + /** + * Always refresh SerialVersionUID when prompted + */ private static final long serialVersionUID = 8691072211054430124L; // The value of the CLOB that this Clob object represents. @@ -82,27 +170,31 @@ abstract class SQLServerClobBase extends SQLServerLob implements Serializable { private final SQLCollation sqlCollation; private boolean isClosed = false; - + private final TypeInfo typeInfo; // Active streams which must be closed when the Clob/NClob is closed // - // Initial size of the array is based on an assumption that a Clob/NClob object is - // typically used either for input or output, and then only once. The array size + // Initial size of the array is based on an assumption that a Clob/NClob + // object is + // typically used either for input or output, and then only once. The array + // size // grows automatically if multiple streams are used. private ArrayList activeStreams = new ArrayList<>(1); transient SQLServerConnection con; - + private final Logger logger; - + final private String traceID = getClass().getName().substring(1 + getClass().getName().lastIndexOf('.')) + ":" + nextInstanceID(); final public String toString() { return traceID; } - static private final AtomicInteger baseID = new AtomicInteger(0); // Unique id generator for each instance (used for logging). + // Unique id generator for each instance (used for logging). + static private final AtomicInteger baseID = new AtomicInteger(0); + // Returns unique id for each instance. private static int nextInstanceID() { @@ -162,7 +254,8 @@ private String getDisplayClassName() { */ public void free() throws SQLException { if (!isClosed) { - // Close active streams, ignoring any errors, since nothing can be done with them after that point anyway. + // Close active streams, ignoring any errors, since nothing can be + // done with them after that point anyway. if (null != activeStreams) { for (Closeable stream : activeStreams) { try { @@ -246,8 +339,8 @@ public Reader getCharacterStream() throws SQLException { */ public Reader getCharacterStream(long pos, long length) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwFeatureNotSupportedException(); + return null; } /** @@ -286,12 +379,14 @@ public String getSubString(long pos, if (pos > value.length()) pos = value.length(); - // Bound the requested length to no larger than the remainder of the value beyond pos so that the + // Bound the requested length to no larger than the remainder of the + // value beyond pos so that the // endIndex computed for the substring call below is within bounds. if (length > value.length() - pos) length = (int) (value.length() - pos); - // Note String.substring uses beginIndex and endIndex (not pos and length), so calculate endIndex. + // Note String.substring uses beginIndex and endIndex (not pos and + // length), so calculate endIndex. return value.substring((int) pos, (int) pos + length); } @@ -306,23 +401,25 @@ public long length() throws SQLException { checkClosed(); if (value == null && activeStreams.get(0) instanceof PLPInputStream) { - return (long)((PLPInputStream)activeStreams.get(0)).payloadLength/2; + return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2; } return value.length(); } - + /** * Function for the result set to maintain clobs it has created + * * @throws SQLException */ void fillFromStream() throws SQLException { - if(!isClosed) { + if (!isClosed) { getStringFromStream(); } } - + /** * Converts the stream to String + * * @throws SQLServerException */ private void getStringFromStream() throws SQLServerException { @@ -389,7 +486,8 @@ public long position(String searchstr, SQLServerException.makeFromDriverError(con, null, form.format(msgArgs), null, true); } - // Back compat: Handle null search string as not found rather than throw an exception. + // Back compat: Handle null search string as not found rather than throw + // an exception. // JDBC spec doesn't describe the behavior for a null search string. if (null == searchstr) return -1; @@ -532,7 +630,8 @@ public int setString(long pos, } // Note position for Clob.setString is 1 based not zero based. - // Position must be in range of existing Clob data or exactly 1 character + // Position must be in range of existing Clob data or exactly 1 + // character // past the end of data to request "append" mode. if (pos < 1 || pos > value.length() + 1) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidPositionIndex")); @@ -545,7 +644,8 @@ public int setString(long pos, // Overwrite past end of value case. if (len >= value.length() - pos) { - // Make sure the new value length wouldn't exceed the maximum allowed + // Make sure the new value length wouldn't exceed the maximum + // allowed DataTypes.getCheckedLength(con, getJdbcType(), pos + len, false); assert pos + len <= Integer.MAX_VALUE; @@ -581,11 +681,14 @@ public int setString(long pos, } } -// SQLServerClobWriter is a simple java.io.Writer interface implementing class that -// forwards all calls to SQLServerClob.setString. This class is returned to caller by +// SQLServerClobWriter is a simple java.io.Writer interface implementing class +// that +// forwards all calls to SQLServerClob.setString. This class is returned to +// caller by // SQLServerClob class when setCharacterStream is called. // -// SQLServerClobWriter starts writing at postion streamPos and continues to write +// SQLServerClobWriter starts writing at postion streamPos and continues to +// write // in a forward only manner. There is no reset with java.io.Writer. // final class SQLServerClobWriter extends java.io.Writer { @@ -655,11 +758,14 @@ private void checkClosed() throws IOException { } } -// SQLServerClobAsciiOutputStream is a simple java.io.OutputStream interface implementing class that -// forwards all calls to SQLServerClob.setString. This class is returned to caller by +// SQLServerClobAsciiOutputStream is a simple java.io.OutputStream interface +// implementing class that +// forwards all calls to SQLServerClob.setString. This class is returned to +// caller by // SQLServerClob class when setAsciiStream is called. // -// SQLServerClobAsciiOutputStream starts writing at character postion streamPos and continues to write +// SQLServerClobAsciiOutputStream starts writing at character postion streamPos +// and continues to write // in a forward only manner. Reset/mark are not supported. // final class SQLServerClobAsciiOutputStream extends java.io.OutputStream { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index ab7a758aa..0c4b2bef9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -11,34 +11,28 @@ import static java.nio.charset.StandardCharsets.UTF_16LE; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.DatagramPacket; import java.net.DatagramSocket; -import java.net.IDN; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; -import java.sql.Blob; import java.sql.CallableStatement; -import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLClientInfoException; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLPermission; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; -import java.sql.Struct; import java.text.MessageFormat; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -53,8 +47,6 @@ import javax.sql.XAConnection; import org.ietf.jgss.GSSCredential; -import org.ietf.jgss.GSSException; - import mssql.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import mssql.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder; import mssql.googlecode.concurrentlinkedhashmap.EvictionListener; @@ -81,23 +73,33 @@ * details. */ -// Note all the public functions in this class also need to be defined in SQLServerConnectionPoolProxy. -public class SQLServerConnection implements ISQLServerConnection { +// NOTE: All the public functions in this class also need to be defined in SQLServerConnectionPoolProxy +// Declare all new custom (non-static) Public APIs in ISQLServerConnection interface such that they can also be implemented by +// SQLServerConnectionPoolProxy +public class SQLServerConnection implements ISQLServerConnection, java.io.Serializable { - long timerExpire; + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = 1965647556064751510L; + + long timerExpire; boolean attemptRefreshTokenLocked = false; - // Threasholds related to when prepared statement handles are cleaned-up. 1 == immediately. + // Thresholds related to when prepared statement handles are cleaned-up. 1 == immediately. /** - * The default for the prepared statement clean-up action threshold (i.e. when sp_unprepare is called). - */ + * The default for the prepared statement clean-up action threshold (i.e. when sp_unprepare is called). + */ static final int DEFAULT_SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD = 10; // Used to set the initial default, can be changed later. private int serverPreparedStatementDiscardThreshold = -1; // Current limit for this particular connection. /** - * The default for if prepared statements should execute sp_executesql before following the prepare, unprepare pattern. - */ - static final boolean DEFAULT_ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT_CALL = false; // Used to set the initial default, can be changed later. false == use sp_executesql -> sp_prepexec -> sp_execute -> batched -> sp_unprepare pattern, true == skip sp_executesql part of pattern. + * The default for if prepared statements should execute sp_executesql before following the prepare, unprepare pattern. + */ + static final boolean DEFAULT_ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT_CALL = false; // Used to set the initial default, can be changed later. + // false == use sp_executesql -> sp_prepexec -> sp_execute + // -> batched -> sp_unprepare pattern, true == skip + // sp_executesql part of pattern. private Boolean enablePrepareOnFirstPreparedStatementCall = null; // Current limit for this particular connection. // Handle the actual queue of discarded prepared statements. @@ -106,7 +108,6 @@ public class SQLServerConnection implements ISQLServerConnection { private boolean fedAuthRequiredByUser = false; private boolean fedAuthRequiredPreLoginResponse = false; - private boolean federatedAuthenticationAcknowledged = false; private boolean federatedAuthenticationRequested = false; private boolean federatedAuthenticationInfoRequested = false; // Keep this distinct from _federatedAuthenticationRequested, since some fedauth // library types may not need more info @@ -116,10 +117,17 @@ public class SQLServerConnection implements ISQLServerConnection { private byte[] accessTokenInByte = null; private SqlFedAuthToken fedAuthToken = null; - + private String originalHostNameInCertificate = null; + + private Boolean isAzureDW = null; + + static class Sha1HashKey implements java.io.Serializable { - static class Sha1HashKey { + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = 166788428640603097L; private byte[] bytes; Sha1HashKey(String sql, @@ -135,7 +143,7 @@ public boolean equals(Object obj) { if (!(obj instanceof Sha1HashKey)) return false; - return java.util.Arrays.equals(bytes, ((Sha1HashKey)obj).bytes); + return java.util.Arrays.equals(bytes, ((Sha1HashKey) obj).bytes); } public int hashCode() { @@ -156,16 +164,19 @@ private java.security.MessageDigest getSha1Digest() { /** * Used to keep track of an individual prepared statement handle. */ - class PreparedStatementHandle { + class PreparedStatementHandle { private int handle = 0; private final AtomicInteger handleRefCount = new AtomicInteger(); private boolean isDirectSql; - private volatile boolean evictedFromCache; - private volatile boolean explicitlyDiscarded; + private volatile boolean evictedFromCache; + private volatile boolean explicitlyDiscarded; private Sha1HashKey key; - PreparedStatementHandle(Sha1HashKey key, int handle, boolean isDirectSql, boolean isEvictedFromCache) { - this.key = key; + PreparedStatementHandle(Sha1HashKey key, + int handle, + boolean isDirectSql, + boolean isEvictedFromCache) { + this.key = key; this.handle = handle; this.isDirectSql = isDirectSql; this.setIsEvictedFromCache(isEvictedFromCache); @@ -184,9 +195,9 @@ private void setIsEvictedFromCache(boolean isEvictedFromCache) { /** Specify that this statement has been explicitly discarded from being used by the cache. */ void setIsExplicitlyDiscarded() { - this.explicitlyDiscarded = true; - - evictCachedPreparedStatementHandle(this); + this.explicitlyDiscarded = true; + + evictCachedPreparedStatementHandle(this); } /** Has the statement been explicitly discarded. */ @@ -208,12 +219,11 @@ boolean isDirectSql() { return isDirectSql; } - /** Make sure handle cannot be re-used. + /** + * Make sure handle cannot be re-used. * - * @return - * false: Handle could not be discarded, it is in use. - * true: Handle was successfully put on path for discarding. - */ + * @return false: Handle could not be discarded, it is in use. true: Handle was successfully put on path for discarding. + */ private boolean tryDiscardHandle() { return handleRefCount.compareAndSet(0, -999); } @@ -223,12 +233,12 @@ private boolean isDiscarded() { return 0 > handleRefCount.intValue(); } - /** Adds a new reference to this handle, i.e. re-using it. + /** + * Adds a new reference to this handle, i.e. re-using it. * - * @return - * false: Reference could not be added, statement has been discarded or does not have a handle associated with it. - * true: Reference was successfully added. - */ + * @return false: Reference could not be added, statement has been discarded or does not have a handle associated with it. true: Reference was + * successfully added. + */ boolean tryAddReference() { if (isDiscarded() || isExplicitlyDiscarded()) return false; @@ -238,7 +248,7 @@ boolean tryAddReference() { } } - /** Remove a reference from this handle*/ + /** Remove a reference from this handle */ void removeReference() { handleRefCount.decrementAndGet(); } @@ -251,34 +261,33 @@ void removeReference() { static private ConcurrentLinkedHashMap parsedSQLCache; static { - parsedSQLCache = new Builder() - .maximumWeightedCapacity(PARSED_SQL_CACHE_SIZE) - .build(); + parsedSQLCache = new Builder().maximumWeightedCapacity(PARSED_SQL_CACHE_SIZE).build(); } /** Get prepared statement cache entry if exists, if not parse and create a new one */ - static ParsedSQLCacheItem getCachedParsedSQL(Sha1HashKey key) { + static ParsedSQLCacheItem getCachedParsedSQL(Sha1HashKey key) { return parsedSQLCache.get(key); } /** Parse and create a information about parsed SQL text */ - static ParsedSQLCacheItem parseAndCacheSQL(Sha1HashKey key, String sql) throws SQLServerException { + static ParsedSQLCacheItem parseAndCacheSQL(Sha1HashKey key, + String sql) throws SQLServerException { JDBCSyntaxTranslator translator = new JDBCSyntaxTranslator(); String parsedSql = translator.translate(sql); - String procName = translator.getProcedureName(); // may return null + String procName = translator.getProcedureName(); // may return null boolean returnValueSyntax = translator.hasReturnValueSyntax(); int paramCount = countParams(parsedSql); - ParsedSQLCacheItem cacheItem = new ParsedSQLCacheItem (parsedSql, paramCount, procName, returnValueSyntax); + ParsedSQLCacheItem cacheItem = new ParsedSQLCacheItem(parsedSql, paramCount, procName, returnValueSyntax); parsedSQLCache.putIfAbsent(key, cacheItem); return cacheItem; } - + /** Default size for prepared statement caches */ - static final int DEFAULT_STATEMENT_POOLING_CACHE_SIZE = 0; - - /** Size of the prepared statement handle cache */ + static final int DEFAULT_STATEMENT_POOLING_CACHE_SIZE = 0; + + /** Size of the prepared statement handle cache */ private int statementPoolingCacheSize = DEFAULT_STATEMENT_POOLING_CACHE_SIZE; /** Cache of prepared statement handles */ @@ -290,23 +299,23 @@ static ParsedSQLCacheItem parseAndCacheSQL(Sha1HashKey key, String sql) throws */ private boolean disableStatementPooling = true; - /** - * Find statement parameters. - * - * @param sql - * SQL text to parse for number of parameters to intialize. - */ - private static int countParams(String sql) { - int nParams = 0; - - // Figure out the expected number of parameters by counting the - // parameter placeholders in the SQL string. - int offset = -1; - while ((offset = ParameterUtils.scanSQLForChar('?', sql, ++offset)) < sql.length()) - ++nParams; - - return nParams; - } + /** + * Find statement parameters. + * + * @param sql + * SQL text to parse for number of parameters to intialize. + */ + private static int countParams(String sql) { + int nParams = 0; + + // Figure out the expected number of parameters by counting the + // parameter placeholders in the SQL string. + int offset = -1; + while ((offset = ParameterUtils.scanSQLForChar('?', sql, ++offset)) < sql.length()) + ++nParams; + + return nParams; + } SqlFedAuthToken getAuthenticationResult() { return fedAuthToken; @@ -361,8 +370,6 @@ public String toString() { } } - - class ActiveDirectoryAuthentication { static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; static final String ADAL_GET_ACCESS_TOKEN_FUNCTION_NAME = "ADALGetAccessToken"; @@ -390,7 +397,6 @@ private enum State { * Connection state variables. NB If new state is added then logical connections derived from a physical connection must inherit the same state. * If state variables are added they must be added also in connection cloning method clone() */ - private final static int INTERMITTENT_TLS_MAX_RETRY = 5; // Indicates if we received a routing ENVCHANGE in the current connection attempt @@ -402,27 +408,22 @@ private enum State { ServerPortPlaceHolder getRoutingInfo() { return routingInfo; } - + // Permission targets private static final String callAbortPerm = "callAbort"; - + private static final String SET_NETWORK_TIMEOUT_PERM = "setNetworkTimeout"; - private boolean sendStringParametersAsUnicode = SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.getDefaultValue(); // see - // connection - // properties - // doc - // (default - // is - // false). + // see connection properties doc (default is false). + private boolean sendStringParametersAsUnicode = SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.getDefaultValue(); private String hostName = null; - + boolean sendStringParametersAsUnicode() { return sendStringParametersAsUnicode; } - private boolean lastUpdateCount; // see connection properties doc + private boolean lastUpdateCount; // see connection properties doc final boolean useLastUpdateCount() { return lastUpdateCount; @@ -454,8 +455,8 @@ final ApplicationIntent getApplicationIntent() { return applicationIntent; } - private int nLockTimeout; // see connection properties doc - private String selectMethod; // see connection properties doc 4.0 new property + private int nLockTimeout; // see connection properties doc + private String selectMethod; // see connection properties doc 4.0 new property final String getSelectMethod() { return selectMethod; @@ -472,13 +473,15 @@ final String getResponseBuffering() { final int getQueryTimeoutSeconds() { return queryTimeoutSeconds; } + /** * timeout value for canceling the query timeout */ private int cancelQueryTimeoutSeconds; - + /** * Retrieves the cancelTimeout in seconds + * * @return */ final int getCancelQueryTimeoutSeconds() { @@ -491,15 +494,32 @@ final int getSocketTimeoutMilliseconds() { return socketTimeoutMilliseconds; } + /** + * boolean value for deciding if the driver should use bulk copy API for batch inserts + */ + private boolean useBulkCopyForBatchInsert; + + /** + * Retrieves the useBulkCopyForBatchInsert value. + * @return flag for using Bulk Copy API for batch insert operations. + */ + public boolean getUseBulkCopyForBatchInsert() { + return useBulkCopyForBatchInsert; + } + + /** + * Specifies the flag for using Bulk Copy API for batch insert operations. + * @param useBulkCopyForBatchInsert boolean value for useBulkCopyForBatchInsert. + */ + public void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert) { + this.useBulkCopyForBatchInsert = useBulkCopyForBatchInsert; + } + boolean userSetTNIR = true; private boolean sendTimeAsDatetime = SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue(); - /** - * Checks the sendTimeAsDatetime property. - * - * @return boolean value of sendTimeAsDatetime - */ + @Override public synchronized final boolean getSendTimeAsDatetime() { return !isKatmaiOrLater() || sendTimeAsDatetime; } @@ -559,6 +579,12 @@ boolean getServerSupportsColumnEncryption() { return serverSupportsColumnEncryption; } + private boolean serverSupportsDataClassification = false; + + boolean getServerSupportsDataClassification() { + return serverSupportsDataClassification; + } + static boolean isWindows; static Map globalSystemColumnEncryptionKeyStoreProviders = new HashMap<>(); static { @@ -902,12 +928,7 @@ int getServerMajorVersion() { private UUID clientConnectionId = null; - /** - * Retrieves the clientConnectionID. - * - * @throws SQLServerException - * when an error occurs - */ + @Override public UUID getClientConnectionId() throws SQLServerException { // If the connection is closed, we do not allow external application to get // ClientConnectionId. @@ -934,15 +955,6 @@ final boolean attachConnId() { connectionlogger.fine(toString() + " created by (" + parentInfo + ")"); initResettableValues(); - // JDBC 3 driver only works with 1.5 JRE - if (3 == DriverJDBCVersion.major && !"1.5".equals(Util.SYSTEM_SPEC_VERSION)) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unsupportedJREVersion")); - Object[] msgArgs = {Util.SYSTEM_SPEC_VERSION}; - String message = form.format(msgArgs); - connectionlogger.severe(message); - throw new UnsupportedOperationException(message); - } - // Caching turned on? if (!this.getDisableStatementPooling() && 0 < this.getStatementPoolingCacheSize()) { prepareCache(); @@ -980,7 +992,7 @@ final void resetPooledConnection() { * * @return the next conn id */ - /* L0 */ private static int nextConnectionID() { + private static int nextConnectionID() { return baseConnectionID.incrementAndGet(); // 4.04 Ensure thread safe id allocation } @@ -995,6 +1007,7 @@ String getClassNameLogging() { /** * This is a helper function to provide an ID string suitable for tracing. */ + @Override public String toString() { if (null != clientConnectionId) return traceID + " ClientConnectionId: " + clientConnectionId.toString(); @@ -1002,21 +1015,12 @@ public String toString() { return traceID; } - /** - * Throw a not implemeneted exception. - * - * @throws SQLServerException - */ - /* L0 */ void NotImplemented() throws SQLServerException { - SQLServerException.makeFromDriverError(this, this, SQLServerException.getErrString("R_notSupported"), null, false); - } - /** * Check if the connection is closed Create a new connection if it's a fedauth connection and the access token is going to expire. * * @throws SQLServerException */ - /* L0 */ void checkClosed() throws SQLServerException { + void checkClosed() throws SQLServerException { if (isSessionUnAvailable()) { SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_connectionIsClosed"), null, false); } @@ -1041,7 +1045,7 @@ public String toString() { * @exception SQLServerException * thrown if value is not recognized. */ - /* L0 */ private boolean booleanPropertyOn(String propName, + private boolean booleanPropertyOn(String propName, String propValue) throws SQLServerException { // Null means take the default of false. if (null == propValue) @@ -1136,8 +1140,8 @@ else if (elapsedSeconds >= loginTimeoutSeconds) { else { // Retry the connection. if (connectionlogger.isLoggable(Level.FINE)) { - connectionlogger - .fine("Connection failed during SSL handshake. Retrying due to an intermittent TLS 1.2 failure issue. Retry attempt = " + connectionlogger.fine( + "Connection failed during SSL handshake. Retrying due to an intermittent TLS 1.2 failure issue. Retry attempt = " + retryAttempt + "."); } } @@ -1200,24 +1204,23 @@ Connection connectInternal(Properties propsIn, activeConnectionProperties = (Properties) propsIn.clone(); pooledConnectionParent = pooledConnection; - - String hostNameInCertificate = activeConnectionProperties. - getProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString()); - + + String hostNameInCertificate = activeConnectionProperties.getProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString()); + // hostNameInCertificate property can change when redirection is involved, so maintain this value // for every instance of SQLServerConnection. if (null == originalHostNameInCertificate && null != hostNameInCertificate && !hostNameInCertificate.isEmpty()) { - originalHostNameInCertificate = activeConnectionProperties. - getProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString()); + originalHostNameInCertificate = activeConnectionProperties + .getProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString()); } - + if (null != originalHostNameInCertificate && !originalHostNameInCertificate.isEmpty()) { // if hostNameInCertificate has a legitimate value (and not empty or null), // reset hostNameInCertificate to the original value every time we connect (or re-connect). - activeConnectionProperties.setProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString(), + activeConnectionProperties.setProperty(SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString(), originalHostNameInCertificate); } - + String sPropKey; String sPropValue; @@ -1297,7 +1300,7 @@ Connection connectInternal(Properties propsIn, if (true == serverNameAsACE) { try { - sPropValue = IDN.toASCII(sPropValue); + sPropValue = java.net.IDN.toASCII(sPropValue); } catch (IllegalArgumentException ex) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); @@ -1402,7 +1405,8 @@ Connection connectInternal(Properties propsIn, trustServerCertificate = booleanPropertyOn(sPropKey, sPropValue); trustManagerClass = activeConnectionProperties.getProperty(SQLServerDriverStringProperty.TRUST_MANAGER_CLASS.toString()); - trustManagerConstructorArg = activeConnectionProperties.getProperty(SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString()); + trustManagerConstructorArg = activeConnectionProperties + .getProperty(SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString()); sPropKey = SQLServerDriverStringProperty.SELECT_METHOD.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); @@ -1465,7 +1469,7 @@ Connection connectInternal(Properties propsIn, sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { setDisableStatementPooling(booleanPropertyOn(sPropKey, sPropValue)); - } + } sPropKey = SQLServerDriverBooleanProperty.INTEGRATED_SECURITY.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); @@ -1482,14 +1486,14 @@ Connection connectInternal(Properties propsIn, } } - if(intAuthScheme == AuthenticationScheme.javaKerberos){ + if (intAuthScheme == AuthenticationScheme.javaKerberos) { sPropKey = SQLServerDriverObjectProperty.GSS_CREDENTIAL.toString(); - if(activeConnectionProperties.containsKey(sPropKey)) { + if (activeConnectionProperties.containsKey(sPropKey)) { ImpersonatedUserCred = (GSSCredential) activeConnectionProperties.get(sPropKey); isUserCreatedCredential = true; } } - + sPropKey = SQLServerDriverStringProperty.AUTHENTICATION.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (sPropValue == null) { @@ -1721,18 +1725,18 @@ else if (0 == requestedPacketSize) SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, false); } } - + sPropKey = SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.toString(); int cancelQueryTimeout = SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.getDefaultValue(); - + if (activeConnectionProperties.getProperty(sPropKey) != null && activeConnectionProperties.getProperty(sPropKey).length() > 0) { try { int n = Integer.parseInt(activeConnectionProperties.getProperty(sPropKey)); if (n >= cancelQueryTimeout) { - // use cancelQueryTimeout only if queryTimeout is set. - if(queryTimeoutSeconds > defaultQueryTimeout) { - cancelQueryTimeoutSeconds = n; - } + // use cancelQueryTimeout only if queryTimeout is set. + if (queryTimeoutSeconds > defaultQueryTimeout) { + cancelQueryTimeoutSeconds = n; + } } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidCancelQueryTimeout")); @@ -1746,7 +1750,7 @@ else if (0 == requestedPacketSize) SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, false); } } - + sPropKey = SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(); if (activeConnectionProperties.getProperty(sPropKey) != null && activeConnectionProperties.getProperty(sPropKey).length() > 0) { try { @@ -1765,7 +1769,13 @@ else if (0 == requestedPacketSize) if (null != sPropValue) { setEnablePrepareOnFirstPreparedStatementCall(booleanPropertyOn(sPropKey, sPropValue)); } - + + sPropKey = SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.toString(); + sPropValue = activeConnectionProperties.getProperty(sPropKey); + if (null != sPropValue) { + useBulkCopyForBatchInsert = booleanPropertyOn(sPropKey, sPropValue); + } + sPropKey = SQLServerDriverStringProperty.SSL_PROTOCOL.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null == sPropValue) { @@ -1775,7 +1785,7 @@ else if (0 == requestedPacketSize) else { activeConnectionProperties.setProperty(sPropKey, SSLProtocol.valueOfString(sPropValue).toString()); } - + FailoverInfo fo = null; String databaseNameProperty = SQLServerDriverStringProperty.DATABASE_NAME.toString(); String serverNameProperty = SQLServerDriverStringProperty.SERVER_NAME.toString(); @@ -2286,14 +2296,14 @@ private void connectHelper(ServerPortPlaceHolder serverInfo, connectionlogger.fine(toString() + " Connecting with server: " + serverInfo.getServerName() + " port: " + serverInfo.getPortNumber() + " Timeout slice: " + timeOutsliceInMillis + " Timeout Full: " + timeOutFullInSeconds); } - + // Before opening the TDSChannel, calculate local hostname // as the InetAddress.getLocalHost() takes more than usual time in certain OS and JVM combination, it avoids connection loss hostName = activeConnectionProperties.getProperty(SQLServerDriverStringProperty.WORKSTATION_ID.toString()); if (StringUtils.isEmpty(hostName)) { hostName = Util.lookupHostName(); } - + // if the timeout is infinite slices are infinite too. tdsChannel = new TDSChannel(this); if (0 == timeOutFullInSeconds) @@ -2822,7 +2832,7 @@ final boolean doExecute() throws SQLServerException { * * @return the syntax string */ - /* L0 */ private String sqlStatementToInitialize() { + private String sqlStatementToInitialize() { String s = null; if (nLockTimeout > -1) s = " set lock_timeout " + nLockTimeout; @@ -2836,7 +2846,7 @@ final boolean doExecute() throws SQLServerException { * the new catalog * @return the required syntax */ - /* L0 */ void setCatalogName(String sDB) { + void setCatalogName(String sDB) { if (sDB != null) { if (sDB.length() > 0) { sCatalog = sDB; @@ -2849,7 +2859,7 @@ final boolean doExecute() throws SQLServerException { * * @return the required syntax */ - /* L0 */ String sqlStatementToSetTransactionIsolationLevel() throws SQLServerException { + String sqlStatementToSetTransactionIsolationLevel() throws SQLServerException { String sql = "set transaction isolation level "; switch (transactionIsolationLevel) { @@ -2891,34 +2901,39 @@ static String sqlStatementToSetCommit(boolean autoCommit) { return (true == autoCommit) ? "set implicit_transactions off " : "set implicit_transactions on "; } - /* L0 */ public Statement createStatement() throws SQLServerException { + @Override + public Statement createStatement() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "createStatement"); Statement st = createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); loggerExternal.exiting(getClassNameLogging(), "createStatement", st); return st; } - /* L0 */ public PreparedStatement prepareStatement(String sql) throws SQLServerException { + @Override + public PreparedStatement prepareStatement(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "prepareStatement", sql); PreparedStatement pst = prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); loggerExternal.exiting(getClassNameLogging(), "prepareStatement", pst); return pst; } - /* L0 */ public CallableStatement prepareCall(String sql) throws SQLServerException { + @Override + public CallableStatement prepareCall(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "prepareCall", sql); CallableStatement st = prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); loggerExternal.exiting(getClassNameLogging(), "prepareCall", st); return st; } - /* L0 */ public String nativeSQL(String sql) throws SQLServerException { + @Override + public String nativeSQL(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "nativeSQL", sql); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "nativeSQL", sql); return sql; } + @Override public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) { loggerExternal.entering(getClassNameLogging(), "setAutoCommit", newAutoCommitMode); @@ -2946,7 +2961,8 @@ public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setAutoCommit"); } - /* L0 */ public boolean getAutoCommit() throws SQLServerException { + @Override + public boolean getAutoCommit() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getAutoCommit"); checkClosed(); boolean res = !inXATransaction && databaseAutoCommitMode; @@ -2955,16 +2971,11 @@ public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException { return res; } - /* LO */ final byte[] getTransactionDescriptor() { + final byte[] getTransactionDescriptor() { return transactionDescriptor; } - /** - * Commit a transcation. Per our transaction spec, see also SDT#410729, a commit in autocommit mode = true is a NO-OP. - * - * @throws SQLServerException - * if no transaction exists. - */ + @Override public void commit() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "commit"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -2977,12 +2988,7 @@ public void commit() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "commit"); } - /** - * Rollback a transcation. - * - * @throws SQLServerException - * if no transaction exists or if the connection is in auto-commit mode. - */ + @Override public void rollback() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "rollback"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -2998,6 +3004,7 @@ public void rollback() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "rollback"); } + @Override public void abort(Executor executor) throws SQLException { loggerExternal.entering(getClassNameLogging(), "abort", executor); @@ -3027,17 +3034,13 @@ public void abort(Executor executor) throws SQLException { setState(State.Closed); - executor.execute(new Runnable() { - public void run() { - if (null != tdsChannel) { - tdsChannel.close(); - } - } - }); + if (null != tdsChannel) + executor.execute(() -> tdsChannel.close()); loggerExternal.exiting(getClassNameLogging(), "abort"); } + @Override public void close() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "close"); @@ -3062,7 +3065,7 @@ public void close() throws SQLServerException { // Clean-up queue etc. related to batching of prepared statement discard actions (sp_unprepare). cleanupPreparedStatementDiscardActions(); - + ActivityCorrelator.cleanupActivityId(); loggerExternal.exiting(getClassNameLogging(), "close"); @@ -3092,13 +3095,15 @@ final void poolCloseEventNotify() throws SQLServerException { } - /* L0 */ public boolean isClosed() throws SQLServerException { + @Override + public boolean isClosed() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "isClosed"); loggerExternal.exiting(getClassNameLogging(), "isClosed", isSessionUnAvailable()); return isSessionUnAvailable(); } - /* L0 */ public DatabaseMetaData getMetaData() throws SQLServerException { + @Override + public DatabaseMetaData getMetaData() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMetaData"); checkClosed(); if (databaseMetaData == null) { @@ -3108,7 +3113,8 @@ final void poolCloseEventNotify() throws SQLServerException { return databaseMetaData; } - /* L0 */ public void setReadOnly(boolean readOnly) throws SQLServerException { + @Override + public void setReadOnly(boolean readOnly) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setReadOnly", readOnly); checkClosed(); @@ -3116,7 +3122,8 @@ final void poolCloseEventNotify() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setReadOnly"); } - /* L0 */ public boolean isReadOnly() throws SQLServerException { + @Override + public boolean isReadOnly() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "isReadOnly"); checkClosed(); if (loggerExternal.isLoggable(Level.FINER)) @@ -3124,7 +3131,8 @@ final void poolCloseEventNotify() throws SQLServerException { return false; } - /* L0 */ public void setCatalog(String catalog) throws SQLServerException { + @Override + public void setCatalog(String catalog) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setCatalog", catalog); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -3137,7 +3145,8 @@ final void poolCloseEventNotify() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setCatalog"); } - /* L0 */ public String getCatalog() throws SQLServerException { + @Override + public String getCatalog() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getCatalog"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getCatalog", sCatalog); @@ -3148,7 +3157,8 @@ String getSCatalog() throws SQLServerException { return sCatalog; } - /* L0 */ public void setTransactionIsolation(int level) throws SQLServerException { + @Override + public void setTransactionIsolation(int level) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) { loggerExternal.entering(getClassNameLogging(), "setTransactionIsolation", level); if (Util.IsActivityTraceOn()) { @@ -3166,7 +3176,8 @@ String getSCatalog() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setTransactionIsolation"); } - /* L0 */ public int getTransactionIsolation() throws SQLServerException { + @Override + public int getTransactionIsolation() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTransactionIsolation"); checkClosed(); if (loggerExternal.isLoggable(Level.FINER)) @@ -3178,7 +3189,8 @@ String getSCatalog() throws SQLServerException { Object warningSynchronization = new Object(); // Think about returning a copy when we implement additional warnings. - /* L0 */ public SQLWarning getWarnings() throws SQLServerException { + @Override + public SQLWarning getWarnings() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getWarnings"); checkClosed(); // check null warn wont crash @@ -3200,7 +3212,8 @@ private void addWarning(String warningString) { } } - /* L2 */ public void clearWarnings() throws SQLServerException { + @Override + public void clearWarnings() throws SQLServerException { synchronized (warningSynchronization) { loggerExternal.entering(getClassNameLogging(), "clearWarnings"); checkClosed(); @@ -3210,38 +3223,35 @@ private void addWarning(String warningString) { } // --------------------------JDBC 2.0----------------------------- + @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "createStatement", - new Object[] {resultSetType, resultSetConcurrency}); + loggerExternal.entering(getClassNameLogging(), "createStatement", new Object[] {resultSetType, resultSetConcurrency}); checkClosed(); Statement st = new SQLServerStatement(this, resultSetType, resultSetConcurrency, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); + if (requestStarted) { + addOpenStatement(st); + } loggerExternal.exiting(getClassNameLogging(), "createStatement", st); return st; } + @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "prepareStatement", - new Object[] {sql, resultSetType, resultSetConcurrency}); + loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {sql, resultSetType, resultSetConcurrency}); checkClosed(); - PreparedStatement st; - - // Make sure SQLServerPreparedStatement42 is used for 4.2 and above. - if (Util.use42Wrapper() || Util.use43Wrapper()) { - st = new SQLServerPreparedStatement42(this, sql, resultSetType, resultSetConcurrency, - SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); - } - else { - st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, - SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); - } + PreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, + SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); + if (requestStarted) { + addOpenStatement(st); + } loggerExternal.exiting(getClassNameLogging(), "prepareStatement", st); return st; } @@ -3255,45 +3265,37 @@ private PreparedStatement prepareStatement(String sql, new Object[] {sql, resultSetType, resultSetConcurrency, stmtColEncSetting}); checkClosed(); - PreparedStatement st; + PreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, stmtColEncSetting); - // Make sure SQLServerPreparedStatement42 is used for 4.2 and above. - if (Util.use42Wrapper() || Util.use43Wrapper()) { - st = new SQLServerPreparedStatement42(this, sql, resultSetType, resultSetConcurrency, stmtColEncSetting); - } - else { - st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, stmtColEncSetting); + if (requestStarted) { + addOpenStatement(st); } loggerExternal.exiting(getClassNameLogging(), "prepareStatement", st); return st; } + @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "prepareCall", - new Object[] {sql, resultSetType, resultSetConcurrency}); + loggerExternal.entering(getClassNameLogging(), "prepareCall", new Object[] {sql, resultSetType, resultSetConcurrency}); checkClosed(); - CallableStatement st; + CallableStatement st = new SQLServerCallableStatement(this, sql, resultSetType, resultSetConcurrency, + SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); - // Make sure SQLServerCallableStatement42 is used for 4.2 and above. - if (Util.use42Wrapper() || Util.use43Wrapper()) { - st = new SQLServerCallableStatement42(this, sql, resultSetType, resultSetConcurrency, - SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); - } - else { - st = new SQLServerCallableStatement(this, sql, resultSetType, resultSetConcurrency, - SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); + if (requestStarted) { + addOpenStatement(st); } loggerExternal.exiting(getClassNameLogging(), "prepareCall", st); return st; } - /* L2 */ public void setTypeMap(java.util.Map> map) throws SQLServerException { + @Override + public void setTypeMap(java.util.Map> map) throws SQLException { loggerExternal.entering(getClassNameLogging(), "setTypeMap", map); checkClosed(); if (map != null && (map instanceof java.util.HashMap)) { @@ -3304,9 +3306,10 @@ public CallableStatement prepareCall(String sql, } } - NotImplemented(); + SQLServerException.throwNotSupportedException(this, null); } + @Override public java.util.Map> getTypeMap() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTypeMap"); checkClosed(); @@ -3324,9 +3327,9 @@ int writeAEFeatureRequest(boolean write, int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version) if (write) { - tdsWriter.writeByte((byte) TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TCE + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TCE tdsWriter.writeInt(1); - tdsWriter.writeByte((byte) TDS.MAX_SUPPORTED_TCE_VERSION); + tdsWriter.writeByte(TDS.MAX_SUPPORTED_TCE_VERSION); } return len; } @@ -3337,7 +3340,6 @@ int writeFedAuthFeatureRequest(boolean write, * if false just calculates the * length */ - assert (fedAuthFeatureExtensionData.libraryType == TDS.TDS_FEDAUTH_LIBRARY_ADAL || fedAuthFeatureExtensionData.libraryType == TDS.TDS_FEDAUTH_LIBRARY_SECURITYTOKEN); @@ -3421,6 +3423,28 @@ int writeFedAuthFeatureRequest(boolean write, } return totalLen; } + + int writeDataClassificationFeatureRequest(boolean write /* if false just calculates the length */, + TDSWriter tdsWriter) throws SQLServerException { + int len = 6; // 1byte = featureID, 4bytes = featureData length, 1 bytes = Version + if (write) { + // Write Feature ID, length of the version# field and Sensitivity Classification Version# + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_DATACLASSIFICATION); + tdsWriter.writeInt(1); + tdsWriter.writeByte(TDS.MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION); + } + return len; // size of data written + } + + int writeUTF8SupportFeatureRequest(boolean write, + TDSWriter tdsWriter /* if false just calculates the length */) throws SQLServerException { + int len = 5; // 1byte = featureID, 4bytes = featureData length + if (write) { + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_UTF8SUPPORT); + tdsWriter.writeInt(0); + } + return len; + } private final class LogonCommand extends UninterruptableTDSCommand { LogonCommand() { @@ -3433,7 +3457,7 @@ final boolean doExecute() throws SQLServerException { } } - /* L0 */ private void logon(LogonCommand command) throws SQLServerException { + private void logon(LogonCommand command) throws SQLServerException { SSPIAuthentication authentication = null; if (integratedSecurity && AuthenticationScheme.nativeAuthentication == intAuthScheme) authentication = new AuthenticationJNI(this, currentConnectPlaceHolder.getServerName(), currentConnectPlaceHolder.getPortNumber()); @@ -3476,7 +3500,8 @@ final boolean doExecute() throws SQLServerException { connectionCommand(sqlStmt, "Change Settings"); } } - } finally { + } + finally { if (integratedSecurity) { if (null != authentication) { authentication.ReleaseClientContext(); @@ -3502,6 +3527,7 @@ final boolean doExecute() throws SQLServerException { private static final int ENVCHANGE_DTC_ENLIST = 11; private static final int ENVCHANGE_DTC_DEFECT = 12; private static final int ENVCHANGE_CHANGE_MIRROR = 13; + @SuppressWarnings("unused") private static final int ENVCHANGE_UNUSED_14 = 14; private static final int ENVCHANGE_DTC_PROMOTE = 15; private static final int ENVCHANGE_DTC_MGR_ADDR = 16; @@ -3536,7 +3562,7 @@ final void processEnvChange(TDSReader tdsReader) throws SQLServerException { try { databaseCollation = new SQLCollation(tdsReader); } - catch (UnsupportedEncodingException e) { + catch (java.io.UnsupportedEncodingException e) { terminate(SQLServerException.DRIVER_ERROR_INVALID_TDS, e.getMessage(), e); } @@ -3664,8 +3690,11 @@ final void processEnvChange(TDSReader tdsReader) throws SQLServerException { // Check if the hostNameInCertificate needs to be updated to handle the rerouted subdomain in Azure String currentHostName = activeConnectionProperties.getProperty("hostNameInCertificate"); - if (null != currentHostName && currentHostName.startsWith("*") - && (null != routingServerName) /* skip the check for hostNameInCertificate if routingServerName is null */ + if (null != currentHostName && currentHostName.startsWith("*") && (null != routingServerName) /* + * skip the check for + * hostNameInCertificate if + * routingServerName is null + */ && routingServerName.indexOf('.') != -1) { char[] currentHostNameCharArray = currentHostName.toCharArray(); char[] routingServerNameCharArray = routingServerName.toCharArray(); @@ -3694,6 +3723,7 @@ final void processEnvChange(TDSReader tdsReader) throws SQLServerException { isRoutedInCurrentAttempt = true; routingInfo = new ServerPortPlaceHolder(routingServerName, routingPortNumber, null, integratedSecurity); + break; // Error on unrecognized, unused ENVCHANGES @@ -3900,7 +3930,7 @@ private SqlFedAuthToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLSe // No:of milliseconds to sleep for the inital back off. int sleepInterval = 100; - + while (true) { if (authenticationString.trim().equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString())) { fedAuthToken = SQLServerADAL4JUtils.getSqlFedAuthToken(fedAuthInfo, user, password, authenticationString); @@ -3909,7 +3939,7 @@ private SqlFedAuthToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLSe break; } else if (authenticationString.trim().equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString())) { - + // If operating system is windows and sqljdbc_auth is loaded then choose the DLL authentication. if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows") && AuthenticationJNI.isDllLoaded()) { try { @@ -4046,7 +4076,7 @@ final void processFeatureExtAck(TDSReader tdsReader) throws SQLServerException { while (featureId != TDS.FEATURE_EXT_TERMINATOR); } - private void onFeatureExtAck(int featureId, + private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerException { if (null != routingInfo) { return; @@ -4092,8 +4122,6 @@ private void onFeatureExtAck(int featureId, Object[] msgArgs = {fedAuthFeatureExtensionData.libraryType}; throw new SQLServerException(form.format(msgArgs), null); } - federatedAuthenticationAcknowledged = true; - break; } case TDS.TDS_FEATURE_EXT_AE: { @@ -4116,11 +4144,46 @@ private void onFeatureExtAck(int featureId, throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - assert supportedTceVersion == TDS.MAX_SUPPORTED_TCE_VERSION; // Client support TCE version 1 serverSupportsColumnEncryption = true; break; } + case TDS.TDS_FEATURE_EXT_DATACLASSIFICATION: { + if (connectionlogger.isLoggable(Level.FINER)) { + connectionlogger.fine(toString() + " Received feature extension acknowledgement for Data Classification."); + } + if (2 != data.length) { + if (connectionlogger.isLoggable(Level.SEVERE)) { + connectionlogger.severe(toString() + " Unknown token for Data Classification."); + } + throw new SQLServerException(SQLServerException.getErrString("R_UnknownDataClsTokenNumber"), null); + } + + byte supportedDataClassificationVersion = data[0]; + if ((0 == supportedDataClassificationVersion) + || (supportedDataClassificationVersion > TDS.MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION)) { + if (connectionlogger.isLoggable(Level.SEVERE)) { + connectionlogger.severe(toString() + " Invalid version number for Data Classification"); + } + throw new SQLServerException(SQLServerException.getErrString("R_InvalidDataClsVersionNumber"), null); + } + + byte enabled = data[1]; + serverSupportsDataClassification = (enabled == 0) ? false : true; + } + case TDS.TDS_FEATURE_EXT_UTF8SUPPORT: { + if (connectionlogger.isLoggable(Level.FINER)) { + connectionlogger.fine(toString() + " Received feature extension acknowledgement for UTF8 support."); + } + + if (1 > data.length) { + if (connectionlogger.isLoggable(Level.SEVERE)) { + connectionlogger.severe(toString() + " Unknown value for UTF8 support."); + } + throw new SQLServerException(SQLServerException.getErrString("R_unknownUTF8SupportValue"), null); + } + break; + } default: { // Unknown feature ack if (connectionlogger.isLoggable(Level.SEVERE)) { @@ -4206,7 +4269,7 @@ final void JTAEnlistConnection(byte cookie[]) throws SQLServerException { * @throws SQLServerException * @return the encoded data */ - /* L0 */ private byte[] toUCS16(String s) throws SQLServerException { + private byte[] toUCS16(String s) throws SQLServerException { if (s == null) return new byte[0]; int l = s.length(); @@ -4228,7 +4291,7 @@ final void JTAEnlistConnection(byte cookie[]) throws SQLServerException { * the password * @return the encryption */ - /* L0 */ private byte[] encryptPassword(String pwd) { + private byte[] encryptPassword(String pwd) { // Changed to handle non ascii passwords if (pwd == null) pwd = ""; @@ -4407,7 +4470,12 @@ else if (serverMajorVersion >= 9) // Yukon (9.0) --> TDS 7.2 // Prelogin disconn len2 = len2 + writeFedAuthFeatureRequest(false, tdsWriter, fedAuthFeatureExtensionData); } - len2 = len2 + 1; // add 1 to length becaue of FeatureEx terminator + // Data Classification is always enabled (by default) + len2 += writeDataClassificationFeatureRequest(false, tdsWriter); + + len2 = len2 + writeUTF8SupportFeatureRequest(false, tdsWriter); + + len2 = len2 + 1; // add 1 to length because of FeatureEx terminator // Length of entire Login 7 packet tdsWriter.writeInt(len2); @@ -4434,8 +4502,9 @@ else if (serverMajorVersion >= 9) // Yukon (9.0) --> TDS 7.2 // Prelogin disconn TDS.LOGIN_OPTION2_INTEGRATED_SECURITY_ON : TDS.LOGIN_OPTION2_INTEGRATED_SECURITY_OFF))); // TypeFlags - tdsWriter.writeByte((byte) (TDS.LOGIN_SQLTYPE_DEFAULT | (applicationIntent != null && applicationIntent.equals(ApplicationIntent.READ_ONLY) - ? TDS.LOGIN_READ_ONLY_INTENT : TDS.LOGIN_READ_WRITE_INTENT))); + tdsWriter.writeByte((byte) (TDS.LOGIN_SQLTYPE_DEFAULT + | (applicationIntent != null && applicationIntent.equals(ApplicationIntent.READ_ONLY) ? TDS.LOGIN_READ_ONLY_INTENT + : TDS.LOGIN_READ_WRITE_INTENT))); // OptionFlags3 byte colEncSetting; @@ -4588,6 +4657,9 @@ else if (serverMajorVersion >= 9) // Yukon (9.0) --> TDS 7.2 // Prelogin disconn writeFedAuthFeatureRequest(true, tdsWriter, fedAuthFeatureExtensionData); } + writeDataClassificationFeatureRequest(true, tdsWriter); + writeUTF8SupportFeatureRequest(true, tdsWriter); + tdsWriter.writeByte((byte) TDS.FEATURE_EXT_TERMINATOR); tdsWriter.setDataLoggable(true); @@ -4626,123 +4698,92 @@ private void checkMatchesCurrentHoldability(int resultSetHoldability) throws SQL } } + @Override public Statement createStatement(int nType, int nConcur, int resultSetHoldability) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "createStatement", - new Object[] {nType, nConcur, resultSetHoldability}); + loggerExternal.entering(getClassNameLogging(), "createStatement", new Object[] {nType, nConcur, resultSetHoldability}); Statement st = createStatement(nType, nConcur, resultSetHoldability, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); loggerExternal.exiting(getClassNameLogging(), "createStatement", st); return st; } + @Override public Statement createStatement(int nType, int nConcur, int resultSetHoldability, SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "createStatement", - new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetting}); + loggerExternal.entering(getClassNameLogging(), "createStatement", new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetting}); checkClosed(); checkValidHoldability(resultSetHoldability); checkMatchesCurrentHoldability(resultSetHoldability); Statement st = new SQLServerStatement(this, nType, nConcur, stmtColEncSetting); + if (requestStarted) { + addOpenStatement(st); + } loggerExternal.exiting(getClassNameLogging(), "createStatement", st); return st; } - /* L3 */ public PreparedStatement prepareStatement(java.lang.String sql, + @Override + public PreparedStatement prepareStatement(java.lang.String sql, int nType, int nConcur, int resultSetHoldability) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "prepareStatement", - new Object[] {nType, nConcur, resultSetHoldability}); + loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {nType, nConcur, resultSetHoldability}); PreparedStatement st = prepareStatement(sql, nType, nConcur, resultSetHoldability, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); loggerExternal.exiting(getClassNameLogging(), "prepareStatement", st); return st; } - /** - * Creates a PreparedStatement object that will generate ResultSet objects with the given type, concurrency, and - * holdability. - *

- * This method is the same as the prepareStatement method above, but it allows the default result set type, concurrency, and - * holdability to be overridden. - * - * @param sql - * a String object that is the SQL statement to be sent to the database; may contain one or more '?' IN parameters - * @param nType - * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, - * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE - * @param nConcur - * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or - * ResultSet.CONCUR_UPDATABLE - * @param resultSetHoldability - * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or - * ResultSet.CLOSE_CURSORS_AT_COMMIT - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will generate ResultSet - * objects with the given type, concurrency, and holdability - * @throws SQLServerException - * if a database access error occurs, this method is called on a closed connection or the given parameters are not - * ResultSet constants indicating type, concurrency, and holdability - */ + @Override public PreparedStatement prepareStatement(java.lang.String sql, int nType, int nConcur, int resultSetHoldability, SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "prepareStatement", - new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetting}); + loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetting}); checkClosed(); checkValidHoldability(resultSetHoldability); checkMatchesCurrentHoldability(resultSetHoldability); - PreparedStatement st; + PreparedStatement st = new SQLServerPreparedStatement(this, sql, nType, nConcur, stmtColEncSetting); - // Make sure SQLServerPreparedStatement42 is used for 4.2 and above. - if (Util.use42Wrapper() || Util.use43Wrapper()) { - st = new SQLServerPreparedStatement42(this, sql, nType, nConcur, stmtColEncSetting); - } - else { - st = new SQLServerPreparedStatement(this, sql, nType, nConcur, stmtColEncSetting); + if (requestStarted) { + addOpenStatement(st); } loggerExternal.exiting(getClassNameLogging(), "prepareStatement", st); return st; } - /* L3 */ public CallableStatement prepareCall(String sql, + @Override + public CallableStatement prepareCall(String sql, int nType, int nConcur, int resultSetHoldability) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "prepareStatement", - new Object[] {nType, nConcur, resultSetHoldability}); + loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {nType, nConcur, resultSetHoldability}); CallableStatement st = prepareCall(sql, nType, nConcur, resultSetHoldability, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); loggerExternal.exiting(getClassNameLogging(), "prepareCall", st); return st; } + @Override public CallableStatement prepareCall(String sql, int nType, int nConcur, int resultSetHoldability, SQLServerStatementColumnEncryptionSetting stmtColEncSetiing) throws SQLServerException { - loggerExternal.entering(getClassNameLogging(), "prepareStatement", - new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetiing}); + loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {nType, nConcur, resultSetHoldability, stmtColEncSetiing}); checkClosed(); checkValidHoldability(resultSetHoldability); checkMatchesCurrentHoldability(resultSetHoldability); - CallableStatement st; + CallableStatement st = new SQLServerCallableStatement(this, sql, nType, nConcur, stmtColEncSetiing); - // Make sure SQLServerCallableStatement42 is used for 4.2 and above - if (Util.use42Wrapper() || Util.use43Wrapper()) { - st = new SQLServerCallableStatement42(this, sql, nType, nConcur, stmtColEncSetiing); - } - else { - st = new SQLServerCallableStatement(this, sql, nType, nConcur, stmtColEncSetiing); + if (requestStarted) { + addOpenStatement(st); } loggerExternal.exiting(getClassNameLogging(), "prepareCall", st); @@ -4751,7 +4792,8 @@ public CallableStatement prepareCall(String sql, /* JDBC 3.0 Auto generated keys */ - /* L3 */ public PreparedStatement prepareStatement(String sql, + @Override + public PreparedStatement prepareStatement(String sql, int flag) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {sql, flag}); @@ -4762,33 +4804,7 @@ public CallableStatement prepareCall(String sql, return ps; } - /** - * Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys. The given constant tells the - * driver whether it should make auto-generated keys available for retrieval. This parameter is ignored if the SQL statement is not an - * INSERT statement, or an SQL statement able to return auto-generated keys (the list of such statements is vendor-specific). - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param flag - * a flag indicating whether auto-generated keys should be returned; one of Statement.RETURN_GENERATED_KEYS or - * Statement.NO_GENERATED_KEYS - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will have the capability of returning - * auto-generated keys - * @throws SQLServerException - * if a database access error occurs, this method is called on a closed connection or the given parameter is not a - * Statement constant indicating whether auto-generated keys should be returned - */ + @Override public PreparedStatement prepareStatement(String sql, int flag, SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { @@ -4801,7 +4817,8 @@ public PreparedStatement prepareStatement(String sql, return ps; } - /* L3 */ public PreparedStatement prepareStatement(String sql, + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {sql, columnIndexes}); SQLServerPreparedStatement ps = (SQLServerPreparedStatement) prepareStatement(sql, columnIndexes, @@ -4811,35 +4828,7 @@ public PreparedStatement prepareStatement(String sql, return ps; } - /** - * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array - * contains the indexes of the columns in the target table that contain the auto-generated keys that should be made available. The driver will - * ignore the array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list - * of such statements is vendor-specific). - *

- * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then - * be used to efficiently execute this statement multiple times. - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param columnIndexes - * an array of column indexes indicating the columns that should be returned from the inserted row or rows - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated - * keys designated by the given array of column indexes - * @throws SQLServerException - * if a database access error occurs or this method is called on a closed connection - */ + @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes, SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { @@ -4856,7 +4845,8 @@ public PreparedStatement prepareStatement(String sql, return ps; } - /* L3 */ public PreparedStatement prepareStatement(String sql, + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "prepareStatement", new Object[] {sql, columnNames}); @@ -4867,35 +4857,7 @@ public PreparedStatement prepareStatement(String sql, return ps; } - /** - * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array - * contains the names of the columns in the target table that contain the auto-generated keys that should be returned. The driver will ignore the - * array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list of such - * statements is vendor-specific). - *

- * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then - * be used to efficiently execute this statement multiple times. - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param columnNames - * an array of column names indicating the columns that should be returned from the inserted row or rows - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated - * keys designated by the given array of column names - * @throws SQLServerException - * if a database access error occurs or this method is called on a closed connection - */ + @Override public PreparedStatement prepareStatement(String sql, String[] columnNames, SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { @@ -4913,9 +4875,10 @@ public PreparedStatement prepareStatement(String sql, /* JDBC 3.0 Savepoints */ - public void releaseSavepoint(Savepoint savepoint) throws SQLServerException { + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { loggerExternal.entering(getClassNameLogging(), "releaseSavepoint", savepoint); - NotImplemented(); + SQLServerException.throwNotSupportedException(this, null); } final private Savepoint setNamedSavepoint(String sName) throws SQLServerException { @@ -4938,7 +4901,8 @@ final private Savepoint setNamedSavepoint(String sName) throws SQLServerExceptio return s; } - /* L3 */ public Savepoint setSavepoint(String sName) throws SQLServerException { + @Override + public Savepoint setSavepoint(String sName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setSavepoint", sName); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -4949,7 +4913,8 @@ final private Savepoint setNamedSavepoint(String sName) throws SQLServerExceptio return pt; } - /* L3 */ public Savepoint setSavepoint() throws SQLServerException { + @Override + public Savepoint setSavepoint() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setSavepoint"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -4960,7 +4925,8 @@ final private Savepoint setNamedSavepoint(String sName) throws SQLServerExceptio return pt; } - /* L3 */ public void rollback(Savepoint s) throws SQLServerException { + @Override + public void rollback(Savepoint s) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "rollback", s); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -4973,13 +4939,15 @@ final private Savepoint setNamedSavepoint(String sName) throws SQLServerExceptio loggerExternal.exiting(getClassNameLogging(), "rollback"); } - /* L3 */ public int getHoldability() throws SQLServerException { + @Override + public int getHoldability() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getHoldability"); if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.exiting(getClassNameLogging(), "getHoldability", holdability); return holdability; } + @Override public void setHoldability(int holdability) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setHoldability", holdability); @@ -5002,6 +4970,7 @@ public void setHoldability(int holdability) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setHoldability"); } + @Override public int getNetworkTimeout() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNetworkTimeout"); @@ -5019,6 +4988,7 @@ public int getNetworkTimeout() throws SQLException { return timeout; } + @Override public void setNetworkTimeout(Executor executor, int timeout) throws SQLException { loggerExternal.entering(getClassNameLogging(), "setNetworkTimeout", timeout); @@ -5030,7 +5000,7 @@ public void setNetworkTimeout(Executor executor, } checkClosed(); - + // check for setNetworkTimeout permission SecurityManager secMgr = System.getSecurityManager(); if (secMgr != null) { @@ -5055,6 +5025,7 @@ public void setNetworkTimeout(Executor executor, loggerExternal.exiting(getClassNameLogging(), "setNetworkTimeout"); } + @Override public String getSchema() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getSchema"); @@ -5094,6 +5065,7 @@ public String getSchema() throws SQLException { return null; } + @Override public void setSchema(String schema) throws SQLException { loggerExternal.entering(getClassNameLogging(), "setSchema", schema); checkClosed(); @@ -5102,61 +5074,58 @@ public void setSchema(String schema) throws SQLException { loggerExternal.exiting(getClassNameLogging(), "setSchema"); } - /** - * Modifies the setting of the sendTimeAsDatetime connection property. When true, java.sql.Time values will be sent to the server as SQL - * Serverdatetime values. When false, java.sql.Time values will be sent to the server as SQL Servertime values. sendTimeAsDatetime can also be - * modified programmatically with SQLServerDataSource.setSendTimeAsDatetime. The default value for this property may change in a future release. - * - * @param sendTimeAsDateTimeValue - * enables/disables setting the sendTimeAsDatetime connection property. For more information about how the Microsoft JDBC Driver for - * SQL Server configures java.sql.Time values before sending them to the server, see - * Configuring How java.sql.Time Values are Sent to the - * Server. - */ - public synchronized void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) { + @Override + public void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) { sendTimeAsDatetime = sendTimeAsDateTimeValue; } + @Override public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(this, null); + return null; } - public Blob createBlob() throws SQLException { + @Override + public java.sql.Blob createBlob() throws SQLException { checkClosed(); return new SQLServerBlob(this); } - public Clob createClob() throws SQLException { + @Override + public java.sql.Clob createClob() throws SQLException { checkClosed(); return new SQLServerClob(this); } - public NClob createNClob() throws SQLException { + @Override + public java.sql.NClob createNClob() throws SQLException { checkClosed(); return new SQLServerNClob(this); } + @Override public SQLXML createSQLXML() throws SQLException { loggerExternal.entering(getClassNameLogging(), "createSQLXML"); - SQLXML sqlxml = new SQLServerSQLXML(this); + SQLXML sqlxml = new SQLServerSQLXML(this); if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.exiting(getClassNameLogging(), "createSQLXML", sqlxml); return sqlxml; } - public Struct createStruct(String typeName, + @Override + public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(this, null); + return null; } String getTrustedServerNameAE() throws SQLServerException { return trustedServerNameAE.toUpperCase(); } + @Override public Properties getClientInfo() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getClientInfo"); checkClosed(); @@ -5165,6 +5134,7 @@ public Properties getClientInfo() throws SQLException { return p; } + @Override public String getClientInfo(String name) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getClientInfo", name); checkClosed(); @@ -5172,6 +5142,7 @@ public String getClientInfo(String name) throws SQLException { return null; } + @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { loggerExternal.entering(getClassNameLogging(), "setClientInfo", properties); // This function is only marked as throwing only SQLClientInfoException so the conversion is necessary @@ -5195,6 +5166,7 @@ public void setClientInfo(Properties properties) throws SQLClientInfoException { loggerExternal.exiting(getClassNameLogging(), "setClientInfo"); } + @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { loggerExternal.entering(getClassNameLogging(), "setClientInfo", new Object[] {name, value}); @@ -5231,6 +5203,7 @@ public void setClientInfo(String name, * @throws SQLException * if the value supplied for the timeout is less than 0. */ + @Override public boolean isValid(int timeout) throws SQLException { boolean isValid = false; @@ -5274,6 +5247,7 @@ public boolean isValid(int timeout) throws SQLException { return isValid; } + @Override public boolean isWrapperFor(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "isWrapperFor", iface); boolean f = iface.isInstance(this); @@ -5281,6 +5255,7 @@ public boolean isWrapperFor(Class iface) throws SQLException { return f; } + @Override public T unwrap(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "unwrap", iface); T t; @@ -5296,14 +5271,91 @@ public T unwrap(Class iface) throws SQLException { return t; } - public void beginRequest() throws SQLFeatureNotSupportedException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLFeatureNotSupportedException("beginRequest not implemented"); - } - - public void endRequest() throws SQLFeatureNotSupportedException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLFeatureNotSupportedException("endRequest not implemented"); + private boolean requestStarted = false; + private boolean originalDatabaseAutoCommitMode; + private int originalTransactionIsolationLevel; + private int originalNetworkTimeout; + private int originalHoldability; + private boolean originalSendTimeAsDatetime; + private int originalStatementPoolingCacheSize; + private boolean originalDisableStatementPooling; + private int originalServerPreparedStatementDiscardThreshold; + private Boolean originalEnablePrepareOnFirstPreparedStatementCall; + private String originalSCatalog; + private volatile SQLWarning originalSqlWarnings; + private List openStatements; + + protected void beginRequestInternal() throws SQLException { + loggerExternal.entering(getClassNameLogging(), "beginRequest", this); + synchronized (this) { + if (!requestStarted) { + originalDatabaseAutoCommitMode = databaseAutoCommitMode; + originalTransactionIsolationLevel = transactionIsolationLevel; + originalNetworkTimeout = getNetworkTimeout(); + originalHoldability = holdability; + originalSendTimeAsDatetime = sendTimeAsDatetime; + originalStatementPoolingCacheSize = statementPoolingCacheSize; + originalDisableStatementPooling = disableStatementPooling; + originalServerPreparedStatementDiscardThreshold = getServerPreparedStatementDiscardThreshold(); + originalEnablePrepareOnFirstPreparedStatementCall = getEnablePrepareOnFirstPreparedStatementCall(); + originalSCatalog = sCatalog; + originalSqlWarnings = sqlWarnings; + openStatements = new LinkedList(); + requestStarted = true; + } + } + loggerExternal.exiting(getClassNameLogging(), "beginRequest", this); + } + + protected void endRequestInternal() throws SQLException { + loggerExternal.entering(getClassNameLogging(), "endRequest", this); + synchronized (this) { + if (requestStarted) { + if (!databaseAutoCommitMode) { + rollback(); + } + if (databaseAutoCommitMode != originalDatabaseAutoCommitMode) { + setAutoCommit(originalDatabaseAutoCommitMode); + } + if (transactionIsolationLevel != originalTransactionIsolationLevel) { + setTransactionIsolation(originalTransactionIsolationLevel); + } + if (getNetworkTimeout() != originalNetworkTimeout) { + setNetworkTimeout(null, originalNetworkTimeout); + } + if (holdability != originalHoldability) { + setHoldability(originalHoldability); + } + if (sendTimeAsDatetime != originalSendTimeAsDatetime) { + setSendTimeAsDatetime(originalSendTimeAsDatetime); + } + if (statementPoolingCacheSize != originalStatementPoolingCacheSize) { + setStatementPoolingCacheSize(originalStatementPoolingCacheSize); + } + if (disableStatementPooling != originalDisableStatementPooling) { + setDisableStatementPooling(originalDisableStatementPooling); + } + if (getServerPreparedStatementDiscardThreshold() != originalServerPreparedStatementDiscardThreshold) { + setServerPreparedStatementDiscardThreshold(originalServerPreparedStatementDiscardThreshold); + } + if (getEnablePrepareOnFirstPreparedStatementCall() != originalEnablePrepareOnFirstPreparedStatementCall) { + setEnablePrepareOnFirstPreparedStatementCall(originalEnablePrepareOnFirstPreparedStatementCall); + } + if (!sCatalog.equals(originalSCatalog)) { + setCatalog(originalSCatalog); + } + sqlWarnings = originalSqlWarnings; + if (null != openStatements) { + while (!openStatements.isEmpty()) { + try (Statement st = openStatements.get(0)) { + } + } + openStatements.clear(); + } + requestStarted = false; + } + } + loggerExternal.exiting(getClassNameLogging(), "endRequest", this); } /** @@ -5316,7 +5368,7 @@ public void endRequest() throws SQLFeatureNotSupportedException { */ static final char[] OUT = {' ', 'O', 'U', 'T'}; - /* L0 */ String replaceParameterMarkers(String sqlSrc, + String replaceParameterMarkers(String sqlSrc, Parameter[] params, boolean isReturnValueSyntax) throws SQLServerException { final int MAX_PARAM_NAME_LEN = 6; @@ -5361,7 +5413,7 @@ public void endRequest() throws SQLFeatureNotSupportedException { * @param offset * @return int */ - /* L0 */ static int makeParamName(int nParam, + static int makeParamName(int nParam, char[] name, int offset) { name[offset + 0] = '@'; @@ -5499,8 +5551,7 @@ String getInstancePort(String server, datagramSocket.receive(udpResponse); browserResult = new String(receiveBuffer, 3, receiveBuffer.length - 3); if (connectionlogger.isLoggable(Level.FINER)) - connectionlogger.fine( - toString() + " Received SSRP UDP response from IP address: " + udpResponse.getAddress().getHostAddress()); + connectionlogger.fine(toString() + " Received SSRP UDP response from IP address: " + udpResponse.getAddress().getHostAddress()); } catch (IOException ioException) { // Warn and retry @@ -5534,7 +5585,7 @@ String getInstancePort(String server, return browserResult.substring(p1, p2); } - /* L0 */ int getNextSavepointId() { + int getNextSavepointId() { nNextSavePointId++; // Make them unique for this connection return nNextSavePointId; } @@ -5575,16 +5626,15 @@ public static synchronized void setColumnEncryptionKeyCacheTtl(int columnEncrypt static synchronized long getColumnEncryptionKeyCacheTtl() { return columnEncryptionKeyCacheTtl; } - /** * Enqueue a discarded prepared statement handle to be clean-up on the server. * * @param statementHandle - * The prepared statement handle that should be scheduled for unprepare. + * The prepared statement handle that should be scheduled for unprepare. */ final void enqueueUnprepareStatementHandle(PreparedStatementHandle statementHandle) { - if(null == statementHandle) + if (null == statementHandle) return; if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5595,19 +5645,12 @@ final void enqueueUnprepareStatementHandle(PreparedStatementHandle statementHand this.discardedPreparedStatementHandleCount.incrementAndGet(); } - - /** - * Returns the number of currently outstanding prepared statement un-prepare actions. - * - * @return Returns the current value per the description. - */ + @Override public int getDiscardedServerPreparedStatementCount() { return this.discardedPreparedStatementHandleCount.get(); } - /** - * Forces the un-prepare requests for any outstanding discarded prepared statements to be executed. - */ + @Override public void closeUnreferencedPreparedStatementHandles() { this.unprepareUnreferencedPreparedStatementHandles(true); } @@ -5620,43 +5663,20 @@ private final void cleanupPreparedStatementDiscardActions() { discardedPreparedStatementHandleCount.set(0); } - /** - * Returns the behavior for a specific connection instance. If false the first execution will call sp_executesql and not prepare - * a statement, once the second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following - * executions will call sp_execute. This relieves the need for sp_unprepare on prepared statement close if the statement is only - * executed once. The default for this option can be changed by calling setDefaultEnablePrepareOnFirstPreparedStatementCall(). - * - * @return Returns the current setting per the description. - */ + @Override public boolean getEnablePrepareOnFirstPreparedStatementCall() { - if(null == this.enablePrepareOnFirstPreparedStatementCall) + if (null == this.enablePrepareOnFirstPreparedStatementCall) return DEFAULT_ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT_CALL; else - return this.enablePrepareOnFirstPreparedStatementCall; + return this.enablePrepareOnFirstPreparedStatementCall; } - /** - * Specifies the behavior for a specific connection instance. If value is false the first execution will call sp_executesql and not prepare - * a statement, once the second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following - * executions will call sp_execute. This relieves the need for sp_unprepare on prepared statement close if the statement is only - * executed once. - * - * @param value - * Changes the setting per the description. - */ + @Override public void setEnablePrepareOnFirstPreparedStatementCall(boolean value) { this.enablePrepareOnFirstPreparedStatementCall = value; } - /** - * Returns the behavior for a specific connection instance. This setting controls how many outstanding prepared statement discard actions - * (sp_unprepare) can be outstanding per connection before a call to clean-up the outstanding handles on the server is executed. If the setting is - * {@literal <=} 1, unprepare actions will be executed immedietely on prepared statement close. If it is set to {@literal >} 1, these calls - * will be batched together to avoid overhead of calling sp_unprepare too often. The default for this option can be changed by calling - * getDefaultServerPreparedStatementDiscardThreshold(). - * - * @return Returns the current setting per the description. - */ + @Override public int getServerPreparedStatementDiscardThreshold() { if (0 > this.serverPreparedStatementDiscardThreshold) return DEFAULT_SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD; @@ -5664,32 +5684,24 @@ public int getServerPreparedStatementDiscardThreshold() { return this.serverPreparedStatementDiscardThreshold; } - /** - * Specifies the behavior for a specific connection instance. This setting controls how many outstanding prepared statement discard actions - * (sp_unprepare) can be outstanding per connection before a call to clean-up the outstanding handles on the server is executed. If the setting is - * {@literal <=} 1 unprepare actions will be executed immedietely on prepared statement close. If it is set to {@literal >} 1 these calls will be - * batched together to avoid overhead of calling sp_unprepare too often. - * - * @param value - * Changes the setting per the description. - */ + @Override public void setServerPreparedStatementDiscardThreshold(int value) { this.serverPreparedStatementDiscardThreshold = Math.max(0, value); } final boolean isPreparedStatementUnprepareBatchingEnabled() { - return 1 < getServerPreparedStatementDiscardThreshold(); + return 1 < getServerPreparedStatementDiscardThreshold(); } /** * Cleans-up discarded prepared statement handles on the server using batched un-prepare actions if the batching threshold has been reached. * - * @param force - * When force is set to true we ignore the current threshold for if the discard actions should run and run them anyway. + * @param force + * When force is set to true we ignore the current threshold for if the discard actions should run and run them anyway. */ final void unprepareUnreferencedPreparedStatementHandles(boolean force) { // Skip out if session is unavailable to adhere to previous non-batched behavior. - if (isSessionUnAvailable()) + if (isSessionUnAvailable()) return; final int threshold = getServerPreparedStatementDiscardThreshold(); @@ -5698,33 +5710,32 @@ final void unprepareUnreferencedPreparedStatementHandles(boolean force) { if (force || threshold < getDiscardedServerPreparedStatementCount()) { // Create batch of sp_unprepare statements. - StringBuilder sql = new StringBuilder(threshold * 32/*EXEC sp_cursorunprepare++;*/); + StringBuilder sql = new StringBuilder(threshold * 32/* EXEC sp_cursorunprepare++; */); // Build the string containing no more than the # of handles to remove. - // Note that sp_unprepare can fail if the statement is already removed. - // However, the server will only abort that statement and continue with + // Note that sp_unprepare can fail if the statement is already removed. + // However, the server will only abort that statement and continue with // the remaining clean-up. int handlesRemoved = 0; PreparedStatementHandle statementHandle = null; - while (null != (statementHandle = discardedPreparedStatementHandles.poll())){ + while (null != (statementHandle = discardedPreparedStatementHandles.poll())) { ++handlesRemoved; - - sql.append(statementHandle.isDirectSql() ? "EXEC sp_unprepare " : "EXEC sp_cursorunprepare ") - .append(statementHandle.getHandle()) - .append(';'); + + sql.append(statementHandle.isDirectSql() ? "EXEC sp_unprepare " : "EXEC sp_cursorunprepare ").append(statementHandle.getHandle()) + .append(';'); } try { // Execute the batched set. - try(Statement stmt = this.createStatement()) { + try (Statement stmt = this.createStatement()) { stmt.execute(sql.toString()); } if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.finer(this + ": Finished un-preparing handle count:" + handlesRemoved); } - catch(SQLException e) { + catch (SQLException e) { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.log(Level.FINER, this + ": Error batch-closing at least one prepared handle", e); } @@ -5734,61 +5745,38 @@ final void unprepareUnreferencedPreparedStatementHandles(boolean force) { } } - /** - * Determine whether statement pooling is disabled. - * - * @return true if statement pooling is disabled, false if it is enabled. - */ + @Override public boolean getDisableStatementPooling() { return this.disableStatementPooling; } - /** - * Disable/enable statement pooling. - * - * @param value true to disable statement pooling, false to enable it. - */ + @Override public void setDisableStatementPooling(boolean value) { this.disableStatementPooling = value; if (!value && 0 < this.getStatementPoolingCacheSize()) { prepareCache(); } } - - /** - * Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache. - * @return Returns the current setting per the description. - */ + + @Override public int getStatementPoolingCacheSize() { return statementPoolingCacheSize; - } + } - /** - * Returns the current number of pooled prepared statement handles. - * @return Returns the current setting per the description. - */ + @Override public int getStatementHandleCacheEntryCount() { - if(!isStatementPoolingEnabled()) + if (!isStatementPoolingEnabled()) return 0; else return this.preparedStatementHandleCache.size(); } - /** - * Whether statement pooling is enabled or not for this connection. - * @return Returns the current setting per the description. - */ + @Override public boolean isStatementPoolingEnabled() { return null != preparedStatementHandleCache && 0 < this.getStatementPoolingCacheSize() && !this.getDisableStatementPooling(); } - /** - * Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache. - * - * @param value - * The new cache size. - * - */ + @Override public void setStatementPoolingCacheSize(int value) { value = Math.max(0, value); statementPoolingCacheSize = value; @@ -5805,6 +5793,7 @@ public void setStatementPoolingCacheSize(int value) { /** * Internal method to prepare the cache handle + * * @param value */ private void prepareCache() { @@ -5817,33 +5806,36 @@ private void prepareCache() { /** Get a parameter metadata cache entry if statement pooling is enabled */ final SQLServerParameterMetaData getCachedParameterMetadata(Sha1HashKey key) { - if(!isStatementPoolingEnabled()) + if (!isStatementPoolingEnabled()) return null; - + return parameterMetadataCache.get(key); } /** Register a parameter metadata cache entry if statement pooling is enabled */ - final void registerCachedParameterMetadata(Sha1HashKey key, SQLServerParameterMetaData pmd) { - if(!isStatementPoolingEnabled() || null == pmd) + final void registerCachedParameterMetadata(Sha1HashKey key, + SQLServerParameterMetaData pmd) { + if (!isStatementPoolingEnabled() || null == pmd) return; - + parameterMetadataCache.put(key, pmd); } /** Get or create prepared statement handle cache entry if statement pooling is enabled */ final PreparedStatementHandle getCachedPreparedStatementHandle(Sha1HashKey key) { - if(!isStatementPoolingEnabled()) + if (!isStatementPoolingEnabled()) return null; - + return preparedStatementHandleCache.get(key); } /** Get or create prepared statement handle cache entry if statement pooling is enabled */ - final PreparedStatementHandle registerCachedPreparedStatementHandle(Sha1HashKey key, int handle, boolean isDirectSql) { - if(!isStatementPoolingEnabled() || null == key) + final PreparedStatementHandle registerCachedPreparedStatementHandle(Sha1HashKey key, + int handle, + boolean isDirectSql) { + if (!isStatementPoolingEnabled() || null == key) return null; - + PreparedStatementHandle cacheItem = new PreparedStatementHandle(key, handle, isDirectSql, false); preparedStatementHandleCache.putIfAbsent(key, cacheItem); return cacheItem; @@ -5859,26 +5851,74 @@ final void returnCachedPreparedStatementHandle(PreparedStatementHandle handle) { /** Force eviction of prepared statement handle cache entry. */ final void evictCachedPreparedStatementHandle(PreparedStatementHandle handle) { - if(null == handle || null == handle.getKey()) - return; - - preparedStatementHandleCache.remove(handle.getKey()); + if (null == handle || null == handle.getKey()) + return; + + preparedStatementHandleCache.remove(handle.getKey()); } // Handle closing handles when removed from cache. final class PreparedStatementCacheEvictionListener implements EvictionListener { - public void onEviction(Sha1HashKey key, PreparedStatementHandle handle) { - if(null != handle) { + public void onEviction(Sha1HashKey key, + PreparedStatementHandle handle) { + if (null != handle) { handle.setIsEvictedFromCache(true); // Mark as evicted from cache. // Only discard if not referenced. - if(handle.tryDiscardHandle()) { + if (handle.tryDiscardHandle()) { enqueueUnprepareStatementHandle(handle); // Do not run discard actions here! Can interfere with executing statement. - } + } } } } + + boolean isAzureDW() throws SQLServerException, SQLException { + if (null == isAzureDW) { + try (Statement stmt = this.createStatement(); ResultSet rs = stmt.executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)");) + { + // SERVERPROPERTY('EngineEdition') can be used to determine whether the db server is SQL Azure. + // It should return 6 for SQL Azure DW. This is more reliable than @@version or serverproperty('edition'). + // Reference: http://msdn.microsoft.com/en-us/library/ee336261.aspx + // + // SERVERPROPERTY('EngineEdition') means + // Database Engine edition of the instance of SQL Server installed on the server. + // 1 = Personal or Desktop Engine (Not available for SQL Server.) + // 2 = Standard (This is returned for Standard and Workgroup.) + // 3 = Enterprise (This is returned for Enterprise, Enterprise Evaluation, and Developer.) + // 4 = Express (This is returned for Express, Express with Advanced Services, and Windows Embedded SQL.) + // 5 = SQL Azure + // 6 = SQL Azure DW + // Base data type: int + final int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; + rs.next(); + isAzureDW = (rs.getInt(1) == ENGINE_EDITION_FOR_SQL_AZURE_DW) ? true : false; + } + return isAzureDW; + } else { + return isAzureDW; + } + } + + /** + * @param st + * Statement to add to openStatements + */ + final synchronized void addOpenStatement(Statement st) { + if (null != openStatements) { + openStatements.add(st); + } + } + + /** + * @param st + * Statement to remove from openStatements + */ + final synchronized void removeOpenStatement(Statement st) { + if (null != openStatements) { + openStatements.remove(st); + } + } } // Helper class for security manager functions used by SQLServerConnection class. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection43.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection43.java index 217bcfc72..27c782c0c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection43.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection43.java @@ -1,36 +1,64 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + package com.microsoft.sqlserver.jdbc; -import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLException; import java.sql.ShardingKey; +/** + * SQLServerConnection43 extends {@link SQLServerConnection43} class and implements {@link ISQLServerConnection43} with methods introduced in JDBC 4.3 + * Specifications. This class is used by the drdiver when initializing a class with 43 driver version + */ public class SQLServerConnection43 extends SQLServerConnection implements ISQLServerConnection43 { + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = -6904163521498951547L; + SQLServerConnection43(String parentInfo) throws SQLServerException { super(parentInfo); } - - public void setShardingKey(ShardingKey shardingKey) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLServerException("setShardingKey not implemented", new SQLFeatureNotSupportedException("setShardingKey not implemented")); + + @Override + public void beginRequest() throws SQLException { + beginRequestInternal(); + } + + @Override + public void endRequest() throws SQLException { + endRequestInternal(); + } + + @Override + public void setShardingKey(ShardingKey shardingKey) throws SQLException { + SQLServerException.throwFeatureNotSupportedException(); } + @Override public void setShardingKey(ShardingKey shardingKey, - ShardingKey superShardingKey) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLServerException("setShardingKey not implemented", new SQLFeatureNotSupportedException("setShardingKey not implemented")) ; + ShardingKey superShardingKey) throws SQLException { + SQLServerException.throwFeatureNotSupportedException(); } + @Override public boolean setShardingKeyIfValid(ShardingKey shardingKey, - int timeout) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLServerException("setShardingKeyIfValid not implemented", new SQLFeatureNotSupportedException("setShardingKeyIfValid not implemented")); + int timeout) throws SQLException { + SQLServerException.throwFeatureNotSupportedException(); + return false; } + @Override public boolean setShardingKeyIfValid(ShardingKey shardingKey, ShardingKey superShardingKey, - int timeout) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC43(); - throw new SQLServerException("setShardingKeyIfValid not implemented", new SQLFeatureNotSupportedException("setShardingKeyIfValid not implemented")); + int timeout) throws SQLException { + SQLServerException.throwFeatureNotSupportedException(); + return false; } - } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolDataSource.java index 798a6b036..50115cd05 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolDataSource.java @@ -21,10 +21,10 @@ * physical connections. For example, J2EE application servers that provide JDBC 3.0 API spec connection pooling. * */ - public class SQLServerConnectionPoolDataSource extends SQLServerDataSource implements ConnectionPoolDataSource { // Get a new physical connection that the pool manager will issue logical connections from - /* L0 */ public PooledConnection getPooledConnection() throws SQLException { + @Override + public PooledConnection getPooledConnection() throws SQLException { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getPooledConnection"); PooledConnection pcon = getPooledConnection(getUser(), getPassword()); @@ -33,7 +33,8 @@ public class SQLServerConnectionPoolDataSource extends SQLServerDataSource imple return pcon; } - /* L0 */ public PooledConnection getPooledConnection(String user, + @Override + public PooledConnection getPooledConnection(String user, String password) throws SQLException { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getPooledConnection", new Object[] {user, "Password not traced"}); @@ -45,6 +46,7 @@ public class SQLServerConnectionPoolDataSource extends SQLServerDataSource imple // Implement javax.naming.Referenceable interface methods. + @Override public Reference getReference() { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getReference"); @@ -82,5 +84,4 @@ private Object readResolve() { return ds; } } - } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolProxy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolProxy.java index 80d3a234d..cca04ad76 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolProxy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolProxy.java @@ -1,689 +1,615 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.SQLClientInfoException; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLPermission; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Savepoint; -import java.sql.Statement; -import java.sql.Struct; -import java.text.MessageFormat; -import java.util.Properties; -import java.util.UUID; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; - -/** - * SQLServerConnectionPoolProxy is a wrapper around SQLServerConnection object. When returning a connection object from PooledConnection.getConnection - * we return this proxy per SPEC. - *

- * This class's public functions need to be kept identical to the SQLServerConnection's. - *

- * The API javadoc for JDBC API methods that this class implements are not repeated here. Please see Sun's JDBC API interfaces javadoc for those - * details. - */ - -class SQLServerConnectionPoolProxy implements ISQLServerConnection { - private SQLServerConnection wrappedConnection; - private boolean bIsOpen; - static private final AtomicInteger baseConnectionID = new AtomicInteger(0); // connection id dispenser - final private String traceID; - - // Permission targets - // currently only callAbort is implemented - private static final String callAbortPerm = "callAbort"; - - /** - * Generate the next unique connection id. - * - * @return the next conn id - */ - /* L0 */ private static int nextConnectionID() { - return baseConnectionID.incrementAndGet(); - } - - public String toString() { - return traceID; - } - - /* L0 */ SQLServerConnectionPoolProxy(SQLServerConnection con) { - traceID = " ProxyConnectionID:" + nextConnectionID(); - wrappedConnection = con; - // the Proxy is created with an open conn - con.setAssociatedProxy(this); - bIsOpen = true; - } - - /* L0 */ void checkClosed() throws SQLServerException { - if (!bIsOpen) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_connectionIsClosed"), null, false); - } - } - - /* L0 */ public Statement createStatement() throws SQLServerException { - checkClosed(); - return wrappedConnection.createStatement(); - } - - /* L0 */ public PreparedStatement prepareStatement(String sql) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql); - } - - /* L0 */ public CallableStatement prepareCall(String sql) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareCall(sql); - } - - /* L0 */ public String nativeSQL(String sql) throws SQLServerException { - checkClosed(); - return wrappedConnection.nativeSQL(sql); - } - - public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException { - checkClosed(); - wrappedConnection.setAutoCommit(newAutoCommitMode); - } - - /* L0 */ public boolean getAutoCommit() throws SQLServerException { - checkClosed(); - return wrappedConnection.getAutoCommit(); - } - - public void commit() throws SQLServerException { - checkClosed(); - wrappedConnection.commit(); - } - - /** - * Rollback a transaction. - * - * @throws SQLServerException - * if no transaction exists or if the connection is in auto-commit mode. - */ - public void rollback() throws SQLServerException { - checkClosed(); - wrappedConnection.rollback(); - } - - public void abort(Executor executor) throws SQLException { - if (!bIsOpen || (null == wrappedConnection)) - return; - - if (null == executor) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidArgument")); - Object[] msgArgs = {"executor"}; - SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false); - } - - // check for callAbort permission - SecurityManager secMgr = System.getSecurityManager(); - if (secMgr != null) { - try { - SQLPermission perm = new SQLPermission(callAbortPerm); - secMgr.checkPermission(perm); - } - catch (SecurityException ex) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_permissionDenied")); - Object[] msgArgs = {callAbortPerm}; - throw new SQLServerException(form.format(msgArgs), null, 0, ex); - } - } - - bIsOpen = false; - - executor.execute(new Runnable() { - public void run() { - if (wrappedConnection.getConnectionLogger().isLoggable(Level.FINER)) - wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy aborted "); - try { - wrappedConnection.poolCloseEventNotify(); - wrappedConnection = null; - } - catch (SQLException e) { - throw new RuntimeException(e); - } - } - }); - } - - /* L0 */ public void close() throws SQLServerException { - if (bIsOpen && (null != wrappedConnection)) { - if (wrappedConnection.getConnectionLogger().isLoggable(Level.FINER)) - wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy closed "); - - wrappedConnection.poolCloseEventNotify(); - wrappedConnection = null; - } - bIsOpen = false; - } - - /* L0 */ void internalClose() { - bIsOpen = false; - wrappedConnection = null; - } - - /* L0 */ public boolean isClosed() throws SQLServerException { - return !bIsOpen; - } - - /* L0 */ public DatabaseMetaData getMetaData() throws SQLServerException { - checkClosed(); - return wrappedConnection.getMetaData(); - } - - /* L0 */ public void setReadOnly(boolean readOnly) throws SQLServerException { - checkClosed(); - wrappedConnection.setReadOnly(readOnly); - } - - /* L0 */ public boolean isReadOnly() throws SQLServerException { - checkClosed(); - return wrappedConnection.isReadOnly(); - } - - /* L0 */ public void setCatalog(String catalog) throws SQLServerException { - checkClosed(); - wrappedConnection.setCatalog(catalog); - } - - /* L0 */ public String getCatalog() throws SQLServerException { - checkClosed(); - return wrappedConnection.getCatalog(); - } - - /* L0 */ public void setTransactionIsolation(int level) throws SQLServerException { - checkClosed(); - wrappedConnection.setTransactionIsolation(level); - } - - /* L0 */ public int getTransactionIsolation() throws SQLServerException { - checkClosed(); - return wrappedConnection.getTransactionIsolation(); - } - - /* L0 */ public SQLWarning getWarnings() throws SQLServerException { - checkClosed(); - return wrappedConnection.getWarnings(); // Warnings support added - } - - /* L2 */ public void clearWarnings() throws SQLServerException { - checkClosed(); - wrappedConnection.clearWarnings(); - } - - // --------------------------JDBC 2.0----------------------------- - - /* L2 */ public Statement createStatement(int resultSetType, - int resultSetConcurrency) throws SQLException { - checkClosed(); - return wrappedConnection.createStatement(resultSetType, resultSetConcurrency); - } - - /* L2 */ public PreparedStatement prepareStatement(String sSql, - int resultSetType, - int resultSetConcurrency) throws SQLException { - checkClosed(); - return wrappedConnection.prepareStatement(sSql, resultSetType, resultSetConcurrency); - } - - /* L2 */ public CallableStatement prepareCall(String sql, - int resultSetType, - int resultSetConcurrency) throws SQLException { - checkClosed(); - return wrappedConnection.prepareCall(sql, resultSetType, resultSetConcurrency); - } - - /* L2 */ public void setTypeMap(java.util.Map> map) throws SQLServerException { - checkClosed(); - wrappedConnection.setTypeMap(map); - } - - public java.util.Map> getTypeMap() throws SQLServerException { - checkClosed(); - return wrappedConnection.getTypeMap(); - } - - /* L3 */ public Statement createStatement(int nType, - int nConcur, - int nHold) throws SQLServerException { - checkClosed(); - return wrappedConnection.createStatement(nType, nConcur, nHold); - } - - /** - * Creates a Statement object that will generate ResultSet objects with the given type, concurrency, and holdability. - * This method is the same as the createStatement method above, but it allows the default result set type, concurrency, and - * holdability to be overridden. - * - * @param nType - * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, - * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE - * @param nConcur - * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or - * ResultSet.CONCUR_UPDATABLE - * @param nHold - * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or - * ResultSet.CLOSE_CURSORS_AT_COMMIT - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new Statement object that will generate ResultSet objects with the given type, concurrency, and holdability - * @exception SQLException - * if a database access error occurs, this method is called on a closed connection or the given parameters are not - * ResultSet constants indicating type, concurrency, and holdability - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method or this method is not supported for the specified result set type, result set - * holdability and result set concurrency. - */ - public Statement createStatement(int nType, - int nConcur, - int nHold, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - checkClosed(); - return wrappedConnection.createStatement(nType, nConcur, nHold, stmtColEncSetting); - } - - /* L3 */ public PreparedStatement prepareStatement(java.lang.String sql, - int nType, - int nConcur, - int nHold) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold); - } - - /** - * Creates a PreparedStatement object that will generate ResultSet objects with the given type, concurrency, and - * holdability. - *

- * This method is the same as the prepareStatement method above, but it allows the default result set type, concurrency, and - * holdability to be overridden. - * - * @param sql - * a String object that is the SQL statement to be sent to the database; may contain one or more '?' IN parameters - * @param nType - * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, - * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE - * @param nConcur - * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or - * ResultSet.CONCUR_UPDATABLE - * @param nHold - * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or - * ResultSet.CLOSE_CURSORS_AT_COMMIT - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will generate ResultSet - * objects with the given type, concurrency, and holdability - * @exception SQLException - * if a database access error occurs, this method is called on a closed connection or the given parameters are not - * ResultSet constants indicating type, concurrency, and holdability - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method or this method is not supported for the specified result set type, result set - * holdability and result set concurrency. - */ - public PreparedStatement prepareStatement(String sql, - int nType, - int nConcur, - int nHold, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold, stmtColEncSetting); - } - - /* L3 */ public CallableStatement prepareCall(String sql, - int nType, - int nConcur, - int nHold) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareCall(sql, nType, nConcur, nHold); - } - - /** - * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. This - * method is the same as the prepareCall method above, but it allows the default result set type, result set concurrency type and - * holdability to be overridden. - * - * @param sql - * a String object that is the SQL statement to be sent to the database; may contain on or more '?' parameters - * @param nType - * one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, - * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE - * @param nConcur - * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or - * ResultSet.CONCUR_UPDATABLE - * @param nHold - * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or - * ResultSet.CLOSE_CURSORS_AT_COMMIT - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will generate ResultSet - * objects with the given type, concurrency, and holdability - * @exception SQLException - * if a database access error occurs, this method is called on a closed connection or the given parameters are not - * ResultSet constants indicating type, concurrency, and holdability - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method or this method is not supported for the specified result set type, result set - * holdability and result set concurrency. - */ - public CallableStatement prepareCall(String sql, - int nType, - int nConcur, - int nHold, - SQLServerStatementColumnEncryptionSetting stmtColEncSetiing) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareCall(sql, nType, nConcur, nHold, stmtColEncSetiing); - } - - /* JDBC 3.0 Auto generated keys */ - - /* L3 */ public PreparedStatement prepareStatement(String sql, - int flag) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, flag); - } - - /** - * Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys. The given constant tells the - * driver whether it should make auto-generated keys available for retrieval. This parameter is ignored if the SQL statement is not an - * INSERT statement, or an SQL statement able to return auto-generated keys (the list of such statements is vendor-specific). - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param flag - * a flag indicating whether auto-generated keys should be returned; one of Statement.RETURN_GENERATED_KEYS or - * Statement.NO_GENERATED_KEYS - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled SQL statement, that will have the capability of returning - * auto-generated keys - * @exception SQLException - * if a database access error occurs, this method is called on a closed connection or the given parameter is not a - * Statement constant indicating whether auto-generated keys should be returned - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method with a constant of Statement.RETURN_GENERATED_KEYS - */ - public PreparedStatement prepareStatement(String sql, - int flag, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, flag, stmtColEncSetting); - } - - /* L3 */ public PreparedStatement prepareStatement(String sql, - int[] columnIndexes) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, columnIndexes); - } - - /** - * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array - * contains the indexes of the columns in the target table that contain the auto-generated keys that should be made available. The driver will - * ignore the array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list - * of such statements is vendor-specific). - *

- * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then - * be used to efficiently execute this statement multiple times. - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param columnIndexes - * an array of column indexes indicating the columns that should be returned from the inserted row or rows - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated - * keys designated by the given array of column indexes - * @exception SQLException - * if a database access error occurs or this method is called on a closed connection - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method - */ - public PreparedStatement prepareStatement(String sql, - int[] columnIndexes, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, columnIndexes, stmtColEncSetting); - } - - /* L3 */ public PreparedStatement prepareStatement(String sql, - String[] columnNames) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, columnNames); - } - - /** - * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. This array - * contains the names of the columns in the target table that contain the auto-generated keys that should be returned. The driver will ignore the - * array if the SQL statement is not an INSERT statement, or an SQL statement able to return auto-generated keys (the list of such - * statements is vendor-specific). - *

- * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then - * be used to efficiently execute this statement multiple times. - *

- * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If the driver supports - * precompilation, the method prepareStatement will send the statement to the database for precompilation. Some drivers may not - * support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement object is - * executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions. - *

- * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have a - * concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling - * {@link #getHoldability}. - * - * @param sql - * an SQL statement that may contain one or more '?' IN parameter placeholders - * @param columnNames - * an array of column names indicating the columns that should be returned from the inserted row or rows - * @param stmtColEncSetting - * Specifies how data will be sent and received when reading and writing encrypted columns. - * @return a new PreparedStatement object, containing the pre-compiled statement, that is capable of returning the auto-generated - * keys designated by the given array of column names - * @exception SQLException - * if a database access error occurs or this method is called on a closed connection - * @exception SQLFeatureNotSupportedException - * if the JDBC driver does not support this method - */ - public PreparedStatement prepareStatement(String sql, - String[] columnNames, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - checkClosed(); - return wrappedConnection.prepareStatement(sql, columnNames, stmtColEncSetting); - } - - /* JDBC 3.0 Savepoints */ - - /* L3 */ public void releaseSavepoint(Savepoint savepoint) throws SQLServerException { - checkClosed(); - wrappedConnection.releaseSavepoint(savepoint); - } - - /* L3 */ public Savepoint setSavepoint(String sName) throws SQLServerException { - checkClosed(); - return wrappedConnection.setSavepoint(sName); - } - - /* L3 */ public Savepoint setSavepoint() throws SQLServerException { - checkClosed(); - return wrappedConnection.setSavepoint(); - } - - /* L3 */ public void rollback(Savepoint s) throws SQLServerException { - checkClosed(); - wrappedConnection.rollback(s); - } - - /* L3 */ public int getHoldability() throws SQLServerException { - checkClosed(); - return wrappedConnection.getHoldability(); - } - - /* L3 */ public void setHoldability(int nNewHold) throws SQLServerException { - checkClosed(); - wrappedConnection.setHoldability(nNewHold); - } - - public int getNetworkTimeout() throws SQLException { - checkClosed(); - return wrappedConnection.getNetworkTimeout(); - } - - public void setNetworkTimeout(Executor executor, - int timeout) throws SQLException { - checkClosed(); - wrappedConnection.setNetworkTimeout(executor, timeout); - } - - public String getSchema() throws SQLException { - checkClosed(); - return wrappedConnection.getSchema(); - } - - public void setSchema(String schema) throws SQLException { - checkClosed(); - wrappedConnection.setSchema(schema); - } - - public java.sql.Array createArrayOf(String typeName, - Object[] elements) throws SQLException { - checkClosed(); - return wrappedConnection.createArrayOf(typeName, elements); - } - - public Blob createBlob() throws SQLException { - checkClosed(); - return wrappedConnection.createBlob(); - } - - public Clob createClob() throws SQLException { - checkClosed(); - return wrappedConnection.createClob(); - } - - public NClob createNClob() throws SQLException { - checkClosed(); - return wrappedConnection.createNClob(); - } - - public SQLXML createSQLXML() throws SQLException { - checkClosed(); - return wrappedConnection.createSQLXML(); - } - - public Struct createStruct(String typeName, - Object[] attributes) throws SQLException { - checkClosed(); - return wrappedConnection.createStruct(typeName, attributes); - } - - public Properties getClientInfo() throws SQLException { - checkClosed(); - return wrappedConnection.getClientInfo(); - } - - public String getClientInfo(String name) throws SQLException { - checkClosed(); - return wrappedConnection.getClientInfo(name); - } - - public void setClientInfo(Properties properties) throws SQLClientInfoException { - // No checkClosed() call since we can only throw SQLClientInfoException from here - wrappedConnection.setClientInfo(properties); - } - - public void setClientInfo(String name, - String value) throws SQLClientInfoException { - // No checkClosed() call since we can only throw SQLClientInfoException from here - wrappedConnection.setClientInfo(name, value); - } - - public boolean isValid(int timeout) throws SQLException { - checkClosed(); - return wrappedConnection.isValid(timeout); - } - - public boolean isWrapperFor(Class iface) throws SQLException { - wrappedConnection.getConnectionLogger().entering(toString(), "isWrapperFor", iface); - boolean f = iface.isInstance(this); - wrappedConnection.getConnectionLogger().exiting(toString(), "isWrapperFor", f); - return f; - } - - public T unwrap(Class iface) throws SQLException { - wrappedConnection.getConnectionLogger().entering(toString(), "unwrap", iface); - T t; - try { - t = iface.cast(this); - } - catch (ClassCastException e) { - SQLServerException newe = new SQLServerException(e.getMessage(), e); - throw newe; - } - wrappedConnection.getConnectionLogger().exiting(toString(), "unwrap", t); - return t; - } - - public UUID getClientConnectionId() throws SQLServerException { - checkClosed(); - return wrappedConnection.getClientConnectionId(); - } - - /** - * Modifies the setting of the sendTimeAsDatetime connection property. When true, java.sql.Time values will be sent to the server as SQL - * Serverdatetime values. When false, java.sql.Time values will be sent to the server as SQL Servertime values. sendTimeAsDatetime can also be - * modified programmatically with SQLServerDataSource.setSendTimeAsDatetime. The default value for this property may change in a future release. - * - * @param sendTimeAsDateTimeValue - * enables/disables setting the sendTimeAsDatetime connection property. For more information about how the Microsoft JDBC Driver for - * SQL Server configures java.sql.Time values before sending them to the server, see - * Configuring How java.sql.Time Values are Sent to the - * Server. - */ - public synchronized void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) throws SQLServerException { - checkClosed(); - wrappedConnection.setSendTimeAsDatetime(sendTimeAsDateTimeValue); - } - - /** - * Returns the setting of the sendTimeAsDatetime connection property. - * - * @return if enabled, returns true. Otherwise, false. - * @throws SQLServerException - * when an error occurs. - */ - public synchronized final boolean getSendTimeAsDatetime() throws SQLServerException { - checkClosed(); - return wrappedConnection.getSendTimeAsDatetime(); - } -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.sql.Statement; +import java.text.MessageFormat; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * SQLServerConnectionPoolProxy is a wrapper around SQLServerConnection object. When returning a connection object from PooledConnection.getConnection + * we return this proxy per SPEC. + *

+ * This class's public functions need to be kept identical to the SQLServerConnection's. + *

+ * The API javadoc for JDBC API methods that this class implements are not repeated here. Please see Sun's JDBC API interfaces javadoc for those + * details. + */ + +class SQLServerConnectionPoolProxy implements ISQLServerConnection, java.io.Serializable { + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = 5752599482349578127L; + + private SQLServerConnection wrappedConnection; + private boolean bIsOpen; + static private final AtomicInteger baseConnectionID = new AtomicInteger(0); // connection + // id + // dispenser + final private String traceID; + + // Permission targets + // currently only callAbort is implemented + private static final String callAbortPerm = "callAbort"; + + /** + * Generate the next unique connection id. + * + * @return the next conn id + */ + private static int nextConnectionID() { + return baseConnectionID.incrementAndGet(); + } + + @Override + public String toString() { + return traceID; + } + + SQLServerConnectionPoolProxy(SQLServerConnection con) { + traceID = " ProxyConnectionID:" + nextConnectionID(); + wrappedConnection = con; + // the Proxy is created with an open conn + con.setAssociatedProxy(this); + bIsOpen = true; + } + + void checkClosed() throws SQLServerException { + if (!bIsOpen) { + SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_connectionIsClosed"), null, false); + } + } + + @Override + public Statement createStatement() throws SQLServerException { + checkClosed(); + return wrappedConnection.createStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareCall(sql); + } + + @Override + public String nativeSQL(String sql) throws SQLServerException { + checkClosed(); + return wrappedConnection.nativeSQL(sql); + } + + @Override + public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException { + checkClosed(); + wrappedConnection.setAutoCommit(newAutoCommitMode); + } + + @Override + public boolean getAutoCommit() throws SQLServerException { + checkClosed(); + return wrappedConnection.getAutoCommit(); + } + + @Override + public void commit() throws SQLServerException { + checkClosed(); + wrappedConnection.commit(); + } + + @Override + public void rollback() throws SQLServerException { + checkClosed(); + wrappedConnection.rollback(); + } + + @Override + public void abort(Executor executor) throws SQLException { + if (!bIsOpen || (null == wrappedConnection)) + return; + + if (null == executor) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidArgument")); + Object[] msgArgs = {"executor"}; + SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false); + } + + // check for callAbort permission + SecurityManager secMgr = System.getSecurityManager(); + if (secMgr != null) { + try { + java.sql.SQLPermission perm = new java.sql.SQLPermission(callAbortPerm); + secMgr.checkPermission(perm); + } + catch (SecurityException ex) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_permissionDenied")); + Object[] msgArgs = {callAbortPerm}; + throw new SQLServerException(form.format(msgArgs), null, 0, ex); + } + } + + bIsOpen = false; + + executor.execute(new Runnable() { + public void run() { + if (wrappedConnection.getConnectionLogger().isLoggable(java.util.logging.Level.FINER)) + wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy aborted "); + try { + wrappedConnection.poolCloseEventNotify(); + wrappedConnection = null; + } + catch (SQLException e) { + throw new RuntimeException(e); + } + } + }); + } + + @Override + public void close() throws SQLServerException { + if (bIsOpen && (null != wrappedConnection)) { + if (wrappedConnection.getConnectionLogger().isLoggable(java.util.logging.Level.FINER)) + wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy closed "); + + wrappedConnection.poolCloseEventNotify(); + wrappedConnection = null; + } + bIsOpen = false; + } + + void internalClose() { + bIsOpen = false; + wrappedConnection = null; + } + + @Override + public boolean isClosed() throws SQLServerException { + return !bIsOpen; + } + + @Override + public java.sql.DatabaseMetaData getMetaData() throws SQLServerException { + checkClosed(); + return wrappedConnection.getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLServerException { + checkClosed(); + wrappedConnection.setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLServerException { + checkClosed(); + return wrappedConnection.isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLServerException { + checkClosed(); + wrappedConnection.setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLServerException { + checkClosed(); + return wrappedConnection.getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLServerException { + checkClosed(); + wrappedConnection.setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLServerException { + checkClosed(); + return wrappedConnection.getTransactionIsolation(); + } + + @Override + public java.sql.SQLWarning getWarnings() throws SQLServerException { + checkClosed(); + return wrappedConnection.getWarnings(); // Warnings support added + } + + @Override + public void clearWarnings() throws SQLServerException { + checkClosed(); + wrappedConnection.clearWarnings(); + } + + // --------------------------JDBC 2.0----------------------------- + + @Override + public Statement createStatement(int resultSetType, + int resultSetConcurrency) throws SQLException { + checkClosed(); + return wrappedConnection.createStatement(resultSetType, resultSetConcurrency); + } + + @Override + public PreparedStatement prepareStatement(String sSql, + int resultSetType, + int resultSetConcurrency) throws SQLException { + checkClosed(); + return wrappedConnection.prepareStatement(sSql, resultSetType, resultSetConcurrency); + } + + @Override + public CallableStatement prepareCall(String sql, + int resultSetType, + int resultSetConcurrency) throws SQLException { + checkClosed(); + return wrappedConnection.prepareCall(sql, resultSetType, resultSetConcurrency); + } + + @Override + public void setTypeMap(java.util.Map> map) throws SQLException { + checkClosed(); + wrappedConnection.setTypeMap(map); + } + + @Override + public java.util.Map> getTypeMap() throws SQLServerException { + checkClosed(); + return wrappedConnection.getTypeMap(); + } + + @Override + public Statement createStatement(int nType, + int nConcur, + int nHold) throws SQLServerException { + checkClosed(); + return wrappedConnection.createStatement(nType, nConcur, nHold); + } + + @Override + public Statement createStatement(int nType, + int nConcur, + int nHold, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { + checkClosed(); + return wrappedConnection.createStatement(nType, nConcur, nHold, stmtColEncSetting); + } + + @Override + public PreparedStatement prepareStatement(java.lang.String sql, + int nType, + int nConcur, + int nHold) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold); + } + + @Override + public PreparedStatement prepareStatement(String sql, + int nType, + int nConcur, + int nHold, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold, stmtColEncSetting); + } + + @Override + public CallableStatement prepareCall(String sql, + int nType, + int nConcur, + int nHold) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareCall(sql, nType, nConcur, nHold); + } + + @Override + public CallableStatement prepareCall(String sql, + int nType, + int nConcur, + int nHold, + SQLServerStatementColumnEncryptionSetting stmtColEncSetiing) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareCall(sql, nType, nConcur, nHold, stmtColEncSetiing); + } + + /* JDBC 3.0 Auto generated keys */ + + @Override + public PreparedStatement prepareStatement(String sql, + int flag) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, flag); + } + + @Override + public PreparedStatement prepareStatement(String sql, + int flag, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, flag, stmtColEncSetting); + } + + @Override + public PreparedStatement prepareStatement(String sql, + int[] columnIndexes) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, columnIndexes); + } + + @Override + public PreparedStatement prepareStatement(String sql, + int[] columnIndexes, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, columnIndexes, stmtColEncSetting); + } + + @Override + public PreparedStatement prepareStatement(String sql, + String[] columnNames) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, columnNames); + } + + @Override + public PreparedStatement prepareStatement(String sql, + String[] columnNames, + SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { + checkClosed(); + return wrappedConnection.prepareStatement(sql, columnNames, stmtColEncSetting); + } + + /* JDBC 3.0 Savepoints */ + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + checkClosed(); + wrappedConnection.releaseSavepoint(savepoint); + } + + @Override + public Savepoint setSavepoint(String sName) throws SQLServerException { + checkClosed(); + return wrappedConnection.setSavepoint(sName); + } + + @Override + public Savepoint setSavepoint() throws SQLServerException { + checkClosed(); + return wrappedConnection.setSavepoint(); + } + + @Override + public void rollback(Savepoint s) throws SQLServerException { + checkClosed(); + wrappedConnection.rollback(s); + } + + @Override + public int getHoldability() throws SQLServerException { + checkClosed(); + return wrappedConnection.getHoldability(); + } + + @Override + public void setHoldability(int nNewHold) throws SQLServerException { + checkClosed(); + wrappedConnection.setHoldability(nNewHold); + } + + @Override + public int getNetworkTimeout() throws SQLException { + checkClosed(); + return wrappedConnection.getNetworkTimeout(); + } + + @Override + public void setNetworkTimeout(Executor executor, + int timeout) throws SQLException { + checkClosed(); + wrappedConnection.setNetworkTimeout(executor, timeout); + } + + @Override + public String getSchema() throws SQLException { + checkClosed(); + return wrappedConnection.getSchema(); + } + + @Override + public void setSchema(String schema) throws SQLException { + checkClosed(); + wrappedConnection.setSchema(schema); + } + + @Override + public java.sql.Array createArrayOf(String typeName, + Object[] elements) throws SQLException { + checkClosed(); + return wrappedConnection.createArrayOf(typeName, elements); + } + + @Override + public java.sql.Blob createBlob() throws SQLException { + checkClosed(); + return wrappedConnection.createBlob(); + } + + @Override + public java.sql.Clob createClob() throws SQLException { + checkClosed(); + return wrappedConnection.createClob(); + } + + @Override + public java.sql.NClob createNClob() throws SQLException { + checkClosed(); + return wrappedConnection.createNClob(); + } + + @Override + public java.sql.SQLXML createSQLXML() throws SQLException { + checkClosed(); + return wrappedConnection.createSQLXML(); + } + + @Override + public java.sql.Struct createStruct(String typeName, + Object[] attributes) throws SQLException { + checkClosed(); + return wrappedConnection.createStruct(typeName, attributes); + } + + @Override + public java.util.Properties getClientInfo() throws SQLException { + checkClosed(); + return wrappedConnection.getClientInfo(); + } + + @Override + public String getClientInfo(String name) throws SQLException { + checkClosed(); + return wrappedConnection.getClientInfo(name); + } + + @Override + public void setClientInfo(java.util.Properties properties) throws SQLClientInfoException { + // No checkClosed() call since we can only throw SQLClientInfoException + // from here + wrappedConnection.setClientInfo(properties); + } + + @Override + public void setClientInfo(String name, + String value) throws SQLClientInfoException { + // No checkClosed() call since we can only throw SQLClientInfoException + // from here + wrappedConnection.setClientInfo(name, value); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + checkClosed(); + return wrappedConnection.isValid(timeout); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + wrappedConnection.getConnectionLogger().entering(toString(), "isWrapperFor", iface); + boolean f = iface.isInstance(this); + wrappedConnection.getConnectionLogger().exiting(toString(), "isWrapperFor", f); + return f; + } + + @Override + public T unwrap(Class iface) throws SQLException { + wrappedConnection.getConnectionLogger().entering(toString(), "unwrap", iface); + T t; + try { + t = iface.cast(this); + } + catch (ClassCastException e) { + SQLServerException newe = new SQLServerException(e.getMessage(), e); + throw newe; + } + wrappedConnection.getConnectionLogger().exiting(toString(), "unwrap", t); + return t; + } + + @Override + public java.util.UUID getClientConnectionId() throws SQLServerException { + checkClosed(); + return wrappedConnection.getClientConnectionId(); + } + + @Override + public synchronized void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) throws SQLServerException { + checkClosed(); + wrappedConnection.setSendTimeAsDatetime(sendTimeAsDateTimeValue); + } + + @Override + public boolean getSendTimeAsDatetime() throws SQLServerException { + checkClosed(); + return wrappedConnection.getSendTimeAsDatetime(); + } + + @Override + public int getDiscardedServerPreparedStatementCount() { + return wrappedConnection.getDiscardedServerPreparedStatementCount(); + } + + @Override + public void closeUnreferencedPreparedStatementHandles() { + wrappedConnection.closeUnreferencedPreparedStatementHandles(); + } + + @Override + public boolean getEnablePrepareOnFirstPreparedStatementCall() { + return wrappedConnection.getEnablePrepareOnFirstPreparedStatementCall(); + } + + @Override + public void setEnablePrepareOnFirstPreparedStatementCall(boolean value) { + wrappedConnection.setEnablePrepareOnFirstPreparedStatementCall(value); + } + + @Override + public int getServerPreparedStatementDiscardThreshold() { + return wrappedConnection.getServerPreparedStatementDiscardThreshold(); + } + + @Override + public void setServerPreparedStatementDiscardThreshold(int value) { + wrappedConnection.setServerPreparedStatementDiscardThreshold(value); + } + + @Override + public void setStatementPoolingCacheSize(int value) { + wrappedConnection.setStatementPoolingCacheSize(value); + } + + @Override + public int getStatementPoolingCacheSize() { + return wrappedConnection.getStatementPoolingCacheSize(); + } + + @Override + public boolean isStatementPoolingEnabled() { + return wrappedConnection.isStatementPoolingEnabled(); + } + + @Override + public int getStatementHandleCacheEntryCount() { + return wrappedConnection.getStatementHandleCacheEntryCount(); + } + + @Override + public void setDisableStatementPooling(boolean value) { + wrappedConnection.setDisableStatementPooling(value); + } + + @Override + public boolean getDisableStatementPooling() { + return wrappedConnection.getDisableStatementPooling(); + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index 96d25f106..607c2d89f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -11,7 +11,6 @@ import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; import java.util.Enumeration; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; @@ -20,27 +19,39 @@ import javax.naming.Reference; import javax.naming.StringRefAddr; -import javax.sql.DataSource; import org.ietf.jgss.GSSCredential; /** * This datasource lists properties specific for the SQLServerConnection class. */ -public class SQLServerDataSource implements ISQLServerDataSource, DataSource, java.io.Serializable, javax.naming.Referenceable { +public class SQLServerDataSource implements ISQLServerDataSource, javax.sql.DataSource, java.io.Serializable, javax.naming.Referenceable { // dsLogger is logger used for all SQLServerDataSource instances. static final java.util.logging.Logger dsLogger = java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerDataSource"); static final java.util.logging.Logger loggerExternal = java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc.DataSource"); static final private java.util.logging.Logger parentLogger = java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc"); final private String loggingClassName; private boolean trustStorePasswordStripped = false; + + /** + * Always refresh SerialVersionUID when prompted + */ private static final long serialVersionUID = 654861379544314296L; - private Properties connectionProps; // Properties passed to SQLServerConnection class. - private String dataSourceURL; // URL for datasource. - private String dataSourceDescription; // Description for datasource. - static private final AtomicInteger baseDataSourceID = new AtomicInteger(0); // Unique id generator for each DataSource instance (used for - // logging). + private Properties connectionProps; // Properties passed to + // SQLServerConnection class. + private String dataSourceURL; // URL for datasource. + private String dataSourceDescription; // Description for datasource. + static private final AtomicInteger baseDataSourceID = new AtomicInteger(0); // Unique + // id + // generator + // for + // each + // DataSource + // instance + // (used + // for + // logging). final private String traceID; /** @@ -58,12 +69,14 @@ String getClassNameLogging() { return loggingClassName; } + @Override public String toString() { return traceID; } // DataSource interface public methods + @Override public Connection getConnection() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getConnection"); Connection con = getConnectionInternal(null, null, null); @@ -71,6 +84,7 @@ public Connection getConnection() throws SQLServerException { return con; } + @Override public Connection getConnection(String username, String password) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER)) @@ -82,10 +96,12 @@ public Connection getConnection(String username, // Sets the maximum time in seconds that this data source will wait while // attempting to connect to a database. Note default value is 0. + @Override public void setLoginTimeout(int loginTimeout) { setIntProperty(connectionProps, SQLServerDriverIntProperty.LOGIN_TIMEOUT.toString(), loginTimeout); } + @Override public int getLoginTimeout() { int defaultTimeOut = SQLServerDriverIntProperty.LOGIN_TIMEOUT.getDefaultValue(); final int logintimeout = getIntProperty(connectionProps, SQLServerDriverIntProperty.LOGIN_TIMEOUT.toString(), defaultTimeOut); @@ -94,9 +110,11 @@ public int getLoginTimeout() { } // Sets the log writer for this DataSource. - // Currently we just hold onto this logWriter and pass it back to callers, nothing else. + // Currently we just hold onto this logWriter and pass it back to callers, + // nothing else. private transient PrintWriter logWriter; + @Override public void setLogWriter(PrintWriter out) { loggerExternal.entering(getClassNameLogging(), "setLogWriter", out); logWriter = out; @@ -104,298 +122,256 @@ public void setLogWriter(PrintWriter out) { } // Retrieves the log writer for this DataSource. + @Override public PrintWriter getLogWriter() { loggerExternal.entering(getClassNameLogging(), "getLogWriter"); loggerExternal.exiting(getClassNameLogging(), "getLogWriter", logWriter); return logWriter; } - public Logger getParentLogger() throws SQLFeatureNotSupportedException { + @Override + public Logger getParentLogger() throws java.sql.SQLFeatureNotSupportedException { return parentLogger; } // Core Connection property setters/getters. - // applicationName is used to identify the specific application in various SQL Server + // applicationName is used to identify the specific application in various + // SQL Server // profiling and logging tools. + @Override public void setApplicationName(String applicationName) { setStringProperty(connectionProps, SQLServerDriverStringProperty.APPLICATION_NAME.toString(), applicationName); } + @Override public String getApplicationName() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.APPLICATION_NAME.toString(), SQLServerDriverStringProperty.APPLICATION_NAME.getDefaultValue()); } - // databaseName is the name of the database to connect to. If databaseName is not set, + // databaseName is the name of the database to connect to. If databaseName + // is not set, // getDatabaseName returns the default value of null. + @Override public void setDatabaseName(String databaseName) { setStringProperty(connectionProps, SQLServerDriverStringProperty.DATABASE_NAME.toString(), databaseName); } + @Override public String getDatabaseName() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.DATABASE_NAME.toString(), null); } // instanceName is the SQL Server instance name to connect to. - // If instanceName is not set, getInstanceName returns the default value of null. + // If instanceName is not set, getInstanceName returns the default value of + // null. + @Override public void setInstanceName(String instanceName) { setStringProperty(connectionProps, SQLServerDriverStringProperty.INSTANCE_NAME.toString(), instanceName); } + @Override public String getInstanceName() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.INSTANCE_NAME.toString(), null); } + @Override public void setIntegratedSecurity(boolean enable) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.INTEGRATED_SECURITY.toString(), enable); } + @Override public void setAuthenticationScheme(String authenticationScheme) { setStringProperty(connectionProps, SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.toString(), authenticationScheme); } - /** - * sets the authentication mode - * - * @param authentication - * the authentication mode - */ + @Override public void setAuthentication(String authentication) { setStringProperty(connectionProps, SQLServerDriverStringProperty.AUTHENTICATION.toString(), authentication); } - /** - * Retrieves the authentication mode - * - * @return the authentication value - */ + @Override public String getAuthentication() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.AUTHENTICATION.toString(), SQLServerDriverStringProperty.AUTHENTICATION.getDefaultValue()); } - /** - * sets GSSCredential - * - * @param userCredential the credential - */ - public void setGSSCredentials(GSSCredential userCredential){ - setObjectProperty(connectionProps,SQLServerDriverObjectProperty.GSS_CREDENTIAL.toString(), userCredential); + @Override + public void setGSSCredentials(GSSCredential userCredential) { + setObjectProperty(connectionProps, SQLServerDriverObjectProperty.GSS_CREDENTIAL.toString(), userCredential); } - /** - * Retrieves the GSSCredential - * - * @return GSSCredential - */ - public GSSCredential getGSSCredentials(){ + @Override + public GSSCredential getGSSCredentials() { return (GSSCredential) getObjectProperty(connectionProps, SQLServerDriverObjectProperty.GSS_CREDENTIAL.toString(), SQLServerDriverObjectProperty.GSS_CREDENTIAL.getDefaultValue()); } - - /** - * Sets the access token. - * - * @param accessToken - * to be set in the string property. - */ + + @Override public void setAccessToken(String accessToken) { setStringProperty(connectionProps, SQLServerDriverStringProperty.ACCESS_TOKEN.toString(), accessToken); } - /** - * Retrieves the access token. - * - * @return the access token. - */ + @Override public String getAccessToken() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.ACCESS_TOKEN.toString(), null); } - // If lastUpdateCount is set to true, the driver will return only the last update - // count from all the update counts returned by a batch. The default of false will - // return all update counts. If lastUpdateCount is not set, getLastUpdateCount + // If lastUpdateCount is set to true, the driver will return only the last + // update + // count from all the update counts returned by a batch. The default of + // false will + // return all update counts. If lastUpdateCount is not set, + // getLastUpdateCount // returns the default value of false. - /** - * Enables/disables Always Encrypted functionality for the data source object. The default is Disabled. - * - * @param columnEncryptionSetting - * Enables/disables Always Encrypted functionality for the data source object. The default is Disabled. - */ + @Override public void setColumnEncryptionSetting(String columnEncryptionSetting) { setStringProperty(connectionProps, SQLServerDriverStringProperty.COLUMN_ENCRYPTION.toString(), columnEncryptionSetting); } - /** - * Retrieves the Always Encrypted functionality setting for the data source object. - * - * @return the Always Encrypted functionality setting for the data source object. - */ + @Override public String getColumnEncryptionSetting() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.COLUMN_ENCRYPTION.toString(), SQLServerDriverStringProperty.COLUMN_ENCRYPTION.getDefaultValue()); } - /** - * Sets the name that identifies a key store. Only value supported is the "JavaKeyStorePassword" for identifying the Java Key Store. The default - * is null. - * - * @param keyStoreAuthentication - * the name that identifies a key store. - */ + @Override public void setKeyStoreAuthentication(String keyStoreAuthentication) { setStringProperty(connectionProps, SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(), keyStoreAuthentication); } - /** - * Gets the value of the keyStoreAuthentication setting for the data source object. - * - * @return the value of the keyStoreAuthentication setting for the data source object. - */ + @Override public String getKeyStoreAuthentication() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(), SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.getDefaultValue()); } - /** - * Sets the password for the Java keystore. Note that, for Java Key Store provider the password for the keystore and the key must be the same. - * Note that, keyStoreAuthentication must be set with "JavaKeyStorePassword". - * - * @param keyStoreSecret - * the password to use for the keystore as well as for the key - */ + @Override public void setKeyStoreSecret(String keyStoreSecret) { setStringProperty(connectionProps, SQLServerDriverStringProperty.KEY_STORE_SECRET.toString(), keyStoreSecret); } - /** - * Sets the location including the file name for the Java keystore. Note that, keyStoreAuthentication must be set with "JavaKeyStorePassword". - * - * @param keyStoreLocation - * the location including the file name for the Java keystore. - */ + @Override public void setKeyStoreLocation(String keyStoreLocation) { setStringProperty(connectionProps, SQLServerDriverStringProperty.KEY_STORE_LOCATION.toString(), keyStoreLocation); } - /** - * Retrieves the keyStoreLocation for the Java Key Store. - * - * @return the keyStoreLocation for the Java Key Store. - */ + @Override public String getKeyStoreLocation() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.KEY_STORE_LOCATION.toString(), SQLServerDriverStringProperty.KEY_STORE_LOCATION.getDefaultValue()); } + @Override public void setLastUpdateCount(boolean lastUpdateCount) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.LAST_UPDATE_COUNT.toString(), lastUpdateCount); } + @Override public boolean getLastUpdateCount() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.LAST_UPDATE_COUNT.toString(), SQLServerDriverBooleanProperty.LAST_UPDATE_COUNT.getDefaultValue()); } - // Encryption + @Override public void setEncrypt(boolean encrypt) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENCRYPT.toString(), encrypt); } + @Override public boolean getEncrypt() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENCRYPT.toString(), SQLServerDriverBooleanProperty.ENCRYPT.getDefaultValue()); } - /** - * Beginning in version 6.0 of the Microsoft JDBC Driver for SQL Server, a new connection property transparentNetworkIPResolution (TNIR) is added - * for transparent connection to Always On availability groups or to a server which has multiple IP addresses associated. When - * transparentNetworkIPResolution is true, the driver attempts to connect to the first IP address available. If the first attempt fails, the - * driver tries to connect to all IP addresses in parallel until the timeout expires, discarding any pending connection attempts when one of them - * succeeds. - *

- * transparentNetworkIPResolution is ignored if multiSubnetFailover is true - *

- * transparentNetworkIPResolution is ignored if database mirroring is used - *

- * transparentNetworkIPResolution is ignored if there are more than 64 IP addresses - * - * @param tnir - * if set to true, the driver attempts to connect to the first IP address available. It is true by default. - */ + @Override public void setTransparentNetworkIPResolution(boolean tnir) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.TRANSPARENT_NETWORK_IP_RESOLUTION.toString(), tnir); } - /** - * Retrieves the TransparentNetworkIPResolution value. - * - * @return if enabled, returns true. Otherwise, false. - */ + @Override public boolean getTransparentNetworkIPResolution() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.TRANSPARENT_NETWORK_IP_RESOLUTION.toString(), SQLServerDriverBooleanProperty.TRANSPARENT_NETWORK_IP_RESOLUTION.getDefaultValue()); } + @Override public void setTrustServerCertificate(boolean e) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.TRUST_SERVER_CERTIFICATE.toString(), e); } + @Override public boolean getTrustServerCertificate() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.TRUST_SERVER_CERTIFICATE.toString(), SQLServerDriverBooleanProperty.TRUST_SERVER_CERTIFICATE.getDefaultValue()); } + @Override public void setTrustStoreType(String trustStoreType) { setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE_TYPE.toString(), trustStoreType); } + @Override public String getTrustStoreType() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE_TYPE.toString(), SQLServerDriverStringProperty.TRUST_STORE_TYPE.getDefaultValue()); } - public void setTrustStore(String st) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE.toString(), st); + @Override + public void setTrustStore(String trustStore) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE.toString(), trustStore); } + @Override public String getTrustStore() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE.toString(), null); } - public void setTrustStorePassword(String p) { + @Override + public void setTrustStorePassword(String trustStorePassword) { // if a non value property is set - if (p != null) + if (trustStorePassword != null) trustStorePasswordStripped = false; - setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE_PASSWORD.toString(), p); + setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_STORE_PASSWORD.toString(), trustStorePassword); } - public void setHostNameInCertificate(String host) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString(), host); + @Override + public void setHostNameInCertificate(String hostName) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString(), hostName); } + @Override public String getHostNameInCertificate() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.HOSTNAME_IN_CERTIFICATE.toString(), null); } - // lockTimeout is the number of milliseconds to wait before the database reports + // lockTimeout is the number of milliseconds to wait before the database + // reports // a lock timeout. The default value of -1 means wait forever. If specified, - // this value will be the default for all statements on the connection. Note a - // value of 0 means no wait. If lockTimeout is not set, getLockTimeout returns + // this value will be the default for all statements on the connection. Note + // a + // value of 0 means no wait. If lockTimeout is not set, getLockTimeout + // returns // the default of -1. + @Override public void setLockTimeout(int lockTimeout) { setIntProperty(connectionProps, SQLServerDriverIntProperty.LOCK_TIMEOUT.toString(), lockTimeout); } + @Override public int getLockTimeout() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.LOCK_TIMEOUT.toString(), SQLServerDriverIntProperty.LOCK_TIMEOUT.getDefaultValue()); } - // setPassword sets the password that will be used when connecting to SQL Server. - // Note getPassword is deliberately declared non-public for security reasons. - // If the password is not set, getPassword returns the default value of null. + // setPassword sets the password that will be used when connecting to SQL + // Server. + // Note getPassword is deliberately declared non-public for security + // reasons. + // If the password is not set, getPassword returns the default value of + // null. + @Override public void setPassword(String password) { setStringProperty(connectionProps, SQLServerDriverStringProperty.PASSWORD.toString(), password); } @@ -404,15 +380,19 @@ String getPassword() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.PASSWORD.toString(), null); } - // portNumber is the TCP-IP port number used when opening a socket connection - // to SQL Server. If portNumber is not set, getPortNumber returns the default + // portNumber is the TCP-IP port number used when opening a socket + // connection + // to SQL Server. If portNumber is not set, getPortNumber returns the + // default // of 1433. Note as mentioned above, setPortNumber does not do any range // checking on the port value passed in, invalid port numbers like 99999 can // be passed in without triggering any error. + @Override public void setPortNumber(int portNumber) { setIntProperty(connectionProps, SQLServerDriverIntProperty.PORT_NUMBER.toString(), portNumber); } + @Override public int getPortNumber() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.PORT_NUMBER.toString(), SQLServerDriverIntProperty.PORT_NUMBER.getDefaultValue()); @@ -420,143 +400,167 @@ public int getPortNumber() { // selectMethod is the default cursor type used for the result set. This // property is useful when you are dealing with large result sets and don't - // want to store the whole result set in memory on the client side. By setting - // the property to "cursor" you will be able to create a server side cursor that + // want to store the whole result set in memory on the client side. By + // setting + // the property to "cursor" you will be able to create a server side cursor + // that // can fetch smaller chunks of data at a time. If selectMethod is not set, // getSelectMethod returns the default value of "direct". + @Override public void setSelectMethod(String selectMethod) { setStringProperty(connectionProps, SQLServerDriverStringProperty.SELECT_METHOD.toString(), selectMethod); } + @Override public String getSelectMethod() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.SELECT_METHOD.toString(), SQLServerDriverStringProperty.SELECT_METHOD.getDefaultValue()); } - public void setResponseBuffering(String respo) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.RESPONSE_BUFFERING.toString(), respo); + @Override + public void setResponseBuffering(String bufferingMode) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.RESPONSE_BUFFERING.toString(), bufferingMode); } + @Override public String getResponseBuffering() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.RESPONSE_BUFFERING.toString(), SQLServerDriverStringProperty.RESPONSE_BUFFERING.getDefaultValue()); } + @Override public void setApplicationIntent(String applicationIntent) { setStringProperty(connectionProps, SQLServerDriverStringProperty.APPLICATION_INTENT.toString(), applicationIntent); } + @Override public String getApplicationIntent() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.APPLICATION_INTENT.toString(), SQLServerDriverStringProperty.APPLICATION_INTENT.getDefaultValue()); } + @Override public void setSendTimeAsDatetime(boolean sendTimeAsDatetime) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.toString(), sendTimeAsDatetime); } + @Override public boolean getSendTimeAsDatetime() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.toString(), SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue()); } // If sendStringParametersAsUnicode is set to true (which is the default), - // string parameters are sent to the server in UNICODE format. If sendStringParametersAsUnicode - // is set to false, string parameters are sent to the server in the native TDS collation - // format of the database, not in UNICODE. If sendStringParametersAsUnicode is not set, + // string parameters are sent to the server in UNICODE format. If + // sendStringParametersAsUnicode + // is set to false, string parameters are sent to the server in the native + // TDS collation + // format of the database, not in UNICODE. If sendStringParametersAsUnicode + // is not set, // getSendStringParametersAsUnicode returns the default of true. + @Override public void setSendStringParametersAsUnicode(boolean sendStringParametersAsUnicode) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.toString(), sendStringParametersAsUnicode); } + @Override public boolean getSendStringParametersAsUnicode() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.toString(), SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.getDefaultValue()); } - /** - * Translates the serverName from Unicode to ASCII Compatible Encoding (ACE) - * - * @param serverNameAsACE - * if enabled the servername will be translated to ASCII Compatible Encoding (ACE) - */ + @Override public void setServerNameAsACE(boolean serverNameAsACE) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SERVER_NAME_AS_ACE.toString(), serverNameAsACE); } - /** - * Retrieves if the serverName should be translated from Unicode to ASCII Compatible Encoding (ACE) - * - * @return if enabled, will return true. Otherwise, false. - */ + @Override public boolean getServerNameAsACE() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SERVER_NAME_AS_ACE.toString(), SQLServerDriverBooleanProperty.SERVER_NAME_AS_ACE.getDefaultValue()); } - // serverName is the host name of the target SQL Server. If serverName is not set, + // serverName is the host name of the target SQL Server. If serverName is + // not set, // getServerName returns the default value of null is returned. + @Override public void setServerName(String serverName) { setStringProperty(connectionProps, SQLServerDriverStringProperty.SERVER_NAME.toString(), serverName); } + @Override public String getServerName() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.SERVER_NAME.toString(), null); } // Specify an Service Principal Name (SPN) of the target SQL Server. // https://msdn.microsoft.com/en-us/library/cc280459.aspx + @Override public void setServerSpn(String serverSpn) { setStringProperty(connectionProps, SQLServerDriverStringProperty.SERVER_SPN.toString(), serverSpn); } + @Override public String getServerSpn() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.SERVER_SPN.toString(), null); } - // serverName is the host name of the target SQL Server. If serverName is not set, + // serverName is the host name of the target SQL Server. If serverName is + // not set, // getServerName returns the default value of null is returned. + @Override public void setFailoverPartner(String serverName) { setStringProperty(connectionProps, SQLServerDriverStringProperty.FAILOVER_PARTNER.toString(), serverName); } + @Override public String getFailoverPartner() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.FAILOVER_PARTNER.toString(), null); } + @Override public void setMultiSubnetFailover(boolean multiSubnetFailover) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.MULTI_SUBNET_FAILOVER.toString(), multiSubnetFailover); } + @Override public boolean getMultiSubnetFailover() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.MULTI_SUBNET_FAILOVER.toString(), SQLServerDriverBooleanProperty.MULTI_SUBNET_FAILOVER.getDefaultValue()); } - // setUser set's the user name that will be used when connecting to SQL Server. + // setUser set's the user name that will be used when connecting to SQL + // Server. // If user is not set, getUser returns the default value of null. + @Override public void setUser(String user) { setStringProperty(connectionProps, SQLServerDriverStringProperty.USER.toString(), user); } + @Override public String getUser() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.USER.toString(), null); } // workstationID is the name of the client machine (or client workstation). - // workstationID is the host name of the client in other words. If workstationID - // is not set, the default value is constructed by calling InetAddress.getLocalHost().getHostName() + // workstationID is the host name of the client in other words. If + // workstationID + // is not set, the default value is constructed by calling + // InetAddress.getLocalHost().getHostName() // or if getHostName() returns blank then getHostAddress().toString(). + @Override public void setWorkstationID(String workstationID) { setStringProperty(connectionProps, SQLServerDriverStringProperty.WORKSTATION_ID.toString(), workstationID); } + @Override public String getWorkstationID() { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getWorkstationID"); String getWSID = connectionProps.getProperty(SQLServerDriverStringProperty.WORKSTATION_ID.toString()); - // Per spec, return what the logon will send here if workstationID property is not set. + // Per spec, return what the logon will send here if workstationID + // property is not set. if (null == getWSID) { getWSID = Util.lookupHostName(); } @@ -564,67 +568,89 @@ public String getWorkstationID() { return getWSID; } - // If xopenStates is set to true, the driver will convert SQL states to XOPEN - // compliant states. The default is false which causes the driver to generate SQL 99 - // state codes. If xopenStates is not set, getXopenStates returns the default value + // If xopenStates is set to true, the driver will convert SQL states to + // XOPEN + // compliant states. The default is false which causes the driver to + // generate SQL 99 + // state codes. If xopenStates is not set, getXopenStates returns the + // default value // of false. + @Override public void setXopenStates(boolean xopenStates) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.XOPEN_STATES.toString(), xopenStates); } + @Override public boolean getXopenStates() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.XOPEN_STATES.toString(), SQLServerDriverBooleanProperty.XOPEN_STATES.getDefaultValue()); } - + + @Override public void setFIPS(boolean fips) { setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.FIPS.toString(), fips); } + @Override public boolean getFIPS() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.FIPS.toString(), SQLServerDriverBooleanProperty.FIPS.getDefaultValue()); } - + + @Override public void setSSLProtocol(String sslProtocol) { setStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), sslProtocol); } + @Override public String getSSLProtocol() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue()); } + @Override public void setTrustManagerClass(String trustManagerClass) { setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_MANAGER_CLASS.toString(), trustManagerClass); } + @Override public String getTrustManagerClass() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_MANAGER_CLASS.toString(), SQLServerDriverStringProperty.TRUST_MANAGER_CLASS.getDefaultValue()); } - public void setTrustManagerConstructorArg(String trustManagerClass) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString(), trustManagerClass); + @Override + public void setTrustManagerConstructorArg(String trustManagerConstructorArg) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString(), trustManagerConstructorArg); } + @Override public String getTrustManagerConstructorArg() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString(), SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.getDefaultValue()); } - // The URL property is exposed for backwards compatibility reasons. Also, several - // Java Application servers expect a setURL function on the DataSource and set it + // The URL property is exposed for backwards compatibility reasons. Also, + // several + // Java Application servers expect a setURL function on the DataSource and + // set it // by default (JBoss and WebLogic). - // Note for security reasons we do not recommend that customers include the password - // in the url supplied to setURL. The reason for this is third-party Java Application - // Servers will very often display the value set to URL property in their DataSource - // configuration GUI. We recommend instead that clients use the setPassword method - // to set the password value. The Java Application Servers will not display a password + // Note for security reasons we do not recommend that customers include the + // password + // in the url supplied to setURL. The reason for this is third-party Java + // Application + // Servers will very often display the value set to URL property in their + // DataSource + // configuration GUI. We recommend instead that clients use the setPassword + // method + // to set the password value. The Java Application Servers will not display + // a password // that is set on the DataSource in the configuration GUI. - // Note if setURL is not called, getURL returns the default value of "jdbc:sqlserver://". + // Note if setURL is not called, getURL returns the default value of + // "jdbc:sqlserver://". + @Override public void setURL(String url) { loggerExternal.entering(getClassNameLogging(), "setURL", url); // URL is not stored in a property set, it is maintained separately. @@ -632,6 +658,7 @@ public void setURL(String url) { loggerExternal.exiting(getClassNameLogging(), "setURL"); } + @Override public String getURL() { String url = dataSourceURL; loggerExternal.entering(getClassNameLogging(), "getURL"); @@ -643,15 +670,16 @@ public String getURL() { } // DataSource specific property setters/getters. - // Per JDBC specification 16.1.1 "...the only property that all DataSource // implementations are required to support is the description property". + @Override public void setDescription(String description) { loggerExternal.entering(getClassNameLogging(), "setDescription", description); dataSourceDescription = description; loggerExternal.exiting(getClassNameLogging(), "setDescription"); } + @Override public String getDescription() { loggerExternal.entering(getClassNameLogging(), "getDescription"); loggerExternal.exiting(getClassNameLogging(), "getDescription", dataSourceDescription); @@ -662,188 +690,121 @@ public String getDescription() { // buffer. It is also the value used for the TDS packet size (SQL Server // Network Packet Size). Validity of the value is checked at connect time. // If no value is set for this property, its default value is 4KB. + @Override public void setPacketSize(int packetSize) { setIntProperty(connectionProps, SQLServerDriverIntProperty.PACKET_SIZE.toString(), packetSize); } + @Override public int getPacketSize() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.PACKET_SIZE.toString(), SQLServerDriverIntProperty.PACKET_SIZE.getDefaultValue()); } - /** - * Setting the query timeout - * - * @param queryTimeout - * The number of seconds to wait before a timeout has occurred on a query. The default value is 0, which means infinite timeout. - */ + @Override public void setQueryTimeout(int queryTimeout) { setIntProperty(connectionProps, SQLServerDriverIntProperty.QUERY_TIMEOUT.toString(), queryTimeout); } - /** - * Getting the query timeout - * - * @return The number of seconds to wait before a timeout has occurred on a query. - */ + @Override public int getQueryTimeout() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.QUERY_TIMEOUT.toString(), SQLServerDriverIntProperty.QUERY_TIMEOUT.getDefaultValue()); } - - /** - * Setting the cancel timeout - * - * @param cancelQueryTimeout - * The number of seconds to wait before we wait for the query timeout to happen. - */ + + @Override public void setCancelQueryTimeout(int cancelQueryTimeout) { setIntProperty(connectionProps, SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.toString(), cancelQueryTimeout); } - /** - * Getting the cancel timeout - * - * @return the number of seconds to wait before we wait for the query timeout to happen. - */ + @Override public int getCancelQueryTimeout() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.toString(), SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.getDefaultValue()); } - /** - * If this configuration is false the first execution of a prepared statement will call sp_executesql and not prepare - * a statement, once the second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following - * executions will call sp_execute. This relieves the need for sp_unprepare on prepared statement close if the statement is only - * executed once. - * - * @param enablePrepareOnFirstPreparedStatementCall - * Changes the setting per the description. - */ + @Override public void setEnablePrepareOnFirstPreparedStatementCall(boolean enablePrepareOnFirstPreparedStatementCall) { - setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.toString(), enablePrepareOnFirstPreparedStatementCall); + setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.toString(), + enablePrepareOnFirstPreparedStatementCall); } - /** - * If this configuration returns false the first execution of a prepared statement will call sp_executesql and not prepare a statement, once the - * second execution happens it will call sp_prepexec and actually setup a prepared statement handle. Following executions will call sp_execute. - * This relieves the need for sp_unprepare on prepared statement close if the statement is only executed once. - * - * @return Returns the current setting per the description. - */ + @Override public boolean getEnablePrepareOnFirstPreparedStatementCall() { boolean defaultValue = SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.getDefaultValue(); return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.toString(), defaultValue); } - /** - * This setting controls how many outstanding prepared statement discard actions (sp_unprepare) can be outstanding per connection before a call to - * clean-up the outstanding handles on the server is executed. If the setting is {@literal <=} 1 unprepare actions will be executed immedietely on - * prepared statement close. If it is set to {@literal >} 1 these calls will be batched together to avoid overhead of calling sp_unprepare too - * often. - * - * @param serverPreparedStatementDiscardThreshold - * Changes the setting per the description. - */ + @Override public void setServerPreparedStatementDiscardThreshold(int serverPreparedStatementDiscardThreshold) { - setIntProperty(connectionProps, SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), serverPreparedStatementDiscardThreshold); + setIntProperty(connectionProps, SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), + serverPreparedStatementDiscardThreshold); } - /** - * This setting controls how many outstanding prepared statement discard actions (sp_unprepare) can be outstanding per connection before a call to - * clean-up the outstanding handles on the server is executed. If the setting is {@literal <=} 1 unprepare actions will be executed immedietely on - * prepared statement close. If it is set to {@literal >} 1 these calls will be batched together to avoid overhead of calling sp_unprepare too - * often. - * - * @return Returns the current setting per the description. - */ + @Override public int getServerPreparedStatementDiscardThreshold() { int defaultSize = SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.getDefaultValue(); return getIntProperty(connectionProps, SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), defaultSize); } - /** - * Specifies the size of the prepared statement cache for this connection. A value less than 1 means no cache. - * - * @param statementPoolingCacheSize - * Changes the setting per the description. - */ + @Override public void setStatementPoolingCacheSize(int statementPoolingCacheSize) { setIntProperty(connectionProps, SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.toString(), statementPoolingCacheSize); } - /** - * Returns the size of the prepared statement cache for this connection. A value less than 1 means no cache. - * - * @return Returns the current setting per the description. - */ + @Override public int getStatementPoolingCacheSize() { int defaultSize = SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.getDefaultValue(); return getIntProperty(connectionProps, SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.toString(), defaultSize); } - - /** - * Disable/enable statement pooling. - * @param disableStatementPooling true to disable statement pooling, false to enable it. - */ + + @Override public void setDisableStatementPooling(boolean disableStatementPooling) { - setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), disableStatementPooling); + setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), disableStatementPooling); } - - /** - * Determine whether statement pooling is disabled. - * @return true if statement pooling is disabled, false if it is enabled. - */ + + @Override public boolean getDisableStatementPooling() { boolean defaultValue = SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.getDefaultValue(); - return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), - defaultValue); + return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), defaultValue); } - /** - * Setting the socket timeout - * - * @param socketTimeout - * The number of milliseconds to wait before a timeout is occurred on a socket read or accept. The default value is 0, which means - * infinite timeout. - */ + @Override public void setSocketTimeout(int socketTimeout) { setIntProperty(connectionProps, SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), socketTimeout); } - /** - * Getting the socket timeout - * - * @return The number of milliseconds to wait before a timeout is occurred on a socket read or accept. - */ + @Override public int getSocketTimeout() { int defaultTimeOut = SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue(); return getIntProperty(connectionProps, SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), defaultTimeOut); } - /** - * Sets the login configuration file for Kerberos authentication. This - * overrides the default configuration SQLJDBCDriver - * - * @param configurationName the configuration name - */ + @Override + public void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert) { + setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.toString(), useBulkCopyForBatchInsert); + } + + @Override + public boolean getUseBulkCopyForBatchInsert() { + return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.toString(), + SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.getDefaultValue()); + } + + @Override public void setJASSConfigurationName(String configurationName) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), - configurationName); + setStringProperty(connectionProps, SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), configurationName); } - /** - * Retrieves the login configuration file for Kerberos authentication. - * - * @return login configuration file name - */ + @Override public String getJASSConfigurationName() { return getStringProperty(connectionProps, SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue()); } - - // responseBuffering controls the driver's buffering of responses from SQL Server. + + // responseBuffering controls the driver's buffering of responses from SQL + // Server. // Possible values are: // // "full" - Fully buffer the response at execution time. @@ -865,7 +826,8 @@ public String getJASSConfigurationName() { // Set a string property value. // Caller will always supply a non-null props and propKey. - // Caller may supply a null propValue, in this case no property value is set. + // Caller may supply a null propValue, in this case no property value is + // set. private void setStringProperty(Properties props, String propKey, String propValue) { @@ -987,21 +949,25 @@ private Object getObjectProperty(Properties props, loggerExternal.exiting(getClassNameLogging(), "get" + propKey); return propValue; } - - // Returns a SQLServerConnection given username, password, and pooledConnection. - // Note that the DataSource properties set to connectionProps are used when creating + + // Returns a SQLServerConnection given username, password, and + // pooledConnection. + // Note that the DataSource properties set to connectionProps are used when + // creating // the connection. // Both username and password can be null. - // If pooledConnection is not null, then connection returned is attached to the pooledConnection + // If pooledConnection is not null, then connection returned is attached to + // the pooledConnection // and participates in connection pooling. SQLServerConnection getConnectionInternal(String username, String password, SQLServerPooledConnection pooledConnection) throws SQLServerException { Properties userSuppliedProps; Properties mergedProps; - // Trust store password stripped and this object got created via Objectfactory referencing. + // Trust store password stripped and this object got created via + // Objectfactory referencing. if (trustStorePasswordStripped) SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_referencingFailedTSP"), null, true); @@ -1028,7 +994,8 @@ SQLServerConnection getConnectionInternal(String username, // Merge in URL properties into userSuppliedProps if URL is set. if (null != dataSourceURL) { Properties urlProps = Util.parseUrl(dataSourceURL, dsLogger); - // null returned properties means that the passed in URL is not supported. + // null returned properties means that the passed in URL is not + // supported. if (null == urlProps) SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_errorConnectionString"), null, true); // Manually merge URL props and user supplied props. @@ -1056,6 +1023,7 @@ SQLServerConnection getConnectionInternal(String username, // Implement javax.naming.Referenceable interface methods. + @Override public Reference getReference() { loggerExternal.entering(getClassNameLogging(), "getReference"); Reference ref = getReferenceInternal("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); @@ -1078,20 +1046,24 @@ Reference getReferenceInternal(String dataSourceClassString) { Enumeration e = connectionProps.keys(); while (e.hasMoreElements()) { String propertyName = (String) e.nextElement(); - // If a trustStore password is set, it is omitted and a trustStorePasswordSet flag is set. + // If a trustStore password is set, it is omitted and a + // trustStorePasswordSet flag is set. if (propertyName.equals(SQLServerDriverStringProperty.TRUST_STORE_PASSWORD.toString())) { - // The property set and the variable set at the same time is not possible + // The property set and the variable set at the same time is not + // possible assert trustStorePasswordStripped == false; ref.add(new StringRefAddr("trustStorePasswordStripped", "true")); } else { - // do not add passwords to the collection. we have normal password + // do not add passwords to the collection. we have normal + // password if (!propertyName.contains(SQLServerDriverStringProperty.PASSWORD.toString())) ref.add(new StringRefAddr(propertyName, connectionProps.getProperty(propertyName))); } } - // Add dataSourceURL and dataSourceDescription as these will not appear in connectionProps. + // Add dataSourceURL and dataSourceDescription as these will not appear + // in connectionProps. if (null != dataSourceURL) ref.add(new StringRefAddr("dataSourceURL", dataSourceURL)); @@ -1101,10 +1073,13 @@ Reference getReferenceInternal(String dataSourceClassString) { return ref; } - // Initialize this datasource from properties found inside the reference ref. - // Called by SQLServerDataSourceObjectFactory to initialize new DataSource instance. + // Initialize this datasource from properties found inside the reference + // ref. + // Called by SQLServerDataSourceObjectFactory to initialize new DataSource + // instance. void initializeFromReference(javax.naming.Reference ref) { - // Enumerate all the StringRefAddr objects in the Reference and assign properties appropriately. + // Enumerate all the StringRefAddr objects in the Reference and assign + // properties appropriately. Enumeration e = ref.getAll(); while (e.hasMoreElements()) { StringRefAddr addr = (StringRefAddr) e.nextElement(); @@ -1121,7 +1096,8 @@ else if ("dataSourceDescription".equals(propertyName)) { else if ("trustStorePasswordStripped".equals(propertyName)) { trustStorePasswordStripped = true; } - // Just skip "class" StringRefAddr, it does not go into connectionProps + // Just skip "class" StringRefAddr, it does not go into + // connectionProps else if (!"class".equals(propertyName)) { connectionProps.setProperty(propertyName, propertyValue); @@ -1129,6 +1105,7 @@ else if (!"class".equals(propertyName)) { } } + @Override public boolean isWrapperFor(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "isWrapperFor", iface); boolean f = iface.isInstance(this); @@ -1136,6 +1113,7 @@ public boolean isWrapperFor(Class iface) throws SQLException { return f; } + @Override public T unwrap(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "unwrap", iface); T t; @@ -1149,7 +1127,6 @@ public T unwrap(Class iface) throws SQLException { return t; } - // Returns unique id for each DataSource instance. private static int nextDataSourceID() { return baseDataSourceID.incrementAndGet(); @@ -1160,8 +1137,10 @@ private Object writeReplace() throws java.io.ObjectStreamException { } private void readObject(java.io.ObjectInputStream stream) throws java.io.InvalidObjectException { - // For added security/robustness, the only way to rehydrate a serialized SQLServerDataSource - // is to use a SerializationProxy. Direct use of readObject() is not supported. + // For added security/robustness, the only way to rehydrate a serialized + // SQLServerDataSource + // is to use a SerializationProxy. Direct use of readObject() is not + // supported. throw new java.io.InvalidObjectException(""); } @@ -1171,7 +1150,8 @@ private static class SerializationProxy implements java.io.Serializable { private static final long serialVersionUID = 654661379542314226L; SerializationProxy(SQLServerDataSource ds) { - // We do not need the class name so pass null, serialization mechanism + // We do not need the class name so pass null, serialization + // mechanism // stores the class info. ref = ds.getReferenceInternal(null); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java index 6518d7057..256635954 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java @@ -45,13 +45,14 @@ public Object getObjectInstance(Object ref, // Our reference will always have a "class" RefAddr. if (null == ra) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); + throwInvalidDataSourceRefException(); } String className = (String) ra.getContent(); - if (null == className) - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); + if (null == className) { + throwInvalidDataSourceRefException(); + } // Check that we have the expected class name inside our reference. if (("com.microsoft.sqlserver.jdbc.SQLServerDataSource").equals(className) @@ -69,32 +70,18 @@ public Object getObjectInstance(Object ref, return dataSourceClassInstance; } // Class not found, throw invalid reference exception. - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (ClassNotFoundException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (InstantiationException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (IllegalAccessException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); + throwInvalidDataSourceRefException(); } - catch (IllegalArgumentException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (InvocationTargetException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (NoSuchMethodException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); - } - catch (SecurityException e) { - SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); + catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throwInvalidDataSourceRefException(); } // no chance of getting here but to keep the compiler happy return null; + } + private void throwInvalidDataSourceRefException() throws SQLServerException { + SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java index 60188841a..1e894bdf9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java @@ -97,7 +97,6 @@ public synchronized void addColumnMetadata(SQLServerDataColumn column) throws SQ columnMetadata.put(columnCount++, column); } - /** * Adds one row of data to the data table. * @@ -139,14 +138,20 @@ public synchronized void addRow(Object... values) throws SQLServerException { } } - + /** * Adding rows one row of data to data table. - * @param jdbcType The jdbcType - * @param val The data value - * @param rowValues Row of data - * @param pair pair to be added to data table + * + * @param jdbcType + * The jdbcType + * @param val + * The data value + * @param rowValues + * Row of data + * @param pair + * pair to be added to data table * @throws SQLServerException + * when an error occurs */ private void internalAddrow(JDBCType jdbcType, Object val, @@ -218,7 +223,6 @@ private void internalAddrow(JDBCType jdbcType, case TIMESTAMP_WITH_TIMEZONE: case TIME_WITH_TIMEZONE: - DriverJDBCVersion.checkSupportsJDBC42(); case DATE: case TIME: case TIMESTAMP: @@ -290,17 +294,29 @@ else if (val instanceof OffsetTime) throw new SQLServerException(null, form.format(msgArgs), null, 0, false); } } - + + /** + * Retrieves java.util.Map object type of columnMetaData for all columns where column indexes are mapped with their + * respective {@link SQLServerDataColumn} Java object + * + * @return Map + */ public synchronized Map getColumnMetadata() { return columnMetadata; } + /** + * Returns name of TVP type set by {@link #setTvpName(String)} + * + * @return tvpName + */ public String getTvpName() { return tvpName; } /** - * Retrieves the column meta data of this data table. + * Sets the TVP Name + * * @param tvpName * the name of TVP */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java index 3f3ed20f8..9c9fb5513 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java @@ -38,7 +38,15 @@ public final class SQLServerDatabaseMetaData implements java.sql.DatabaseMetaDat static final private java.util.logging.Logger loggerExternal = java.util.logging.Logger .getLogger("com.microsoft.sqlserver.jdbc.internals.DatabaseMetaData"); - static private final AtomicInteger baseID = new AtomicInteger(0); // Unique id generator for each instance (used for logging). + static private final AtomicInteger baseID = new AtomicInteger(0); // Unique + // id + // generator + // for + // each + // instance + // (used + // for + // logging). final private String traceID; @@ -47,18 +55,17 @@ public final class SQLServerDatabaseMetaData implements java.sql.DatabaseMetaDat // uniqueidentifier https://msdn.microsoft.com/en-us/library/ms187942.aspx static final int uniqueidentifierSize = 36; - enum CallableHandles - { - SP_COLUMNS ("{ call sp_columns(?, ?, ?, ?, ?) }", "{ call sp_columns_100(?, ?, ?, ?, ?, ?) }"), - SP_COLUMN_PRIVILEGES ("{ call sp_column_privileges(?, ?, ?, ?)}", "{ call sp_column_privileges(?, ?, ?, ?)}"), - SP_TABLES ("{ call sp_tables(?, ?, ?, ?) }", "{ call sp_tables(?, ?, ?, ?) }"), - SP_SPECIAL_COLUMNS ("{ call sp_special_columns (?, ?, ?, ?, ?, ?, ?)}","{ call sp_special_columns_100 (?, ?, ?, ?, ?, ?, ?)}"), - SP_FKEYS ("{ call sp_fkeys (?, ?, ?, ? , ? ,?)}", "{ call sp_fkeys (?, ?, ?, ? , ? ,?)}"), - SP_STATISTICS ("{ call sp_statistics(?,?,?,?,?, ?) }", "{ call sp_statistics_100(?,?,?,?,?, ?) }"), - SP_SPROC_COLUMNS ("{ call sp_sproc_columns(?, ?, ?,?,?) }", "{ call sp_sproc_columns_100(?, ?, ?,?,?) }"), - SP_STORED_PROCEDURES ("{call sp_stored_procedures(?, ?, ?) }", "{call sp_stored_procedures(?, ?, ?) }"), - SP_TABLE_PRIVILEGES ("{call sp_table_privileges(?,?,?) }", "{call sp_table_privileges(?,?,?) }"), - SP_PKEYS ("{ call sp_pkeys (?, ?, ?)}", "{ call sp_pkeys (?, ?, ?)}"); + enum CallableHandles { + SP_COLUMNS("{ call sp_columns(?, ?, ?, ?, ?) }", "{ call sp_columns_100(?, ?, ?, ?, ?, ?) }"), + SP_COLUMN_PRIVILEGES("{ call sp_column_privileges(?, ?, ?, ?)}", "{ call sp_column_privileges(?, ?, ?, ?)}"), + SP_TABLES("{ call sp_tables(?, ?, ?, ?) }", "{ call sp_tables(?, ?, ?, ?) }"), + SP_SPECIAL_COLUMNS("{ call sp_special_columns (?, ?, ?, ?, ?, ?, ?)}", "{ call sp_special_columns_100 (?, ?, ?, ?, ?, ?, ?)}"), + SP_FKEYS("{ call sp_fkeys (?, ?, ?, ? , ? ,?)}", "{ call sp_fkeys (?, ?, ?, ? , ? ,?)}"), + SP_STATISTICS("{ call sp_statistics(?,?,?,?,?, ?) }", "{ call sp_statistics_100(?,?,?,?,?, ?) }"), + SP_SPROC_COLUMNS("{ call sp_sproc_columns(?, ?, ?,?,?) }", "{ call sp_sproc_columns_100(?, ?, ?,?,?) }"), + SP_STORED_PROCEDURES("{call sp_stored_procedures(?, ?, ?) }", "{call sp_stored_procedures(?, ?, ?) }"), + SP_TABLE_PRIVILEGES("{call sp_table_privileges(?,?,?) }", "{call sp_table_privileges(?,?,?) }"), + SP_PKEYS("{ call sp_pkeys (?, ?, ?)}", "{ call sp_pkeys (?, ?, ?)}"); // stored procs before Katmai ie SS10 private final String preKatProc; // procs on or after katmai @@ -112,7 +119,7 @@ final public String toString() { * @param con * the connection */ - /* L0 */ public SQLServerDatabaseMetaData(SQLServerConnection con) { + public SQLServerDatabaseMetaData(SQLServerConnection con) { traceID = " SQLServerDatabaseMetaData:" + nextInstanceID(); connection = con; if (logger.isLoggable(java.util.logging.Level.FINE)) { @@ -120,11 +127,13 @@ final public String toString() { } } + @Override public boolean isWrapperFor(Class iface) throws SQLException { boolean f = iface.isInstance(this); return f; } + @Override public T unwrap(Class iface) throws SQLException { T t; try { @@ -236,7 +245,7 @@ private void checkClosed() throws SQLServerException { * @param query * to execute * @return Resultset from the execution - * @throws SQLTimeoutException + * @throws SQLTimeoutException */ private SQLServerResultSet getResultSetFromInternalQueries(String catalog, String query) throws SQLServerException, SQLTimeoutException { @@ -283,7 +292,7 @@ private CallableStatement getCallableStatementHandle(CallableHandles request, * @param arguments * for the stored procedure * @return Resultset from the execution - * @throws SQLTimeoutException + * @throws SQLTimeoutException */ private SQLServerResultSet getResultSetFromStoredProc(String catalog, CallableHandles procedure, @@ -331,7 +340,7 @@ private SQLServerResultSet getResultSetWithProvidedColumnNames(String catalog, * @throws SQLServerException * @return the old catalog */ - /* L0 */ private String switchCatalogs(String catalog) throws SQLServerException { + private String switchCatalogs(String catalog) throws SQLServerException { if (catalog == null) return null; String sCurr = null; @@ -347,80 +356,92 @@ private SQLServerResultSet getResultSetWithProvidedColumnNames(String catalog, /* -------------- JDBC Interface API starts here ---------------- */ - /* L0 */ public boolean allProceduresAreCallable() throws SQLServerException { + @Override + public boolean allProceduresAreCallable() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean allTablesAreSelectable() throws SQLServerException { + @Override + public boolean allTablesAreSelectable() throws SQLServerException { checkClosed(); return true; } + @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { checkClosed(); return false; } - /* L0 */ public boolean dataDefinitionCausesTransactionCommit() throws SQLServerException { + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean dataDefinitionIgnoredInTransactions() throws SQLServerException { + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean doesMaxRowSizeIncludeBlobs() throws SQLServerException { + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLServerException { checkClosed(); return false; } + @Override public boolean generatedKeyAlwaysReturned() throws SQLException { checkClosed(); - // driver supports retrieving generated keys return true; } + @Override public long getMaxLogicalLobSize() throws SQLException { - DriverJDBCVersion.checkSupportsJDBC42(); checkClosed(); - return MAXLOBSIZE; } + @Override public boolean supportsRefCursors() throws SQLException { - DriverJDBCVersion.checkSupportsJDBC42(); checkClosed(); - return false; } + @Override public boolean supportsSharding() throws SQLException { DriverJDBCVersion.checkSupportsJDBC43(); checkClosed(); - return false; } - /* L0 */ public java.sql.ResultSet getCatalogs() throws SQLServerException, SQLTimeoutException { + @Override + public java.sql.ResultSet getCatalogs() throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } checkClosed(); // Return the orginal case instead of CAPS.removed Upper(). - String s = "SELECT name AS TABLE_CAT FROM sys.databases order by name"; // Need to match case of connection.getCatalog + String s = "SELECT name AS TABLE_CAT FROM sys.databases order by name"; // Need + // to + // match + // case + // of + // connection.getCatalog return getResultSetFromInternalQueries(null, s); } - /* L0 */ public String getCatalogSeparator() throws SQLServerException { + @Override + public String getCatalogSeparator() throws SQLServerException { checkClosed(); return "."; } - /* L0 */ public String getCatalogTerm() throws SQLServerException { + @Override + public String getCatalogTerm() throws SQLServerException { checkClosed(); return "database"; } @@ -428,7 +449,8 @@ public boolean supportsSharding() throws SQLException { private static final String[] getColumnPrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME, /* 5 */ GRANTOR, /* 6 */ GRANTEE, /* 7 */ PRIVILEGE, /* 8 */ IS_GRANTABLE}; - /* L0 */ public java.sql.ResultSet getColumnPrivileges(String catalog, + @Override + public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String col) throws SQLServerException, SQLTimeoutException { @@ -454,7 +476,8 @@ public boolean supportsSharding() throws SQLException { private static final String[] getTablesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ TABLE_TYPE, /* 5 */ REMARKS}; - /* L0 */ public java.sql.ResultSet getTables(String catalog, + @Override + public java.sql.ResultSet getTables(String catalog, String schema, String table, String types[]) throws SQLServerException, SQLTimeoutException { @@ -555,8 +578,10 @@ private static String EscapeIDName(String inID) throws SQLServerException { /* 5 */ DATA_TYPE, /* 6 */ TYPE_NAME, /* 7 */ COLUMN_SIZE, /* 8 */ BUFFER_LENGTH, /* 9 */ DECIMAL_DIGITS, /* 10 */ NUM_PREC_RADIX, /* 11 */ NULLABLE, /* 12 */ REMARKS, /* 13 */ COLUMN_DEF, /* 14 */ SQL_DATA_TYPE, /* 15 */ SQL_DATETIME_SUB, /* 16 */ CHAR_OCTET_LENGTH, /* 17 */ ORDINAL_POSITION, /* 18 */ IS_NULLABLE}; - // SQL10 columns not exahustive we only need to set until the one we want to change - // in this case we want to change SS_IS_IDENTITY 22nd column to IS_AUTOINCREMENT + // SQL10 columns not exahustive we only need to set until the one we want to + // change + // in this case we want to change SS_IS_IDENTITY 22nd column to + // IS_AUTOINCREMENT // to be inline with JDBC spec private static final String[] getColumnsColumnNamesKatmai = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME, /* 5 */ DATA_TYPE, /* 6 */ TYPE_NAME, /* 7 */ COLUMN_SIZE, /* 8 */ BUFFER_LENGTH, /* 9 */ DECIMAL_DIGITS, /* 10 */ NUM_PREC_RADIX, @@ -564,7 +589,8 @@ private static String EscapeIDName(String inID) throws SQLServerException { /* 17 */ ORDINAL_POSITION, /* 18 */ IS_NULLABLE, /* 20 */ SS_IS_SPARSE, /* 20 */ SS_IS_COLUMN_SET, /* 21 */ IS_GENERATEDCOLUMN, /* 22 */ IS_AUTOINCREMENT}; - /* L0 */ public java.sql.ResultSet getColumns(String catalog, + @Override + public java.sql.ResultSet getColumns(String catalog, String schema, String table, String col) throws SQLServerException, SQLTimeoutException { @@ -592,7 +618,8 @@ private static String EscapeIDName(String inID) throws SQLServerException { arguments[2] = catalog; arguments[3] = column; if (connection.isKatmaiOrLater()) { - arguments[4] = "2"; // give information about everything including sparse columns + arguments[4] = "2"; // give information about everything including + // sparse columns arguments[5] = "3"; // odbc version } else @@ -619,6 +646,7 @@ private static String EscapeIDName(String inID) throws SQLServerException { private static final String[] getFunctionsColumnNames = {/* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM, /* 3 */ FUNCTION_NAME, /* 4 */ NUM_INPUT_PARAMS, /* 5 */ NUM_OUTPUT_PARAMS, /* 6 */ NUM_RESULT_SETS, /* 7 */ REMARKS, /* 8 */ FUNCTION_TYPE}; + @Override public java.sql.ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { @@ -647,6 +675,7 @@ public java.sql.ResultSet getFunctions(String catalog, /* 11 */ RADIX, /* 12 */ NULLABLE, /* 13 */ REMARKS, /* 14 */ COLUMN_DEF, /* 15 */ SQL_DATA_TYPE, /* 16 */ SQL_DATETIME_SUB, /* 17 */ CHAR_OCTET_LENGTH, /* 18 */ ORDINAL_POSITION, /* 19 */ IS_NULLABLE}; + @Override public java.sql.ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, @@ -690,6 +719,7 @@ public java.sql.ResultSet getFunctionColumns(String catalog, return rs; } + @Override public java.sql.ResultSet getClientInfoProperties() throws SQLException { checkClosed(); return getResultSetFromInternalQueries(null, "SELECT" + @@ -702,7 +732,8 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException { private static final String[] getBestRowIdentifierColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME, /* 5 */ COLUMN_SIZE, /* 6 */ BUFFER_LENGTH, /* 7 */ DECIMAL_DIGITS, /* 8 */ PSEUDO_COLUMN}; - /* L0 */ public java.sql.ResultSet getBestRowIdentifier(String catalog, + @Override + public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, @@ -739,7 +770,8 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException { return rs; } - /* L0 */ public java.sql.ResultSet getCrossReference(String cat1, + @Override + public java.sql.ResultSet getCrossReference(String cat1, String schem1, String tab1, String cat2, @@ -758,35 +790,42 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException { return executeSPFkeys(arguments); } - /* L0 */ public String getDatabaseProductName() throws SQLServerException { + @Override + public String getDatabaseProductName() throws SQLServerException { checkClosed(); return "Microsoft SQL Server"; } - /* L0 */ public String getDatabaseProductVersion() throws SQLServerException { + @Override + public String getDatabaseProductVersion() throws SQLServerException { checkClosed(); return connection.sqlServerVersion; } - /* L0 */ public int getDefaultTransactionIsolation() throws SQLServerException { + @Override + public int getDefaultTransactionIsolation() throws SQLServerException { checkClosed(); return java.sql.Connection.TRANSACTION_READ_COMMITTED; } - /* L0 */ public int getDriverMajorVersion() { + @Override + public int getDriverMajorVersion() { return SQLJdbcVersion.major; } - /* L0 */ public int getDriverMinorVersion() { + @Override + public int getDriverMinorVersion() { return SQLJdbcVersion.minor; } - /* L0 */ public String getDriverName() throws SQLServerException { + @Override + public String getDriverName() throws SQLServerException { checkClosed(); return SQLServerDriver.PRODUCT_NAME; } - /* L0 */ public String getDriverVersion() throws SQLServerException { + @Override + public String getDriverVersion() throws SQLServerException { // driver version in the Major.Minor.MMDD.Revision form int n = getDriverMinorVersion(); @@ -799,80 +838,70 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException { return s; } - /* L0 */ public java.sql.ResultSet getExportedKeys(String cat, + @Override + public java.sql.ResultSet getExportedKeys(String cat, String schema, String table) throws SQLServerException, SQLTimeoutException { return getCrossReference(cat, schema, table, null, null, null); } - /* L0 */ public String getExtraNameCharacters() throws SQLServerException { + @Override + public String getExtraNameCharacters() throws SQLServerException { checkClosed(); return "$#@"; } - /* L0 */ public String getIdentifierQuoteString() throws SQLServerException { + @Override + public String getIdentifierQuoteString() throws SQLServerException { checkClosed(); return "\""; } - /* L0 */ public java.sql.ResultSet getImportedKeys(String cat, + @Override + public java.sql.ResultSet getImportedKeys(String cat, String schema, String table) throws SQLServerException, SQLTimeoutException { return getCrossReference(null, null, null, cat, schema, table); } - private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, SQLTimeoutException - { + private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, SQLTimeoutException { String tempTableName = "@jdbc_temp_fkeys_result"; - String sql = "DECLARE " + tempTableName + " table (PKTABLE_QUALIFIER sysname, " + - "PKTABLE_OWNER sysname, " + - "PKTABLE_NAME sysname, " + - "PKCOLUMN_NAME sysname, " + - "FKTABLE_QUALIFIER sysname, " + - "FKTABLE_OWNER sysname, " + - "FKTABLE_NAME sysname, " + - "FKCOLUMN_NAME sysname, " + - "KEY_SEQ smallint, " + - "UPDATE_RULE smallint, " + - "DELETE_RULE smallint, " + - "FK_NAME sysname, " + - "PK_NAME sysname, " + - "DEFERRABILITY smallint);" + - "INSERT INTO " + tempTableName + " EXEC sp_fkeys ?,?,?,?,?,?;" + - "SELECT t.PKTABLE_QUALIFIER AS PKTABLE_CAT, " + - "t.PKTABLE_OWNER AS PKTABLE_SCHEM, " + - "t.PKTABLE_NAME, " + - "t.PKCOLUMN_NAME, " + - "t.FKTABLE_QUALIFIER AS FKTABLE_CAT, " + - "t.FKTABLE_OWNER AS FKTABLE_SCHEM, " + - "t.FKTABLE_NAME, " + - "t.FKCOLUMN_NAME, " + - "t.KEY_SEQ, " + - "CASE s.update_referential_action " + - "WHEN 1 THEN 0 " + //cascade - note that sp_fkey and sys.foreign_keys have flipped values for cascade and no action - "WHEN 0 THEN 3 " + //no action - "WHEN 2 THEN 2 " + //set null - "WHEN 3 THEN 4 " + //set default - "END as UPDATE_RULE, " + - "CASE s.delete_referential_action " + - "WHEN 1 THEN 0 " + - "WHEN 0 THEN 3 " + - "WHEN 2 THEN 2 " + - "WHEN 3 THEN 4 " + - "END as DELETE_RULE, " + - "t.FK_NAME, " + - "t.PK_NAME, " + - "t.DEFERRABILITY " + - "FROM " + tempTableName + " t " + - "LEFT JOIN sys.foreign_keys s ON t.FK_NAME = s.name collate database_default;"; + String sql = "DECLARE " + tempTableName + " table (PKTABLE_QUALIFIER sysname, " + "PKTABLE_OWNER sysname, " + "PKTABLE_NAME sysname, " + + "PKCOLUMN_NAME sysname, " + "FKTABLE_QUALIFIER sysname, " + "FKTABLE_OWNER sysname, " + "FKTABLE_NAME sysname, " + + "FKCOLUMN_NAME sysname, " + "KEY_SEQ smallint, " + "UPDATE_RULE smallint, " + "DELETE_RULE smallint, " + "FK_NAME sysname, " + + "PK_NAME sysname, " + "DEFERRABILITY smallint);" + "INSERT INTO " + tempTableName + " EXEC sp_fkeys ?,?,?,?,?,?;" + + "SELECT t.PKTABLE_QUALIFIER AS PKTABLE_CAT, " + "t.PKTABLE_OWNER AS PKTABLE_SCHEM, " + "t.PKTABLE_NAME, " + "t.PKCOLUMN_NAME, " + + "t.FKTABLE_QUALIFIER AS FKTABLE_CAT, " + "t.FKTABLE_OWNER AS FKTABLE_SCHEM, " + "t.FKTABLE_NAME, " + "t.FKCOLUMN_NAME, " + + "t.KEY_SEQ, " + "CASE s.update_referential_action " + "WHEN 1 THEN 0 " + // cascade + // - + // note + // that + // sp_fkey + // and + // sys.foreign_keys + // have + // flipped + // values + // for + // cascade + // and + // no + // action + "WHEN 0 THEN 3 " + // no action + "WHEN 2 THEN 2 " + // set null + "WHEN 3 THEN 4 " + // set default + "END as UPDATE_RULE, " + "CASE s.delete_referential_action " + "WHEN 1 THEN 0 " + "WHEN 0 THEN 3 " + "WHEN 2 THEN 2 " + + "WHEN 3 THEN 4 " + "END as DELETE_RULE, " + "t.FK_NAME, " + "t.PK_NAME, " + "t.DEFERRABILITY " + "FROM " + tempTableName + " t " + + "LEFT JOIN sys.foreign_keys s ON t.FK_NAME = s.name collate database_default;"; SQLServerCallableStatement cstmt = (SQLServerCallableStatement) connection.prepareCall(sql); for (int i = 0; i < 6; i++) { - cstmt.setString(i+1, procParams[i]); + cstmt.setString(i + 1, procParams[i]); } String currentDB = null; - if (procParams[2] != null && procParams[2] != "") {//pktable_qualifier + if (procParams[2] != null && procParams[2] != "") {// pktable_qualifier currentDB = switchCatalogs(procParams[2]); - } else if (procParams[5] != null && procParams[5] != "") {//fktable_qualifier + } + else if (procParams[5] != null && procParams[5] != "") {// fktable_qualifier currentDB = switchCatalogs(procParams[5]); } ResultSet rs = cstmt.executeQuery(); @@ -886,7 +915,8 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, /* 5 */ INDEX_QUALIFIER, /* 6 */ INDEX_NAME, /* 7 */ TYPE, /* 8 */ ORDINAL_POSITION, /* 9 */ COLUMN_NAME, /* 10 */ ASC_OR_DESC, /* 11 */ CARDINALITY, /* 12 */ PAGES, /* 13 */ FILTER_CONDITION}; - /* L0 */ public java.sql.ResultSet getIndexInfo(String cat, + @Override + public java.sql.ResultSet getIndexInfo(String cat, String schema, String table, boolean unique, @@ -916,52 +946,62 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, return getResultSetWithProvidedColumnNames(cat, CallableHandles.SP_STATISTICS, arguments, getIndexInfoColumnNames); } - /* L0 */ public int getMaxBinaryLiteralLength() throws SQLServerException { + @Override + public int getMaxBinaryLiteralLength() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxCatalogNameLength() throws SQLServerException { + @Override + public int getMaxCatalogNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public int getMaxCharLiteralLength() throws SQLServerException { + @Override + public int getMaxCharLiteralLength() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxColumnNameLength() throws SQLServerException { + @Override + public int getMaxColumnNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public int getMaxColumnsInGroupBy() throws SQLServerException { + @Override + public int getMaxColumnsInGroupBy() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxColumnsInIndex() throws SQLServerException { + @Override + public int getMaxColumnsInIndex() throws SQLServerException { checkClosed(); return 16; } - /* L0 */ public int getMaxColumnsInOrderBy() throws SQLServerException { + @Override + public int getMaxColumnsInOrderBy() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxColumnsInSelect() throws SQLServerException { + @Override + public int getMaxColumnsInSelect() throws SQLServerException { checkClosed(); return 4096; } - /* L0 */ public int getMaxColumnsInTable() throws SQLServerException { + @Override + public int getMaxColumnsInTable() throws SQLServerException { checkClosed(); return 1024; } - /* L0 */ public int getMaxConnections() throws SQLServerException, SQLTimeoutException { + @Override + public int getMaxConnections() throws SQLServerException, SQLTimeoutException { checkClosed(); try { String s = "sp_configure 'user connections'"; @@ -976,62 +1016,76 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, } - /* L0 */ public int getMaxCursorNameLength() throws SQLServerException { + @Override + public int getMaxCursorNameLength() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxIndexLength() throws SQLServerException { + @Override + public int getMaxIndexLength() throws SQLServerException { checkClosed(); return 900; } - /* L0 */ public int getMaxProcedureNameLength() throws SQLServerException { + @Override + public int getMaxProcedureNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public int getMaxRowSize() throws SQLServerException { + @Override + public int getMaxRowSize() throws SQLServerException { checkClosed(); return 8060; } - /* L0 */ public int getMaxSchemaNameLength() throws SQLServerException { + @Override + public int getMaxSchemaNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public int getMaxStatementLength() throws SQLServerException { + @Override + public int getMaxStatementLength() throws SQLServerException { checkClosed(); - // SQL Server currently limits to 64K the number of TDS packets per conversation. - // This number multiplied by the size of each TDS packet yields the maximum total - // size of any request to the server, which is therefore an upper bound to the + // SQL Server currently limits to 64K the number of TDS packets per + // conversation. + // This number multiplied by the size of each TDS packet yields the + // maximum total + // size of any request to the server, which is therefore an upper bound + // to the // maximum SQL statement length. return 65536 * connection.getTDSPacketSize(); } - /* L0 */ public int getMaxStatements() throws SQLServerException { + @Override + public int getMaxStatements() throws SQLServerException { checkClosed(); return 0; } - /* L0 */ public int getMaxTableNameLength() throws SQLServerException { + @Override + public int getMaxTableNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public int getMaxTablesInSelect() throws SQLServerException { + @Override + public int getMaxTablesInSelect() throws SQLServerException { checkClosed(); return 256; } - /* L0 */ public int getMaxUserNameLength() throws SQLServerException { + @Override + public int getMaxUserNameLength() throws SQLServerException { checkClosed(); return 128; } - /* L0 */ public String getNumericFunctions() throws SQLServerException { + @Override + public String getNumericFunctions() throws SQLServerException { checkClosed(); return "ABS,ACOS,ASIN,ATAN,ATAN2,CEILING,COS,COT,DEGREES,EXP, FLOOR,LOG,LOG10,MOD,PI,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE"; } @@ -1039,7 +1093,8 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, private static final String[] getPrimaryKeysColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME, /* 5 */ KEY_SEQ, /* 6 */ PK_NAME}; - /* L0 */ public java.sql.ResultSet getPrimaryKeys(String cat, + @Override + public java.sql.ResultSet getPrimaryKeys(String cat, String schema, String table) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1061,7 +1116,8 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, /* 11 */ RADIX, /* 12 */ NULLABLE, /* 13 */ REMARKS, /* 14 */ COLUMN_DEF, /* 15 */ SQL_DATA_TYPE, /* 16 */ SQL_DATETIME_SUB, /* 17 */ CHAR_OCTET_LENGTH, /* 18 */ ORDINAL_POSITION, /* 19 */ IS_NULLABLE}; - /* L0 */ public java.sql.ResultSet getProcedureColumns(String catalog, + @Override + public java.sql.ResultSet getProcedureColumns(String catalog, String schema, String proc, String col) throws SQLServerException, SQLTimeoutException { @@ -1104,7 +1160,8 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, private static final String[] getProceduresColumnNames = {/* 1 */ PROCEDURE_CAT, /* 2 */ PROCEDURE_SCHEM, /* 3 */ PROCEDURE_NAME, /* 4 */ NUM_INPUT_PARAMS, /* 5 */ NUM_OUTPUT_PARAMS, /* 6 */ NUM_RESULT_SETS, /* 7 */ REMARKS, /* 8 */ PROCEDURE_TYPE}; - /* L0 */ public java.sql.ResultSet getProcedures(String catalog, + @Override + public java.sql.ResultSet getProcedures(String catalog, String schema, String proc) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1123,11 +1180,13 @@ private ResultSet executeSPFkeys(String[] procParams) throws SQLServerException, return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_STORED_PROCEDURES, arguments, getProceduresColumnNames); } - /* L0 */ public String getProcedureTerm() throws SQLServerException { + @Override + public String getProcedureTerm() throws SQLServerException { checkClosed(); return "stored procedure"; } + @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, @@ -1139,7 +1198,8 @@ public ResultSet getPseudoColumns(String catalog, checkClosed(); // SQL server does not support pseudo columns for identifiers - // as per http://msdn.microsoft.com/en-us/library/ms378445%28v=sql.110%29.aspx + // as per + // http://msdn.microsoft.com/en-us/library/ms378445%28v=sql.110%29.aspx // so just return empty result set return getResultSetFromInternalQueries(catalog, "SELECT" + /* 1 */ " cast(NULL as char(1)) as TABLE_CAT," + @@ -1156,7 +1216,8 @@ public ResultSet getPseudoColumns(String catalog, /* 13 */ " cast(NULL as char(1)) as IS_NULLABLE" + " where 0 = 1"); } - /* L0 */ public java.sql.ResultSet getSchemas() throws SQLServerException, SQLTimeoutException { + @Override + public java.sql.ResultSet getSchemas() throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } @@ -1169,7 +1230,8 @@ private java.sql.ResultSet getSchemasInternal(String catalog, String schemaPattern) throws SQLServerException, SQLTimeoutException { String s; - // The schemas that return null for catalog name, these are prebuilt schemas shipped by SQLServer, if SQLServer adds anymore of these + // The schemas that return null for catalog name, these are prebuilt + // schemas shipped by SQLServer, if SQLServer adds anymore of these // we need to add them here. String constSchemas = " ('dbo', 'guest','INFORMATION_SCHEMA','sys','db_owner', 'db_accessadmin', 'db_securityadmin', 'db_ddladmin' " + " ,'db_backupoperator','db_datareader','db_datawriter','db_denydatareader','db_denydatawriter') "; @@ -1177,13 +1239,17 @@ private java.sql.ResultSet getSchemasInternal(String catalog, String schema = "sys.schemas"; String schemaName = "sys.schemas.name"; if (null != catalog && catalog.length() != 0) { - schema = catalog + "." + schema; - schemaName = catalog + "." + schemaName; + final String catalogId = Util.escapeSQLId(catalog); + schema = catalogId + "." + schema; + schemaName = catalogId + "." + schemaName; } - // The common schemas need to be under null catalog name however the schemas specific to the particular catalog has to have the current + // The common schemas need to be under null catalog name however the + // schemas specific to the particular catalog has to have the current // catalog name - // to achive this, first we figure out the common schemas by intersecting current catalogs schemas with the const schemas (ie builtinSchemas) + // to achive this, first we figure out the common schemas by + // intersecting current catalogs schemas with the const schemas (ie + // builtinSchemas) s = "select " + schemaName + " 'TABLE_SCHEM',"; if (null != catalog && catalog.length() == 0) { s += "null 'TABLE_CATALOG' "; @@ -1224,7 +1290,8 @@ else if (null != schemaPattern) else { // The prepared statement is not closed after execution. - // Yes we will "leak a server handle" per execution but the connection closure will release them + // Yes we will "leak a server handle" per execution but the + // connection closure will release them // SQLServerPreparedStatement ps = (SQLServerPreparedStatement) connection.prepareStatement(s); ps.setString(1, schemaPattern); @@ -1233,6 +1300,7 @@ else if (null != schemaPattern) return rs; } + @Override public java.sql.ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1241,35 +1309,42 @@ public java.sql.ResultSet getSchemas(String catalog, return getSchemasInternal(catalog, schemaPattern); } - /* L0 */ public String getSchemaTerm() throws SQLServerException { + @Override + public String getSchemaTerm() throws SQLServerException { checkClosed(); return "schema"; } - /* L0 */ public String getSearchStringEscape() throws SQLServerException { + @Override + public String getSearchStringEscape() throws SQLServerException { checkClosed(); return "\\"; } - /* L0 */ public String getSQLKeywords() throws SQLServerException { + @Override + public String getSQLKeywords() throws SQLServerException { checkClosed(); return "BACKUP,BREAK,BROWSE,BULK,CHECKPOINT,CLUSTERED,COMPUTE,CONTAINS,CONTAINSTABLE,DATABASE,DBCC,DENY,DISK,DISTRIBUTED,DUMMY,DUMP,ERRLVL,EXIT,FILE,FILLFACTOR,FREETEXT,FREETEXTTABLE,FUNCTION,HOLDLOCK,IDENTITY_INSERT,IDENTITYCOL,IF,KILL,LINENO,LOAD,NOCHECK,NONCLUSTERED,OFF,OFFSETS,OPENDATASOURCE,OPENQUERY,OPENROWSET,OPENXML,OVER,PERCENT,PLAN,PRINT,PROC,RAISERROR,READTEXT,RECONFIGURE,REPLICATION,RESTORE,RETURN,ROWCOUNT,ROWGUIDCOL,RULE,SAVE,SETUSER,SHUTDOWN,STATISTICS,TEXTSIZE,TOP,TRAN,TRIGGER,TRUNCATE,TSEQUAL,UPDATETEXT,USE,WAITFOR,WHILE,WRITETEXT"; } - /* L0 */ public String getStringFunctions() throws SQLServerException { + @Override + public String getStringFunctions() throws SQLServerException { checkClosed(); return "ASCII,CHAR,CONCAT, DIFFERENCE,INSERT,LCASE,LEFT,LENGTH,LOCATE,LTRIM,REPEAT,REPLACE,RIGHT,RTRIM,SOUNDEX,SPACE,SUBSTRING,UCASE"; } - /* L0 */ public String getSystemFunctions() throws SQLServerException { + @Override + public String getSystemFunctions() throws SQLServerException { checkClosed(); - return "DATABASE,IFNULL,USER"; // The functions no reinstated after the CTS certification. + return "DATABASE,IFNULL,USER"; // The functions no reinstated after the + // CTS certification. } private static final String[] getTablePrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ GRANTOR, /* 5 */ GRANTEE, /* 6 */ PRIVILEGE, /* 7 */ IS_GRANTABLE}; - /* L0 */ public java.sql.ResultSet getTablePrivileges(String catalog, + @Override + public java.sql.ResultSet getTablePrivileges(String catalog, String schema, String table) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1290,7 +1365,8 @@ public java.sql.ResultSet getSchemas(String catalog, return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_TABLE_PRIVILEGES, arguments, getTablePrivilegesColumnNames); } - /* L0 */ public java.sql.ResultSet getTableTypes() throws SQLServerException, SQLTimeoutException { + @Override + public java.sql.ResultSet getTableTypes() throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } @@ -1300,12 +1376,14 @@ public java.sql.ResultSet getSchemas(String catalog, return rs; } - /* L0 */ public String getTimeDateFunctions() throws SQLServerException { + @Override + public String getTimeDateFunctions() throws SQLServerException { checkClosed(); return "CURDATE,CURTIME,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,HOUR,MINUTE,MONTH,MONTHNAME,NOW,QUARTER,SECOND,TIMESTAMPADD,TIMESTAMPDIFF,WEEK,YEAR"; } - /* L0 */ public java.sql.ResultSet getTypeInfo() throws SQLServerException, SQLTimeoutException { + @Override + public java.sql.ResultSet getTypeInfo() throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } @@ -1326,9 +1404,11 @@ public java.sql.ResultSet getSchemas(String catalog, return rs; } - /* L0 */ public String getURL() throws SQLServerException { + @Override + public String getURL() throws SQLServerException { checkClosed(); - // Build up the URL with the connection properties do not hand out user ID and password + // Build up the URL with the connection properties do not hand out user + // ID and password StringBuilder url = new StringBuilder(); // get the properties collection from the connection. Properties props = connection.activeConnectionProperties; @@ -1337,7 +1417,8 @@ public java.sql.ResultSet getSchemas(String catalog, String portNumber = null; String instanceName = null; - // build the connection string without the server name, instance name and port number as these go in the front + // build the connection string without the server name, instance name + // and port number as these go in the front int index = info.length; while (--index >= 0) { String name = info[index].name; @@ -1349,7 +1430,8 @@ public java.sql.ResultSet getSchemas(String catalog, String val = info[index].value; // skip empty strings if (0 != val.length()) { - // special case these server name, instance name and port number as these go in the front + // special case these server name, instance name and port + // number as these go in the front if (name.equals(SQLServerDriverStringProperty.SERVER_NAME.toString())) { serverName = val; } @@ -1387,7 +1469,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return (url.toString()); } - /* L0 */ public String getUserName() throws SQLServerException, SQLTimeoutException { + @Override + public String getUserName() throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } @@ -1419,7 +1502,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { private static final String[] getVersionColumnsColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME, /* 5 */ COLUMN_SIZE, /* 6 */ BUFFER_LENGTH, /* 7 */ DECIMAL_DIGITS, /* 8 */ PSEUDO_COLUMN}; - /* L0 */ public java.sql.ResultSet getVersionColumns(String catalog, + @Override + public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1448,338 +1532,405 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return rs; } - /* L0 */ public boolean isCatalogAtStart() throws SQLServerException { + @Override + public boolean isCatalogAtStart() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean isReadOnly() throws SQLServerException { + @Override + public boolean isReadOnly() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean nullPlusNonNullIsNull() throws SQLServerException { + @Override + public boolean nullPlusNonNullIsNull() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean nullsAreSortedAtEnd() throws SQLServerException { + @Override + public boolean nullsAreSortedAtEnd() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean nullsAreSortedAtStart() throws SQLServerException { + @Override + public boolean nullsAreSortedAtStart() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean nullsAreSortedHigh() throws SQLServerException { + @Override + public boolean nullsAreSortedHigh() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean nullsAreSortedLow() throws SQLServerException { + @Override + public boolean nullsAreSortedLow() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean storesLowerCaseIdentifiers() throws SQLServerException { + @Override + public boolean storesLowerCaseIdentifiers() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean storesLowerCaseQuotedIdentifiers() throws SQLServerException { + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean storesMixedCaseIdentifiers() throws SQLServerException { + @Override + public boolean storesMixedCaseIdentifiers() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean storesMixedCaseQuotedIdentifiers() throws SQLServerException { + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean storesUpperCaseIdentifiers() throws SQLServerException { + @Override + public boolean storesUpperCaseIdentifiers() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean storesUpperCaseQuotedIdentifiers() throws SQLServerException { + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsAlterTableWithAddColumn() throws SQLServerException { + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsAlterTableWithDropColumn() throws SQLServerException { + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsANSI92EntryLevelSQL() throws SQLServerException { + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsANSI92FullSQL() throws SQLServerException { + @Override + public boolean supportsANSI92FullSQL() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsANSI92IntermediateSQL() throws SQLServerException { + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsCatalogsInDataManipulation() throws SQLServerException { + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCatalogsInIndexDefinitions() throws SQLServerException { + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLServerException { + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCatalogsInProcedureCalls() throws SQLServerException { + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCatalogsInTableDefinitions() throws SQLServerException { + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsColumnAliasing() throws SQLServerException { + @Override + public boolean supportsColumnAliasing() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsConvert() throws SQLServerException { + @Override + public boolean supportsConvert() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsConvert(int fromType, + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCoreSQLGrammar() throws SQLServerException { + @Override + public boolean supportsCoreSQLGrammar() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsCorrelatedSubqueries() throws SQLServerException { + @Override + public boolean supportsCorrelatedSubqueries() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLServerException { + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsDataManipulationTransactionsOnly() throws SQLServerException { + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsDifferentTableCorrelationNames() throws SQLServerException { + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsExpressionsInOrderBy() throws SQLServerException { + @Override + public boolean supportsExpressionsInOrderBy() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsExtendedSQLGrammar() throws SQLServerException { + @Override + public boolean supportsExtendedSQLGrammar() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsFullOuterJoins() throws SQLServerException { + @Override + public boolean supportsFullOuterJoins() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsGroupBy() throws SQLServerException { + @Override + public boolean supportsGroupBy() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsGroupByBeyondSelect() throws SQLServerException { + @Override + public boolean supportsGroupByBeyondSelect() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsGroupByUnrelated() throws SQLServerException { + @Override + public boolean supportsGroupByUnrelated() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsIntegrityEnhancementFacility() throws SQLServerException { + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsLikeEscapeClause() throws SQLServerException { + @Override + public boolean supportsLikeEscapeClause() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsLimitedOuterJoins() throws SQLServerException { + @Override + public boolean supportsLimitedOuterJoins() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsMinimumSQLGrammar() throws SQLServerException { + @Override + public boolean supportsMinimumSQLGrammar() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsMixedCaseIdentifiers() throws SQLServerException { + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLServerException { + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsMultipleResultSets() throws SQLServerException { + @Override + public boolean supportsMultipleResultSets() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsMultipleTransactions() throws SQLServerException { + @Override + public boolean supportsMultipleTransactions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsNonNullableColumns() throws SQLServerException { + @Override + public boolean supportsNonNullableColumns() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsOpenCursorsAcrossCommit() throws SQLServerException { + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsOpenCursorsAcrossRollback() throws SQLServerException { + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsOpenStatementsAcrossCommit() throws SQLServerException { + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsOpenStatementsAcrossRollback() throws SQLServerException { + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsOrderByUnrelated() throws SQLServerException { + @Override + public boolean supportsOrderByUnrelated() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsOuterJoins() throws SQLServerException { + @Override + public boolean supportsOuterJoins() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsPositionedDelete() throws SQLServerException { + @Override + public boolean supportsPositionedDelete() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsPositionedUpdate() throws SQLServerException { + @Override + public boolean supportsPositionedUpdate() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSchemasInDataManipulation() throws SQLServerException { + @Override + public boolean supportsSchemasInDataManipulation() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSchemasInIndexDefinitions() throws SQLServerException { + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLServerException { + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSchemasInProcedureCalls() throws SQLServerException { + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSchemasInTableDefinitions() throws SQLServerException { + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSelectForUpdate() throws SQLServerException { + @Override + public boolean supportsSelectForUpdate() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsStoredProcedures() throws SQLServerException { + @Override + public boolean supportsStoredProcedures() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSubqueriesInComparisons() throws SQLServerException { + @Override + public boolean supportsSubqueriesInComparisons() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSubqueriesInExists() throws SQLServerException { + @Override + public boolean supportsSubqueriesInExists() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSubqueriesInIns() throws SQLServerException { + @Override + public boolean supportsSubqueriesInIns() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsSubqueriesInQuantifieds() throws SQLServerException { + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsTableCorrelationNames() throws SQLServerException { + @Override + public boolean supportsTableCorrelationNames() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsTransactionIsolationLevel(int level) throws SQLServerException { + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLServerException { checkClosed(); switch (level) { case Connection.TRANSACTION_READ_UNCOMMITTED: @@ -1792,40 +1943,48 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return false; } - /* L0 */ public boolean supportsTransactions() throws SQLServerException { + @Override + public boolean supportsTransactions() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsUnion() throws SQLServerException { + @Override + public boolean supportsUnion() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean supportsUnionAll() throws SQLServerException { + @Override + public boolean supportsUnionAll() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public boolean usesLocalFilePerTable() throws SQLServerException { + @Override + public boolean usesLocalFilePerTable() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean usesLocalFiles() throws SQLServerException { + @Override + public boolean usesLocalFiles() throws SQLServerException { checkClosed(); return false; } - /* L0 */ public boolean supportsResultSetType(int type) throws SQLServerException { + @Override + public boolean supportsResultSetType(int type) throws SQLServerException { checkClosed(); checkResultType(type); switch (type) { case ResultSet.TYPE_FORWARD_ONLY: case ResultSet.TYPE_SCROLL_INSENSITIVE: case ResultSet.TYPE_SCROLL_SENSITIVE: - // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: insensitive synonym - // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: sensitive synonym + // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: insensitive + // synonym + // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: sensitive + // synonym case SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY: case SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY: case SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC: @@ -1834,7 +1993,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return false; } - /* L0 */ public boolean supportsResultSetConcurrency(int type, + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLServerException { checkClosed(); checkResultType(type); @@ -1842,12 +2002,14 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { switch (type) { case ResultSet.TYPE_FORWARD_ONLY: case ResultSet.TYPE_SCROLL_SENSITIVE: - // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: sensitive synonym + // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: sensitive + // synonym case SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC: case SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY: return true; case ResultSet.TYPE_SCROLL_INSENSITIVE: - // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: sensitive synonym + // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: sensitive + // synonym case SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY: return (ResultSet.CONCUR_READ_ONLY == concurrency); } @@ -1855,7 +2017,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return false; } - /* L0 */ public boolean ownUpdatesAreVisible(int type) throws SQLServerException { + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type @@ -1863,7 +2026,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean ownDeletesAreVisible(int type) throws SQLServerException { + @Override + public boolean ownDeletesAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type @@ -1871,7 +2035,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean ownInsertsAreVisible(int type) throws SQLServerException { + @Override + public boolean ownInsertsAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type @@ -1879,7 +2044,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean othersUpdatesAreVisible(int type) throws SQLServerException { + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type @@ -1887,7 +2053,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean othersDeletesAreVisible(int type) throws SQLServerException { + @Override + public boolean othersDeletesAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type @@ -1895,33 +2062,38 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean othersInsertsAreVisible(int type) throws SQLServerException { + @Override + public boolean othersInsertsAreVisible(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type); } - /* L0 */ public boolean updatesAreDetected(int type) throws SQLServerException { + @Override + public boolean updatesAreDetected(int type) throws SQLServerException { checkClosed(); checkResultType(type); return false; } - /* L0 */ public boolean deletesAreDetected(int type) throws SQLServerException { + @Override + public boolean deletesAreDetected(int type) throws SQLServerException { checkClosed(); checkResultType(type); return (SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type); } // Check the result types to make sure the user does not pass a bad value. - /* L0 */ private void checkResultType(int type) throws SQLServerException { + private void checkResultType(int type) throws SQLServerException { switch (type) { case ResultSet.TYPE_FORWARD_ONLY: case ResultSet.TYPE_SCROLL_INSENSITIVE: case ResultSet.TYPE_SCROLL_SENSITIVE: - // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: synonym TYPE_SCROLL_INSENSITIVE - // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: synonym TYPE_SCROLL_SENSITIVE + // case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: synonym + // TYPE_SCROLL_INSENSITIVE + // case SQLServerResultSet.TYPE_SS_SCROLL_KEYSET: synonym + // TYPE_SCROLL_SENSITIVE case SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY: case SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY: case SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC: @@ -1933,12 +2105,14 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { throw new SQLServerException(null, form.format(msgArgs), null, 0, true); } - // Check the concurrency values and make sure the value is a supported value. - /* L0 */ private void checkConcurrencyType(int type) throws SQLServerException { + // Check the concurrency values and make sure the value is a supported + // value. + private void checkConcurrencyType(int type) throws SQLServerException { switch (type) { case ResultSet.CONCUR_READ_ONLY: case ResultSet.CONCUR_UPDATABLE: - // case SQLServerResultSet.CONCUR_SS_OPTIMISTIC_CC: synonym CONCUR_UPDATABLE + // case SQLServerResultSet.CONCUR_SS_OPTIMISTIC_CC: synonym + // CONCUR_UPDATABLE case SQLServerResultSet.CONCUR_SS_SCROLL_LOCKS: case SQLServerResultSet.CONCUR_SS_OPTIMISTIC_CCVAL: return; @@ -1949,18 +2123,21 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { throw new SQLServerException(null, form.format(msgArgs), null, 0, true); } - /* L0 */ public boolean insertsAreDetected(int type) throws SQLServerException { + @Override + public boolean insertsAreDetected(int type) throws SQLServerException { checkClosed(); checkResultType(type); return false; } - /* L0 */ public boolean supportsBatchUpdates() throws SQLServerException { + @Override + public boolean supportsBatchUpdates() throws SQLServerException { checkClosed(); return true; } - /* L0 */ public java.sql.ResultSet getUDTs(String catalog, + @Override + public java.sql.ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLServerException, SQLTimeoutException { @@ -1978,14 +2155,16 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { /* 7 */ " cast(0 as smallint) as BASE_TYPE" + " where 0 = 1"); } - /* L0 */ public java.sql.Connection getConnection() throws SQLServerException { + @Override + public java.sql.Connection getConnection() throws SQLServerException { checkClosed(); return connection.getConnection(); } /* JDBC 3.0 */ - /* L3 */ public int getSQLStateType() throws SQLServerException { + @Override + public int getSQLStateType() throws SQLServerException { checkClosed(); if (connection != null && connection.xopenStates) return sqlStateXOpen; @@ -1993,7 +2172,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { return sqlStateSQL99; } - /* L3 */ public int getDatabaseMajorVersion() throws SQLServerException { + @Override + public int getDatabaseMajorVersion() throws SQLServerException { checkClosed(); String s = connection.sqlServerVersion; int p = s.indexOf('.'); @@ -2007,7 +2187,8 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { } } - /* L3 */ public int getDatabaseMinorVersion() throws SQLServerException { + @Override + public int getDatabaseMinorVersion() throws SQLServerException { checkClosed(); String s = connection.sqlServerVersion; int p = s.indexOf('.'); @@ -2022,30 +2203,37 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) { } } - /* L3 */ public int getJDBCMajorVersion() throws SQLServerException { + @Override + public int getJDBCMajorVersion() throws SQLServerException { checkClosed(); return DriverJDBCVersion.major; } - /* L3 */ public int getJDBCMinorVersion() throws SQLServerException { + @Override + public int getJDBCMinorVersion() throws SQLServerException { checkClosed(); return DriverJDBCVersion.minor; } - /* L3 */ public int getResultSetHoldability() throws SQLServerException { + @Override + public int getResultSetHoldability() throws SQLServerException { checkClosed(); - return ResultSet.HOLD_CURSORS_OVER_COMMIT; // Hold over commit is the default for SQL Server + return ResultSet.HOLD_CURSORS_OVER_COMMIT; // Hold over commit is the + // default for SQL Server } + @Override public RowIdLifetime getRowIdLifetime() throws SQLException { checkClosed(); return RowIdLifetime.ROWID_UNSUPPORTED; } - /* L3 */ public boolean supportsResultSetHoldability(int holdability) throws SQLServerException { + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLServerException { checkClosed(); if (ResultSet.HOLD_CURSORS_OVER_COMMIT == holdability || ResultSet.CLOSE_CURSORS_AT_COMMIT == holdability) { - return true; // supported one a per connection level only, not statement by statement + return true; // supported one a per connection level only, not + // statement by statement } // if the value is outside of the valid values throw error. @@ -2054,7 +2242,8 @@ public RowIdLifetime getRowIdLifetime() throws SQLException { throw new SQLServerException(null, form.format(msgArgs), null, 0, true); } - /* L3 */ public ResultSet getAttributes(String catalog, + @Override + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLServerException, SQLTimeoutException { @@ -2086,7 +2275,8 @@ public RowIdLifetime getRowIdLifetime() throws SQLException { /* 21 */ " cast(0 as smallint) as SOURCE_DATA_TYPE" + " where 0 = 1"); } - /* L3 */ public ResultSet getSuperTables(String catalog, + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -2100,7 +2290,8 @@ public RowIdLifetime getRowIdLifetime() throws SQLException { /* 4 */ " cast(NULL as char(1)) as SUPERTABLE_NAME" + " where 0 = 1"); } - /* L3 */ public ResultSet getSuperTypes(String catalog, + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -2116,37 +2307,44 @@ public RowIdLifetime getRowIdLifetime() throws SQLException { /* 6 */ " cast(NULL as char(1)) as SUPERTYPE_NAME" + " where 0 = 1"); } - /* L3 */ public boolean supportsGetGeneratedKeys() throws SQLServerException { + @Override + public boolean supportsGetGeneratedKeys() throws SQLServerException { checkClosed(); return true; } - /* L3 */ public boolean supportsMultipleOpenResults() throws SQLServerException { + @Override + public boolean supportsMultipleOpenResults() throws SQLServerException { checkClosed(); return false; } - /* L3 */ public boolean supportsNamedParameters() throws SQLServerException { + @Override + public boolean supportsNamedParameters() throws SQLServerException { checkClosed(); return true; } - /* L3 */ public boolean supportsSavepoints() throws SQLServerException { + @Override + public boolean supportsSavepoints() throws SQLServerException { checkClosed(); return true; } - /* L3 */ public boolean supportsStatementPooling() throws SQLException { + @Override + public boolean supportsStatementPooling() throws SQLException { checkClosed(); return false; } + @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { checkClosed(); return true; } - /* L3 */ public boolean locatorsUpdateCopy() throws SQLException { + @Override + public boolean locatorsUpdateCopy() throws SQLException { checkClosed(); return true; } @@ -2199,7 +2397,8 @@ int oneValueToAnother(int precl) { } } -// abstract class converts one value to another solely based on the column integer value +// abstract class converts one value to another solely based on the column +// integer value // apply to integer columns only abstract class IntColumnFilter extends ColumnFilter { abstract int oneValueToAnother(int value); @@ -2208,8 +2407,10 @@ final Object apply(Object value, JDBCType asJDBCType) throws SQLServerException { if (value == null) return value; - // Assumption: values will only be requested in integral or textual format - // (i.e. not as float, double, BigDecimal, Boolean or bytes). A request to return + // Assumption: values will only be requested in integral or textual + // format + // (i.e. not as float, double, BigDecimal, Boolean or bytes). A request + // to return // a value as anything else results in an exception being thrown. switch (asJDBCType) { @@ -2244,18 +2445,25 @@ final Object apply(Object value, JDBCType asJDBCType) throws SQLServerException { if (value == null) return value; - // Assumption: values will only be requested in integral or textual format - // (i.e. not as float, double, BigDecimal, Boolean or bytes). A request to return + // Assumption: values will only be requested in integral or textual + // format + // (i.e. not as float, double, BigDecimal, Boolean or bytes). A request + // to return // a value as anything else results in an exception being thrown. switch (asJDBCType) { case INTEGER: case SMALLINT: - // This is a way for us to make getObject return a string, not an - // integer. What this means is that getInt/getShort also will return a string. - // However the identity column in the JDBC spec is supposed to return a - // string by default. To get to that default behavior right we are deliberately breaking - // the getInt/getShort behavior which should really error anyways. Only thing is that + // This is a way for us to make getObject return a string, not + // an + // integer. What this means is that getInt/getShort also will + // return a string. + // However the identity column in the JDBC spec is supposed to + // return a + // string by default. To get to that default behavior right we + // are deliberately breaking + // the getInt/getShort behavior which should really error + // anyways. Only thing is that // the user will get a cast exception in this case. assert (value instanceof Number); return zeroOneToYesNo(((Number) value).intValue()); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index 9f13dc3f4..5f67f93db 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -353,7 +353,8 @@ enum SQLServerDriverBooleanProperty TRUST_SERVER_CERTIFICATE ("trustServerCertificate", false), XOPEN_STATES ("xopenStates", false), FIPS ("fips", false), - ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT("enablePrepareOnFirstPreparedStatementCall", SQLServerConnection.DEFAULT_ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT_CALL); + ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT("enablePrepareOnFirstPreparedStatementCall", SQLServerConnection.DEFAULT_ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT_CALL), + USE_BULK_COPY_FOR_BATCH_INSERT ("useBulkCopyForBatchInsert", false); private final String name; private final boolean defaultValue; @@ -429,7 +430,8 @@ public final class SQLServerDriver implements java.sql.Driver { new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.toString(), Integer.toString(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false, new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(), SSLProtocol.TLS_V11.toString(), SSLProtocol.TLS_V12.toString()}), - new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.getDefaultValue()), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.CANCEL_QUERY_TIMEOUT.getDefaultValue()), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.toString(), Boolean.toString(SQLServerDriverBooleanProperty.USE_BULK_COPY_FOR_BATCH_INSERT.getDefaultValue()), false, TRUE_FALSE), }; // Properties that can only be set by using Properties. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java index 80629cc64..18cf1bbac 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java @@ -8,6 +8,7 @@ package com.microsoft.sqlserver.jdbc; +import java.sql.SQLFeatureNotSupportedException; import java.text.MessageFormat; import java.util.UUID; import java.util.logging.Level; @@ -72,6 +73,11 @@ public final class SQLServerException extends java.sql.SQLException { static final int DRIVER_ERROR_INTERMITTENT_TLS_FAILED = 7; static final int ERROR_SOCKET_TIMEOUT = 8; static final int ERROR_QUERY_TIMEOUT = 9; + static final int DATA_CLASSIFICATION_INVALID_VERSION = 10; + static final int DATA_CLASSIFICATION_NOT_EXPECTED = 11; + static final int DATA_CLASSIFICATION_INVALID_LABEL_INDEX = 12; + static final int DATA_CLASSIFICATION_INVALID_INFORMATION_TYPE_INDEX = 13; + private int driverErrorCode = DRIVER_ERROR_NONE; final int getDriverErrorCode() { @@ -92,7 +98,7 @@ final void setDriverErrorCode(int value) { * @param bStack * true to generate the stack trace */ - /* L0 */ private void logException(Object o, + private void logException(Object o, String errText, boolean bStack) { String id = ""; @@ -105,19 +111,20 @@ final void setDriverErrorCode(int value) { if (exLogger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(100); StackTraceElement st[] = this.getStackTrace(); - for (StackTraceElement aSt : st) sb.append(aSt.toString()); + for (StackTraceElement aSt : st) + sb.append(aSt.toString()); Throwable t = this.getCause(); if (t != null) { sb.append("\n caused by " + t + "\n"); StackTraceElement tst[] = t.getStackTrace(); - for (StackTraceElement aTst : tst) sb.append(aTst.toString()); + for (StackTraceElement aTst : tst) + sb.append(aTst.toString()); } exLogger.fine(sb.toString()); } } - if (errText.equals(SQLServerException.getErrString("R_queryTimedOut"))) - { - this.setDriverErrorCode(SQLServerException.ERROR_QUERY_TIMEOUT); + if (errText.equals(SQLServerException.getErrString("R_queryTimedOut"))) { + this.setDriverErrorCode(SQLServerException.ERROR_QUERY_TIMEOUT); } } @@ -397,9 +404,16 @@ static String checkAndAppendClientConnId(String errMsg, sb.append(clientConnId.toString()); return sb.toString(); } - else + else { return errMsg; - + } } + static void throwNotSupportedException(SQLServerConnection con, Object obj) throws SQLServerException { + SQLServerException.makeFromDriverError(con, obj, SQLServerException.getErrString("R_notSupported"), null, false); + } + + static void throwFeatureNotSupportedException() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java index 1950daf62..c37a16729 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java @@ -22,9 +22,6 @@ final class DriverJDBCVersion { static final int major = 4; static final int minor = 2; - static final void checkSupportsJDBC42() { - } - static final void checkSupportsJDBC43() { throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported")); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java index 1f60cd53a..1100f132d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java @@ -24,9 +24,6 @@ final class DriverJDBCVersion { static final void checkSupportsJDBC43() { } - - static final void checkSupportsJDBC42() { - } static final void throwBatchUpdateException(SQLServerException lastError, long[] updateCounts) throws BatchUpdateException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java index 3181cd47d..1849915be 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java @@ -9,6 +9,12 @@ import java.sql.SQLException; -abstract class SQLServerLob { - abstract void fillFromStream() throws SQLException; +abstract class SQLServerLob { + + /** + * Function for the result set to maintain blobs it has created + * + * @throws SQLException + */ + abstract void fillFromStream() throws SQLException; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 4dbf20017..f3930381c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -1,38 +1,127 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.io.UnsupportedEncodingException; -import java.sql.NClob; -import java.util.logging.Logger; - -/** - * SQLServerNClob represents a National Character Set LOB object and implements java.sql.NClob. - */ - -public final class SQLServerNClob extends SQLServerClobBase implements NClob { - - private static final long serialVersionUID = 1L; - - // Loggers should be class static to avoid lock contention with multiple threads - private static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerNClob"); - - SQLServerNClob(SQLServerConnection connection) { - super(connection, "", connection.getDatabaseCollation(), logger, null); - } - - SQLServerNClob(BaseInputStream stream, - TypeInfo typeInfo) throws SQLServerException, UnsupportedEncodingException { - super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo); - } - - final JDBCType getJdbcType() { - return JDBCType.NCLOB; - } -} +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.sql.Clob; +import java.sql.NClob; +import java.sql.SQLException; +import java.util.logging.Logger; + +/** + * SQLServerNClob represents a National Character Set LOB object and implements java.sql.NClob. + */ + +public final class SQLServerNClob extends SQLServerClobBase implements NClob { + + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = 3593610902551842327L; + + // Loggers should be class static to avoid lock contention with multiple + // threads + private static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerNClob"); + + SQLServerNClob(SQLServerConnection connection) { + super(connection, "", connection.getDatabaseCollation(), logger, null); + } + + SQLServerNClob(BaseInputStream stream, + TypeInfo typeInfo) throws SQLServerException, UnsupportedEncodingException { + super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo); + } + + @Override + public void free() throws SQLException { + super.free(); + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return super.getAsciiStream(); + } + + @Override + public Reader getCharacterStream() throws SQLException { + return super.getCharacterStream(); + } + + @Override + public Reader getCharacterStream(long pos, + long length) throws SQLException { + return super.getCharacterStream(pos, length); + } + + @Override + public String getSubString(long pos, + int length) throws SQLException { + return super.getSubString(pos, length); + } + + @Override + public long length() throws SQLException { + return super.length(); + } + + @Override + void fillFromStream() throws SQLException { + super.fillFromStream(); + } + + @Override + public long position(Clob searchstr, + long start) throws SQLException { + return super.position(searchstr, start); + } + + @Override + public long position(String searchstr, + long start) throws SQLException { + return super.position(searchstr, start); + } + + @Override + public void truncate(long len) throws SQLException { + super.truncate(len); + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + return super.setAsciiStream(pos); + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + return super.setCharacterStream(pos); + } + + @Override + public int setString(long pos, + String s) throws SQLException { + return super.setString(pos, s); + } + + @Override + public int setString(long pos, + String str, + int offset, + int len) throws SQLException { + return super.setString(pos, str, offset, len); + } + + @Override + final JDBCType getJdbcType() { + return JDBCType.NCLOB; + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java index dca580ec9..f9ebd3b1c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java @@ -66,6 +66,7 @@ private static int nextInstanceID() { * * @return traceID string */ + @Override final public String toString() { return traceID; } @@ -79,7 +80,7 @@ final public String toString() { * the token that prfixes the column set * @throws SQLServerException */ - /* L2 */ private String parseColumns(String columnSet, + private String parseColumns(String columnSet, String columnStartToken) throws SQLServerException { StringTokenizer st = new StringTokenizer(columnSet, " =?<>!\r\n\t\f", true); final int START = 0; @@ -141,7 +142,7 @@ final public String toString() { * the token that denotes the start of the column set * @throws SQLServerException */ - /* L2 */ private String parseInsertColumns(String sql, + private String parseInsertColumns(String sql, String columnMarker) throws SQLServerException { StringTokenizer st = new StringTokenizer(sql, " (),", true); int nState = 0; @@ -685,11 +686,13 @@ private void checkClosed() throws SQLServerException { } } + @Override public boolean isWrapperFor(Class iface) throws SQLException { boolean f = iface.isInstance(this); return f; } + @Override public T unwrap(Class iface) throws SQLException { T t; try { @@ -701,7 +704,7 @@ public T unwrap(Class iface) throws SQLException { return t; } - /* L2 */ private void verifyParameterPosition(int param) throws SQLServerException { + private void verifyParameterPosition(int param) throws SQLServerException { boolean bFound = false; try { if (((SQLServerPreparedStatement) stmtParent).bReturnValueSyntax && isTVP) { @@ -723,13 +726,14 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ private void checkParam(int n) throws SQLServerException { + private void checkParam(int n) throws SQLServerException { if (!queryMetaMap.containsKey(n)) { SQLServerException.makeFromDriverError(con, stmtParent, SQLServerException.getErrString("R_noMetadata"), null, false); } } - /* L2 */ public String getParameterClassName(int param) throws SQLServerException { + @Override + public String getParameterClassName(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -749,7 +753,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int getParameterCount() throws SQLServerException { + @Override + public int getParameterCount() throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -770,7 +775,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int getParameterMode(int param) throws SQLServerException { + @Override + public int getParameterMode(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -797,7 +803,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int getParameterType(int param) throws SQLServerException { + @Override + public int getParameterType(int param) throws SQLServerException { checkClosed(); int parameterType; @@ -834,7 +841,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public String getParameterTypeName(int param) throws SQLServerException { + @Override + public String getParameterTypeName(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -853,7 +861,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int getPrecision(int param) throws SQLServerException { + @Override + public int getPrecision(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -873,7 +882,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int getScale(int param) throws SQLServerException { + @Override + public int getScale(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -893,7 +903,8 @@ public T unwrap(Class iface) throws SQLException { } } - /* L2 */ public int isNullable(int param) throws SQLServerException { + @Override + public int isNullable(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { @@ -926,7 +937,8 @@ public T unwrap(Class iface) throws SQLException { * when an error occurs * @return boolean */ - /* L2 */ public boolean isSigned(int param) throws SQLServerException { + @Override + public boolean isSigned(int param) throws SQLServerException { checkClosed(); try { if (rsProcedureMeta == null) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java index cc059434d..f17368e6f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java @@ -63,6 +63,7 @@ public class SQLServerPooledConnection implements PooledConnection { * * @return traceID String */ + @Override public String toString() { return traceID; } @@ -79,6 +80,7 @@ private SQLServerConnection createNewConnection() throws SQLException { * when an error occurs * @return a Connection object that is a handle to this PooledConnection object */ + @Override public Connection getConnection() throws SQLException { if (pcLogger.isLoggable(Level.FINER)) pcLogger.finer(toString() + " user:(default)."); @@ -161,6 +163,7 @@ void notifyEvent(SQLServerException e) { } } + @Override public void addConnectionEventListener(ConnectionEventListener listener) { if (pcLogger.isLoggable(Level.FINER)) pcLogger.finer(toString() + safeCID()); @@ -169,6 +172,7 @@ public void addConnectionEventListener(ConnectionEventListener listener) { } } + @Override public void close() throws SQLException { if (pcLogger.isLoggable(Level.FINER)) pcLogger.finer(toString() + " Closing physical connection, " + safeCID()); @@ -189,6 +193,7 @@ public void close() throws SQLException { } + @Override public void removeConnectionEventListener(ConnectionEventListener listener) { if (pcLogger.isLoggable(Level.FINER)) pcLogger.finer(toString() + safeCID()); @@ -197,11 +202,13 @@ public void removeConnectionEventListener(ConnectionEventListener listener) { } } + @Override public void addStatementEventListener(StatementEventListener listener) { // Not implemented throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported")); } + @Override public void removeStatementEventListener(StatementEventListener listener) { // Not implemented throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported")); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index ac8e66fe3..063dabe39 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -6,7 +6,7 @@ * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. */ -package com.microsoft.sqlserver.jdbc; +package com.microsoft.sqlserver.jdbc; import static com.microsoft.sqlserver.jdbc.SQLServerConnection.getCachedParsedSQL; import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; @@ -20,8 +20,8 @@ import java.sql.ResultSet; import java.sql.RowId; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLTimeoutException; +import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Statement; import java.text.MessageFormat; @@ -54,6 +54,7 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS boolean isInternalEncryptionQuery = false; /** delimiter for multiple statements in a single batch */ + @SuppressWarnings("unused") private static final int BATCH_STATEMENT_DELIMITER_TDS_71 = 0x80; private static final int BATCH_STATEMENT_DELIMITER_TDS_72 = 0xFF; final int nBatchStatementDelimiter = BATCH_STATEMENT_DELIMITER_TDS_72; @@ -71,7 +72,7 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS private boolean isExecutedAtLeastOnce = false; /** Reference to cache item for statement handle pooling. Only used to decrement ref count on statement close. */ - private PreparedStatementHandle cachedPreparedStatementHandle; + private PreparedStatementHandle cachedPreparedStatementHandle; /** Hash of user supplied SQL statement used for various cache lookups */ private Sha1HashKey sqlTextCacheKey; @@ -99,30 +100,54 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS /** The prepared statement handle returned by the server */ private int prepStmtHandle = 0; - + /** Statement used for getMetadata(). Declared as a field to facilitate closing the statement. */ private SQLServerStatement internalStmt = null; private void setPreparedStatementHandle(int handle) { this.prepStmtHandle = handle; } - - /** The server handle for this prepared statement. If a value {@literal <} 1 is returned no handle has been created. + + /** + * boolean value for deciding if the driver should use bulk copy API for batch inserts + */ + private boolean useBulkCopyForBatchInsert; + + /** Gets the prepared statement's useBulkCopyForBatchInsert value. * * @return * Per the description. * @throws SQLServerException when an error occurs */ + @SuppressWarnings("unused") + private boolean getUseBulkCopyForBatchInsert() throws SQLServerException { + checkClosed(); + return useBulkCopyForBatchInsert; + } + + /** Sets the prepared statement's useBulkCopyForBatchInsert value. + * + * @param useBulkCopyForBatchInsert + * the boolean value + * @throws SQLServerException when an error occurs + */ + @SuppressWarnings("unused") + private void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert) throws SQLServerException { + checkClosed(); + this.useBulkCopyForBatchInsert = useBulkCopyForBatchInsert; + } + + @Override public int getPreparedStatementHandle() throws SQLServerException { - checkClosed(); + checkClosed(); return prepStmtHandle; } - /** Returns true if this statement has a server handle. - * - * @return - * Per the description. - */ + /** + * Returns true if this statement has a server handle. + * + * @return Per the description. + */ private boolean hasPreparedStatementHandle() { return 0 < prepStmtHandle; } @@ -141,15 +166,17 @@ private boolean resetPrepStmtHandle(boolean discardCurrentCacheItem) { prepStmtHandle = 0; return statementPoolingUsed; } - + /** Flag set to true when statement execution is expected to return the prepared statement handle */ private boolean expectPrepStmtHandle = false; - + /** * Flag set to true when all encryption metadata of inOutParam is retrieved */ private boolean encryptionMetadataIsRetrieved = false; + private String localUserSQL; + // Internal function used in tracing String getClassNameInternal() { return "SQLServerPreparedStatement"; @@ -191,8 +218,8 @@ String getClassNameInternal() { // Parse or fetch SQL metadata from cache. ParsedSQLCacheItem parsedSQL = getCachedParsedSQL(sqlTextCacheKey); - if(null != parsedSQL) { - if(null != connection && connection.isStatementPoolingEnabled()) { + if (null != parsedSQL) { + if (null != connection && connection.isStatementPoolingEnabled()) { isExecutedAtLeastOnce = true; } } @@ -205,6 +232,7 @@ String getClassNameInternal() { bReturnValueSyntax = parsedSQL.bReturnValueSyntax; userSQL = parsedSQL.processedSQL; initParams(parsedSQL.parameterCount); + useBulkCopyForBatchInsert = conn.getUseBulkCopyForBatchInsert(); } /** @@ -224,14 +252,13 @@ private void closePreparedHandle() { else { isExecutedAtLeastOnce = false; final int handleToClose = prepStmtHandle; - // Handle unprepare actions through statement pooling. if (resetPrepStmtHandle(false)) { connection.returnCachedPreparedStatementHandle(cachedPreparedStatementHandle); } - // If no reference to a statement pool cache item is found handle unprepare actions through batching @ connection level. - else if(connection.isPreparedStatementUnprepareBatchingEnabled()) { + // If no reference to a statement pool cache item is found handle unprepare actions through batching @ connection level. + else if (connection.isPreparedStatementUnprepareBatchingEnabled()) { connection.enqueueUnprepareStatementHandle(connection.new PreparedStatementHandle(null, handleToClose, executedSqlDirectly, true)); } else { @@ -286,12 +313,13 @@ final void closeInternal() { // If we have a prepared statement handle, close it. closePreparedHandle(); - + // Close the statement that was used to generate empty statement from getMetadata(). try { if (null != internalStmt) internalStmt.close(); - } catch (SQLServerException e) { + } + catch (SQLServerException e) { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.finer("Ignored error closing internal statement: " + e.getErrorCode() + " " + e.getMessage()); } @@ -303,20 +331,21 @@ final void closeInternal() { batchParamValues = null; } - /** + /** * Intialize the statement parameters. * - * @param nParams - * Number of parameters to Intialize. + * @param nParams + * Number of parameters to Intialize. */ - /* L0 */ final void initParams(int nParams) { + final void initParams(int nParams) { inOutParam = new Parameter[nParams]; for (int i = 0; i < nParams; i++) { inOutParam[i] = new Parameter(Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)); } } - /* L0 */ public final void clearParameters() throws SQLServerException { + @Override + public final void clearParameters() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "clearParameters"); checkClosed(); encryptionMetadataIsRetrieved = false; @@ -337,7 +366,7 @@ private boolean buildPreparedStrings(Parameter[] params, boolean renewDefinition) throws SQLServerException { String newTypeDefinitions = buildParamTypeDefinitions(params, renewDefinition); if (null != preparedTypeDefinitions && newTypeDefinitions.equalsIgnoreCase(preparedTypeDefinitions)) - return false; + return false; preparedTypeDefinitions = newTypeDefinitions; @@ -394,15 +423,7 @@ private String buildParamTypeDefinitions(Parameter[] params, return sb.toString(); } - /** - * Execute a query. - * - * @throws SQLServerException - * when an error occurs - * @throws SQLTimeoutException - * when the query times out - * @return ResultSet - */ + @Override public java.sql.ResultSet executeQuery() throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeQuery"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -419,7 +440,7 @@ public java.sql.ResultSet executeQuery() throws SQLServerException, SQLTimeoutEx * * @throws SQLServerException * @return ResultSet - * @throws SQLTimeoutException + * @throws SQLTimeoutException */ final java.sql.ResultSet executeQueryInternal() throws SQLServerException, SQLTimeoutException { checkClosed(); @@ -427,6 +448,7 @@ final java.sql.ResultSet executeQueryInternal() throws SQLServerException, SQLTi return resultSet; } + @Override public int executeUpdate() throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeUpdate"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -446,8 +468,8 @@ public int executeUpdate() throws SQLServerException, SQLTimeoutException { return (int) updateCount; } + @Override public long executeLargeUpdate() throws SQLServerException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); loggerExternal.entering(getClassNameLogging(), "executeLargeUpdate"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -459,15 +481,7 @@ public long executeLargeUpdate() throws SQLServerException, SQLTimeoutException return updateCount; } - /** - * Execute a query or non query statement. - * - * @throws SQLServerException - * when an error occurs - * @throws SQLTimeoutException - * when the query times out - * @return true if the statement returned a result set - */ + @Override public boolean execute() throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "execute"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -567,7 +581,7 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE throw e; } break; - } + } if (EXECUTE_QUERY == executeMethod && null == resultSet) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_noResultset"), null, true); @@ -576,7 +590,7 @@ else if (EXECUTE_UPDATE == executeMethod && null != resultSet) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_resultsetGeneratedForUpdate"), null, false); } } - + /** Should the execution be retried because the re-used cached handle could not be re-used due to server side state changes? */ private boolean retryBasedOnFailedReuseOfCachedHandle(SQLException e, int attempt, @@ -619,7 +633,7 @@ boolean onRetValue(TDSReader tdsReader) throws SQLServerException { cachedPreparedStatementHandle = connection.registerCachedPreparedStatementHandle( new Sha1HashKey(preparedSQL, preparedTypeDefinitions), prepStmtHandle, executedSqlDirectly); } - + param.skipValue(tdsReader, true); if (getStatementLogger().isLoggable(java.util.logging.Level.FINER)) getStatementLogger().finer(toString() + ": Setting PreparedHandle:" + prepStmtHandle); @@ -655,7 +669,8 @@ void sendParamsByRPC(TDSWriter tdsWriter, private void buildServerCursorPrepExecParams(TDSWriter tdsWriter) throws SQLServerException { if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) - getStatementLogger().fine(toString() + ": calling sp_cursorprepexec: PreparedHandle:" + getPreparedStatementHandle() + ", SQL:" + preparedSQL); + getStatementLogger() + .fine(toString() + ": calling sp_cursorprepexec: PreparedHandle:" + getPreparedStatementHandle() + ", SQL:" + preparedSQL); expectPrepStmtHandle = true; executedSqlDirectly = false; @@ -685,8 +700,8 @@ private void buildServerCursorPrepExecParams(TDSWriter tdsWriter) throws SQLServ // IN // Note: we must strip out SCROLLOPT_PARAMETERIZED_STMT if we don't // actually have any parameters. - tdsWriter.writeRPCInt(null, - getResultSetScrollOpt() & ~((0 == preparedTypeDefinitions.length()) ? TDS.SCROLLOPT_PARAMETERIZED_STMT : 0), false); + tdsWriter.writeRPCInt(null, getResultSetScrollOpt() & ~((0 == preparedTypeDefinitions.length()) ? TDS.SCROLLOPT_PARAMETERIZED_STMT : 0), + false); // IN tdsWriter.writeRPCInt(null, getResultSetCCOpt(), false); @@ -743,13 +758,14 @@ private void buildExecSQLParams(TDSWriter tdsWriter) throws SQLServerException { tdsWriter.writeRPCStringUnicode(preparedSQL); // IN - if (preparedTypeDefinitions.length() > 0) + if (preparedTypeDefinitions.length() > 0) tdsWriter.writeRPCStringUnicode(preparedTypeDefinitions); } private void buildServerCursorExecParams(TDSWriter tdsWriter) throws SQLServerException { if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) - getStatementLogger().fine(toString() + ": calling sp_cursorexecute: PreparedHandle:" + getPreparedStatementHandle() + ", SQL:" + preparedSQL); + getStatementLogger() + .fine(toString() + ": calling sp_cursorexecute: PreparedHandle:" + getPreparedStatementHandle() + ", SQL:" + preparedSQL); expectPrepStmtHandle = false; executedSqlDirectly = false; @@ -1013,7 +1029,8 @@ else if (needsPrepare) return needsPrepare; } - /* L0 */ public final java.sql.ResultSetMetaData getMetaData() throws SQLServerException { + @Override + public final java.sql.ResultSetMetaData getMetaData() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMetaData"); checkClosed(); boolean rsclosed = false; @@ -1045,7 +1062,7 @@ else if (resultSet != null) { * @throws SQLServerException * @return the result set containing the meta data */ - /* L0 */ private ResultSet buildExecuteMetaData() throws SQLServerException { + private ResultSet buildExecuteMetaData() throws SQLServerException { String fmtSQL = userSQL; ResultSet emptyResultSet = null; @@ -1077,7 +1094,7 @@ else if (resultSet != null) { * @exception SQLServerException * The index specified was outside the number of paramters for the statement. */ - /* L0 */ final Parameter setterGetParam(int index) throws SQLServerException { + final Parameter setterGetParam(int index) throws SQLServerException { if (index < 1 || index > inOutParam.length) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_indexOutOfRange")); Object[] msgArgs = {index}; @@ -1142,6 +1159,7 @@ final void setSQLXMLInternal(int parameterIndex, stmtColumnEncriptionSetting, parameterIndex, userSQL, null); } + @Override public final void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1151,6 +1169,7 @@ public final void setAsciiStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } + @Override public final void setAsciiStream(int n, java.io.InputStream x, int length) throws SQLServerException { @@ -1161,6 +1180,7 @@ public final void setAsciiStream(int n, loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } + @Override public final void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { @@ -1171,93 +1191,42 @@ public final void setAsciiStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setAsciiStream"); } - private Parameter getParam(int index) throws SQLServerException { - index--; - if (index < 0 || index >= inOutParam.length) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_indexOutOfRange")); - Object[] msgArgs = {index + 1}; - SQLServerException.makeFromDriverError(connection, this, form.format(msgArgs), "07009", false); - } - return inOutParam[index]; - } - - public final void setBigDecimal(int n, + @Override + public final void setBigDecimal(int paramterIndex, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {n, x}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {paramterIndex, x}); checkClosed(); - setValue(n, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, false); + setValue(paramterIndex, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, false); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ - public final void setBigDecimal(int n, + @Override + public final void setBigDecimal(int paramterIndex, BigDecimal x, int precision, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {n, x, precision, scale}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {paramterIndex, x, precision, scale}); checkClosed(); - setValue(n, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, precision, scale, false); + setValue(paramterIndex, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, precision, scale, false); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ - public final void setBigDecimal(int n, + @Override + public final void setBigDecimal(int paramterIndex, BigDecimal x, int precision, int scale, boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {n, x, precision, scale, forceEncrypt}); + loggerExternal.entering(getClassNameLogging(), "setBigDecimal", new Object[] {paramterIndex, x, precision, scale, forceEncrypt}); checkClosed(); - setValue(n, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, precision, scale, forceEncrypt); + setValue(paramterIndex, JDBCType.DECIMAL, x, JavaType.BIGDECIMAL, precision, scale, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setBigDecimal"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setMoney(int n, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1267,21 +1236,7 @@ public final void setMoney(int n, loggerExternal.exiting(getClassNameLogging(), "setMoney"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setMoney(int n, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -1292,17 +1247,7 @@ public final void setMoney(int n, loggerExternal.exiting(getClassNameLogging(), "setMoney"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setSmallMoney(int n, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1312,21 +1257,7 @@ public final void setSmallMoney(int n, loggerExternal.exiting(getClassNameLogging(), "setSmallMoney"); } - /** - * Sets the designated parameter to the given java.math.BigDecimal value. The driver converts this to an SQL NUMERIC - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setSmallMoney(int n, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -1337,6 +1268,7 @@ public final void setSmallMoney(int n, loggerExternal.exiting(getClassNameLogging(), "setSmallMoney"); } + @Override public final void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1346,6 +1278,7 @@ public final void setBinaryStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBinaryStream(int n, java.io.InputStream x, int length) throws SQLServerException { @@ -1356,6 +1289,7 @@ public final void setBinaryStream(int n, loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { @@ -1366,6 +1300,7 @@ public final void setBinaryStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setBinaryStream"); } + @Override public final void setBoolean(int n, boolean x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1375,21 +1310,7 @@ public final void setBoolean(int n, loggerExternal.exiting(getClassNameLogging(), "setBoolean"); } - /** - * Sets the designated parameter to the given Java boolean value. The driver converts this to an SQL BIT or - * BOOLEAN value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setBoolean(int n, boolean x, boolean forceEncrypt) throws SQLServerException { @@ -1400,6 +1321,7 @@ public final void setBoolean(int n, loggerExternal.exiting(getClassNameLogging(), "setBoolean"); } + @Override public final void setByte(int n, byte x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1409,21 +1331,7 @@ public final void setByte(int n, loggerExternal.exiting(getClassNameLogging(), "setByte"); } - /** - * Sets the designated parameter to the given Java byte value. The driver converts this to an SQL TINYINT value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setByte(int n, byte x, boolean forceEncrypt) throws SQLServerException { @@ -1434,6 +1342,7 @@ public final void setByte(int n, loggerExternal.exiting(getClassNameLogging(), "setByte"); } + @Override public final void setBytes(int n, byte x[]) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1443,22 +1352,7 @@ public final void setBytes(int n, loggerExternal.exiting(getClassNameLogging(), "setBytes"); } - /** - * Sets the designated parameter to the given Java array of bytes. The driver converts this to an SQL VARBINARY or - * LONGVARBINARY (depending on the argument's size relative to the driver's limits on VARBINARY values) when it sends it - * to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setBytes(int n, byte x[], boolean forceEncrypt) throws SQLServerException { @@ -1469,16 +1363,7 @@ public final void setBytes(int n, loggerExternal.exiting(getClassNameLogging(), "setBytes"); } - /** - * Sets the designated parameter to the given String. The driver converts this to an SQL GUID - * - * @param index - * the first parameter is 1, the second is 2, ... - * @param guid - * string representation of the uniqueIdentifier value - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setUniqueIdentifier(int index, String guid) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1488,20 +1373,7 @@ public final void setUniqueIdentifier(int index, loggerExternal.exiting(getClassNameLogging(), "setUniqueIdentifier"); } - /** - * Sets the designated parameter to the given String. The driver converts this to an SQL GUID - * - * @param index - * the first parameter is 1, the second is 2, ... - * @param guid - * string representation of the uniqueIdentifier value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setUniqueIdentifier(int index, String guid, boolean forceEncrypt) throws SQLServerException { @@ -1512,6 +1384,7 @@ public final void setUniqueIdentifier(int index, loggerExternal.exiting(getClassNameLogging(), "setUniqueIdentifier"); } + @Override public final void setDouble(int n, double x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1521,21 +1394,7 @@ public final void setDouble(int n, loggerExternal.exiting(getClassNameLogging(), "setDouble"); } - /** - * Sets the designated parameter to the given Java double value. The driver converts this to an SQL DOUBLE value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setDouble(int n, double x, boolean forceEncrypt) throws SQLServerException { @@ -1546,6 +1405,7 @@ public final void setDouble(int n, loggerExternal.exiting(getClassNameLogging(), "setDouble"); } + @Override public final void setFloat(int n, float x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1555,21 +1415,7 @@ public final void setFloat(int n, loggerExternal.exiting(getClassNameLogging(), "setFloat"); } - /** - * Sets the designated parameter to the given Java float value. The driver converts this to an SQL REAL value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setFloat(int n, float x, boolean forceEncrypt) throws SQLServerException { @@ -1579,7 +1425,8 @@ public final void setFloat(int n, setValue(n, JDBCType.REAL, x, JavaType.FLOAT, forceEncrypt); loggerExternal.exiting(getClassNameLogging(), "setFloat"); } - + + @Override public final void setGeometry(int n, Geometry x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1588,7 +1435,8 @@ public final void setGeometry(int n, setValue(n, JDBCType.GEOMETRY, x, JavaType.STRING, false); loggerExternal.exiting(getClassNameLogging(), "setGeometry"); } - + + @Override public final void setGeography(int n, Geography x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1598,6 +1446,7 @@ public final void setGeography(int n, loggerExternal.exiting(getClassNameLogging(), "setGeography"); } + @Override public final void setInt(int n, int value) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1607,21 +1456,7 @@ public final void setInt(int n, loggerExternal.exiting(getClassNameLogging(), "setInt"); } - /** - * Sets the designated parameter to the given Java int value. The driver converts this to an SQL INTEGER value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param value - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setInt(int n, int value, boolean forceEncrypt) throws SQLServerException { @@ -1632,6 +1467,7 @@ public final void setInt(int n, loggerExternal.exiting(getClassNameLogging(), "setInt"); } + @Override public final void setLong(int n, long x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1641,21 +1477,7 @@ public final void setLong(int n, loggerExternal.exiting(getClassNameLogging(), "setLong"); } - /** - * Sets the designated parameter to the given Java long value. The driver converts this to an SQL BIGINT value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setLong(int n, long x, boolean forceEncrypt) throws SQLServerException { @@ -1666,6 +1488,7 @@ public final void setLong(int n, loggerExternal.exiting(getClassNameLogging(), "setLong"); } + @Override public final void setNull(int index, int jdbcType) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1714,6 +1537,7 @@ final void setObjectNoType(int index, } } + @Override public final void setObject(int index, Object obj) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1723,6 +1547,7 @@ public final void setObject(int index, loggerExternal.exiting(getClassNameLogging(), "setObject"); } + @Override public final void setObject(int n, Object obj, int jdbcType) throws SQLServerException { @@ -1736,6 +1561,7 @@ public final void setObject(int n, loggerExternal.exiting(getClassNameLogging(), "setObject"); } + @Override public final void setObject(int parameterIndex, Object x, int targetSqlType, @@ -1758,34 +1584,7 @@ public final void setObject(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setObject"); } - /** - *

- * Sets the value of the designated parameter with the given object. - * - *

- * The given Java object will be converted to the given targetSqlType before being sent to the database. - * - * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method - * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing - * Ref, Blob, Clob, NClob, Struct, java.net.URL, or - * Array, the driver should pass it to the database as a value of the corresponding SQL type. - * - *

- * Note that this method may be used to pass database-specific abstract data types. - * - * @param parameterIndex - * the first parameter is 1, the second is 2, ... - * @param x - * the object containing the input parameter value - * @param targetSqlType - * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. - * @param precision - * the precision of the column - * @param scale - * scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setObject(int parameterIndex, Object x, int targetSqlType, @@ -1800,46 +1599,15 @@ public final void setObject(int parameterIndex, // InputStream and Reader, this is the length of the data in the stream or reader. // For all other types, this value will be ignored. - setObject(setterGetParam(parameterIndex), x, JavaType.of(x), - JDBCType.of(targetSqlType), (java.sql.Types.NUMERIC == targetSqlType || java.sql.Types.DECIMAL == targetSqlType - || InputStream.class.isInstance(x) || Reader.class.isInstance(x)) ? scale : null, + setObject( + setterGetParam(parameterIndex), x, JavaType.of(x), JDBCType.of(targetSqlType), (java.sql.Types.NUMERIC == targetSqlType + || java.sql.Types.DECIMAL == targetSqlType || InputStream.class.isInstance(x) || Reader.class.isInstance(x)) ? scale : null, precision, false, parameterIndex, null); loggerExternal.exiting(getClassNameLogging(), "setObject"); } - /** - *

- * Sets the value of the designated parameter with the given object. - * - *

- * The given Java object will be converted to the given targetSqlType before being sent to the database. - * - * If the object has a custom mapping (is of a class implementing the interface SQLData), the JDBC driver should call the method - * SQLData.writeSQL to write it to the SQL data stream. If, on the other hand, the object is of a class implementing - * Ref, Blob, Clob, NClob, Struct, java.net.URL, or - * Array, the driver should pass it to the database as a value of the corresponding SQL type. - * - *

- * Note that this method may be used to pass database-specific abstract data types. - * - * @param parameterIndex - * the first parameter is 1, the second is 2, ... - * @param x - * the object containing the input parameter value - * @param targetSqlType - * the SQL type (as defined in java.sql.Types) to be sent to the database. The scale argument may further qualify this type. - * @param precision - * the precision of the column - * @param scale - * scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setObject(int parameterIndex, Object x, int targetSqlType, @@ -1856,9 +1624,9 @@ public final void setObject(int parameterIndex, // InputStream and Reader, this is the length of the data in the stream or reader. // For all other types, this value will be ignored. - setObject(setterGetParam(parameterIndex), x, JavaType.of(x), - JDBCType.of(targetSqlType), (java.sql.Types.NUMERIC == targetSqlType || java.sql.Types.DECIMAL == targetSqlType - || InputStream.class.isInstance(x) || Reader.class.isInstance(x)) ? scale : null, + setObject( + setterGetParam(parameterIndex), x, JavaType.of(x), JDBCType.of(targetSqlType), (java.sql.Types.NUMERIC == targetSqlType + || java.sql.Types.DECIMAL == targetSqlType || InputStream.class.isInstance(x) || Reader.class.isInstance(x)) ? scale : null, precision, forceEncrypt, parameterIndex, null); loggerExternal.exiting(getClassNameLogging(), "setObject"); @@ -1924,6 +1692,41 @@ final void setObject(Parameter param, } } + @Override + public final void setObject(int index, + Object obj, + SQLType jdbcType) throws SQLServerException { + setObject(index, obj, jdbcType.getVendorTypeNumber()); + } + + @Override + public final void setObject(int parameterIndex, + Object x, + SQLType targetSqlType, + int scaleOrLength) throws SQLServerException { + setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), scaleOrLength); + } + + @Override + public final void setObject(int parameterIndex, + Object x, + SQLType targetSqlType, + Integer precision, + Integer scale) throws SQLServerException { + setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), precision, scale); + } + + @Override + public final void setObject(int parameterIndex, + Object x, + SQLType targetSqlType, + Integer precision, + Integer scale, + boolean forceEncrypt) throws SQLServerException { + setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), precision, scale, forceEncrypt); + } + + @Override public final void setShort(int index, short x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1933,21 +1736,7 @@ public final void setShort(int index, loggerExternal.exiting(getClassNameLogging(), "setShort"); } - /** - * Sets the designated parameter to the given Java short value. The driver converts this to an SQL SMALLINT value when - * it sends it to the database. - * - * @param index - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setShort(int index, short x, boolean forceEncrypt) throws SQLServerException { @@ -1958,6 +1747,7 @@ public final void setShort(int index, loggerExternal.exiting(getClassNameLogging(), "setShort"); } + @Override public final void setString(int index, String str) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1967,22 +1757,7 @@ public final void setString(int index, loggerExternal.exiting(getClassNameLogging(), "setString"); } - /** - * Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or - * LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends - * it to the database. - * - * @param index - * the first parameter is 1, the second is 2, ... - * @param str - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setString(int index, String str, boolean forceEncrypt) throws SQLServerException { @@ -1993,6 +1768,7 @@ public final void setString(int index, loggerExternal.exiting(getClassNameLogging(), "setString"); } + @Override public final void setNString(int parameterIndex, String value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2002,25 +1778,10 @@ public final void setNString(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNString"); } - /** - * Sets the designated parameter to the given String object. The driver converts this to a SQL NCHAR or - * NVARCHAR or LONGNVARCHAR value (depending on the argument's size relative to the driver's limits on - * NVARCHAR values) when it sends it to the database. - * - * @param parameterIndex - * of the first parameter is 1, the second is 2, ... - * @param value - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public final void setNString(int parameterIndex, String value, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setNString", new Object[] {parameterIndex, value, forceEncrypt}); checkClosed(); @@ -2028,6 +1789,7 @@ public final void setNString(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNString"); } + @Override public final void setTime(int n, java.sql.Time x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2037,18 +1799,7 @@ public final void setTime(int n, loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTime(int n, java.sql.Time x, int scale) throws SQLServerException { @@ -2059,22 +1810,7 @@ public final void setTime(int n, loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTime(int n, java.sql.Time x, int scale, @@ -2086,6 +1822,7 @@ public final void setTime(int n, loggerExternal.exiting(getClassNameLogging(), "setTime"); } + @Override public final void setTimestamp(int n, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2095,18 +1832,7 @@ public final void setTimestamp(int n, loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTimestamp(int n, java.sql.Timestamp x, int scale) throws SQLServerException { @@ -2117,22 +1843,7 @@ public final void setTimestamp(int n, loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTimestamp(int n, java.sql.Timestamp x, int scale, @@ -2144,18 +1855,9 @@ public final void setTimestamp(int n, loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given microsoft.sql.DatetimeOffset value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @throws SQLException - * if an error occurs. - */ + @Override public final void setDateTimeOffset(int n, - microsoft.sql.DateTimeOffset x) throws SQLException { + microsoft.sql.DateTimeOffset x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {n, x}); checkClosed(); @@ -2163,21 +1865,10 @@ public final void setDateTimeOffset(int n, loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } - /** - * Sets the designated parameter to the given microsoft.sql.DatetimeOffset value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @throws SQLException - * when an error occurs - */ + @Override public final void setDateTimeOffset(int n, microsoft.sql.DateTimeOffset x, - int scale) throws SQLException { + int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {n, x, scale}); checkClosed(); @@ -2185,26 +1876,11 @@ public final void setDateTimeOffset(int n, loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } - /** - * Sets the designated parameter to the given microsoft.sql.DatetimeOffset value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public final void setDateTimeOffset(int n, microsoft.sql.DateTimeOffset x, int scale, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setDateTimeOffset", new Object[] {n, x, scale, forceEncrypt}); checkClosed(); @@ -2212,6 +1888,7 @@ public final void setDateTimeOffset(int n, loggerExternal.exiting(getClassNameLogging(), "setDateTimeOffset"); } + @Override public final void setDate(int n, java.sql.Date x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2221,16 +1898,7 @@ public final void setDate(int n, loggerExternal.exiting(getClassNameLogging(), "setDate"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setDateTime(int n, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2240,20 +1908,7 @@ public final void setDateTime(int n, loggerExternal.exiting(getClassNameLogging(), "setDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setDateTime(int n, java.sql.Timestamp x, boolean forceEncrypt) throws SQLServerException { @@ -2264,16 +1919,7 @@ public final void setDateTime(int n, loggerExternal.exiting(getClassNameLogging(), "setDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setSmallDateTime(int n, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2283,20 +1929,7 @@ public final void setSmallDateTime(int n, loggerExternal.exiting(getClassNameLogging(), "setSmallDateTime"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setSmallDateTime(int n, java.sql.Timestamp x, boolean forceEncrypt) throws SQLServerException { @@ -2307,18 +1940,7 @@ public final void setSmallDateTime(int n, loggerExternal.exiting(getClassNameLogging(), "setSmallDateTime"); } - /** - * Populates a table valued parameter with a data table - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param tvpName - * the name of the table valued parameter - * @param tvpDataTable - * the source datatable object - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setStructured(int n, String tvpName, SQLServerDataTable tvpDataTable) throws SQLServerException { @@ -2330,18 +1952,7 @@ public final void setStructured(int n, loggerExternal.exiting(getClassNameLogging(), "setStructured"); } - /** - * Populates a table valued parameter with a data table - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param tvpName - * the name of the table valued parameter - * @param tvpResultSet - * the source resultset object - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setStructured(int n, String tvpName, ResultSet tvpResultSet) throws SQLServerException { @@ -2353,18 +1964,7 @@ public final void setStructured(int n, loggerExternal.exiting(getClassNameLogging(), "setStructured"); } - /** - * Populates a table valued parameter with a data table - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param tvpName - * the name of the table valued parameter - * @param tvpBulkRecord - * an ISQLServerDataRecord object - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setStructured(int n, String tvpName, ISQLServerDataRecord tvpBulkRecord) throws SQLServerException { @@ -2380,16 +1980,16 @@ String getTVPNameIfNull(int n, String tvpName) throws SQLServerException { if ((null == tvpName) || (0 == tvpName.length())) { // Check if the CallableStatement/PreparedStatement is a stored procedure call - if(null != this.procedureName) { + if (null != this.procedureName) { SQLServerParameterMetaData pmd = (SQLServerParameterMetaData) this.getParameterMetaData(); pmd.isTVP = true; - + if (!pmd.procedureIsFound) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_StoredProcedureNotFound")); Object[] msgArgs = {this.procedureName}; SQLServerException.makeFromDriverError(connection, pmd, form.format(msgArgs), null, false); } - + try { String tvpNameWithoutSchema = pmd.getParameterTypeName(n); String tvpSchema = pmd.getTVPSchemaFromStoredProcedure(n); @@ -2410,12 +2010,14 @@ String getTVPNameIfNull(int n, } @Deprecated + @Override public final void setUnicodeStream(int n, java.io.InputStream x, int length) throws SQLException { - NotImplemented(); + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final void addBatch() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "addBatch"); checkClosed(); @@ -2432,13 +2034,15 @@ public final void addBatch() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "addBatch"); } - /* L0 */ public final void clearBatch() throws SQLServerException { + @Override + public final void clearBatch() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "clearBatch"); checkClosed(); batchParamValues = null; loggerExternal.exiting(getClassNameLogging(), "clearBatch"); } + @Override public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeBatch"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -2446,8 +2050,97 @@ public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQL } checkClosed(); discardLastExecutionResults(); - + int updateCounts[]; + + localUserSQL = userSQL; + + try { + if (isInsert(localUserSQL) && connection.isAzureDW() && (this.useBulkCopyForBatchInsert)) { + // From the JDBC spec, section 9.1.4 - Making Batch Updates: + // The CallableStatement.executeBatch method (inherited from PreparedStatement) will + // throw a BatchUpdateException if the stored procedure returns anything other than an + // update count or takes OUT or INOUT parameters. + // + // Non-update count results (e.g. ResultSets) are treated as individual batch errors + // when they are encountered in the response. + // + // OUT and INOUT parameter checking is done here, before executing the batch. If any + // OUT or INOUT are present, the entire batch fails. + for (Parameter[] paramValues : batchParamValues) { + for (Parameter paramValue : paramValues) { + if (paramValue.isOutput()) { + throw new BatchUpdateException(SQLServerException.getErrString("R_outParamsNotPermittedinBatch"), null, 0, null); + } + } + } + + if (batchParamValues == null) { + updateCounts = new int[0]; + loggerExternal.exiting(getClassNameLogging(), "executeBatch", updateCounts); + return updateCounts; + } + + String tableName = parseUserSQLForTableNameDW(false, false, false, false); + ArrayList columnList = parseUserSQLForColumnListDW(); + ArrayList valueList = parseUserSQLForValueListDW(false); + + String destinationTableName = tableName; + SQLServerStatement stmt = (SQLServerStatement) connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, + connection.getHoldability(), stmtColumnEncriptionSetting); + + // Get destination metadata + try (SQLServerResultSet rs = stmt + .executeQueryInternal("sp_executesql N'SET FMTONLY ON SELECT * FROM " + destinationTableName + " '");) { + + SQLServerBulkBatchInsertRecord batchRecord = new SQLServerBulkBatchInsertRecord(batchParamValues, columnList, valueList, null); + + for (int i = 1; i <= rs.getColumnCount(); i++) { + Column c = rs.getColumn(i); + CryptoMetadata cryptoMetadata = c.getCryptoMetadata(); + int jdbctype; + TypeInfo ti = c.getTypeInfo(); + if (null != cryptoMetadata) { + jdbctype = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType().getIntValue(); + } + else { + jdbctype = ti.getSSType().getJDBCType().getIntValue(); + } + batchRecord.addColumnMetadata(i, c.getColumnName(), jdbctype, ti.getPrecision(), ti.getScale()); + } + + SQLServerBulkCopy bcOperation = new SQLServerBulkCopy(connection); + bcOperation.setDestinationTableName(tableName); + bcOperation.setStmtColumnEncriptionSetting(this.getStmtColumnEncriptionSetting()); + bcOperation.setDestinationTableMetadata(rs); + bcOperation.writeToServer((ISQLServerBulkRecord) batchRecord); + bcOperation.close(); + updateCounts = new int[batchParamValues.size()]; + for (int i = 0; i < batchParamValues.size(); ++i) { + updateCounts[i] = 1; + } + + batchParamValues = null; + loggerExternal.exiting(getClassNameLogging(), "executeBatch", updateCounts); + return updateCounts; + } + finally { + if (null != stmt) + stmt.close(); + } + } + } + catch (SQLException e) { + // throw a BatchUpdateException with the given error message, and return null for the updateCounts. + throw new BatchUpdateException(e.getMessage(), null, 0, null); + } + catch (IllegalArgumentException e) { + // If we fail with IllegalArgumentException, fall back to the original batch insert logic. + if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { + getStatementLogger().fine("Parsing user's Batch Insert SQL Query failed: " + e.toString()); + getStatementLogger().fine("Falling back to the original implementation for Batch Insert."); + } + } if (batchParamValues == null) updateCounts = new int[0]; @@ -2494,9 +2187,8 @@ public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQL return updateCounts; } + @Override public long[] executeLargeBatch() throws SQLServerException, BatchUpdateException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); - loggerExternal.entering(getClassNameLogging(), "executeLargeBatch"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -2505,6 +2197,95 @@ public long[] executeLargeBatch() throws SQLServerException, BatchUpdateExceptio discardLastExecutionResults(); long updateCounts[]; + + localUserSQL = userSQL; + + try { + if (isInsert(localUserSQL) && connection.isAzureDW() && (this.useBulkCopyForBatchInsert)) { + // From the JDBC spec, section 9.1.4 - Making Batch Updates: + // The CallableStatement.executeBatch method (inherited from PreparedStatement) will + // throw a BatchUpdateException if the stored procedure returns anything other than an + // update count or takes OUT or INOUT parameters. + // + // Non-update count results (e.g. ResultSets) are treated as individual batch errors + // when they are encountered in the response. + // + // OUT and INOUT parameter checking is done here, before executing the batch. If any + // OUT or INOUT are present, the entire batch fails. + for (Parameter[] paramValues : batchParamValues) { + for (Parameter paramValue : paramValues) { + if (paramValue.isOutput()) { + throw new BatchUpdateException(SQLServerException.getErrString("R_outParamsNotPermittedinBatch"), null, 0, null); + } + } + } + + if (batchParamValues == null) { + updateCounts = new long[0]; + loggerExternal.exiting(getClassNameLogging(), "executeLargeBatch", updateCounts); + return updateCounts; + } + + String tableName = parseUserSQLForTableNameDW(false, false, false, false); + ArrayList columnList = parseUserSQLForColumnListDW(); + ArrayList valueList = parseUserSQLForValueListDW(false); + + String destinationTableName = tableName; + SQLServerStatement stmt = (SQLServerStatement) connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, + connection.getHoldability(), stmtColumnEncriptionSetting); + + // Get destination metadata + try (SQLServerResultSet rs = stmt + .executeQueryInternal("sp_executesql N'SET FMTONLY ON SELECT * FROM " + destinationTableName + " '");) { + + SQLServerBulkBatchInsertRecord batchRecord = new SQLServerBulkBatchInsertRecord(batchParamValues, columnList, valueList, null); + + for (int i = 1; i <= rs.getColumnCount(); i++) { + Column c = rs.getColumn(i); + CryptoMetadata cryptoMetadata = c.getCryptoMetadata(); + int jdbctype; + TypeInfo ti = c.getTypeInfo(); + if (null != cryptoMetadata) { + jdbctype = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType().getIntValue(); + } + else { + jdbctype = ti.getSSType().getJDBCType().getIntValue(); + } + batchRecord.addColumnMetadata(i, c.getColumnName(), jdbctype, ti.getPrecision(), ti.getScale()); + } + + SQLServerBulkCopy bcOperation = new SQLServerBulkCopy(connection); + bcOperation.setDestinationTableName(tableName); + bcOperation.setStmtColumnEncriptionSetting(this.getStmtColumnEncriptionSetting()); + bcOperation.setDestinationTableMetadata(rs); + bcOperation.writeToServer((ISQLServerBulkRecord) batchRecord); + bcOperation.close(); + updateCounts = new long[batchParamValues.size()]; + for (int i = 0; i < batchParamValues.size(); ++i) { + updateCounts[i] = 1; + } + + batchParamValues = null; + loggerExternal.exiting(getClassNameLogging(), "executeLargeBatch", updateCounts); + return updateCounts; + } + finally { + if (null != stmt) + stmt.close(); + } + } + } + catch (SQLException e) { + // throw a BatchUpdateException with the given error message, and return null for the updateCounts. + throw new BatchUpdateException(e.getMessage(), null, 0, null); + } + catch (IllegalArgumentException e) { + // If we fail with IllegalArgumentException, fall back to the original batch insert logic. + if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { + getStatementLogger().fine("Parsing user's Batch Insert SQL Query failed: " + e.toString()); + getStatementLogger().fine("Falling back to the original implementation for Batch Insert."); + } + } if (batchParamValues == null) updateCounts = new long[0]; @@ -2548,6 +2329,315 @@ public long[] executeLargeBatch() throws SQLServerException, BatchUpdateExceptio loggerExternal.exiting(getClassNameLogging(), "executeLargeBatch", updateCounts); return updateCounts; } + + + private String parseUserSQLForTableNameDW(boolean hasInsertBeenFound, boolean hasIntoBeenFound, boolean hasTableBeenFound, + boolean isExpectingTableName) { + // As far as finding the table name goes, There are two cases: + // Insert into and Insert + // And there could be in-line comments (with /* and */) in between. + // This method assumes the localUserSQL string starts with "insert". + localUserSQL = localUserSQL.trim(); + if (checkAndRemoveComments()) { + return parseUserSQLForTableNameDW(hasInsertBeenFound, hasIntoBeenFound, hasTableBeenFound, isExpectingTableName); + } + + StringBuilder sb = new StringBuilder(); + + // If table has been found and the next character is not a . at this point, we've finished parsing the table name. + // This if statement is needed to handle the case where the user has something like: + // [dbo] . /* random comment */ [tableName] + if (hasTableBeenFound && !isExpectingTableName) { + if (localUserSQL.substring(0, 1).equalsIgnoreCase(".")) { + sb.append("."); + localUserSQL = localUserSQL.substring(1); + return sb.toString() + parseUserSQLForTableNameDW(true, true, true, true); + } else { + return ""; + } + } + + if (localUserSQL.substring(0, 6).equalsIgnoreCase("insert") && !hasInsertBeenFound) { + localUserSQL = localUserSQL.substring(6); + return parseUserSQLForTableNameDW(true, hasIntoBeenFound, hasTableBeenFound, isExpectingTableName); + } + + if (localUserSQL.substring(0, 4).equalsIgnoreCase("into") && !hasIntoBeenFound) { + // is it really "into"? + // if the "into" is followed by a blank space or /*, then yes. + if (Character.isWhitespace(localUserSQL.charAt(4)) || + (localUserSQL.charAt(4) == '/' && localUserSQL.charAt(5) == '*')) { + localUserSQL = localUserSQL.substring(4); + return parseUserSQLForTableNameDW(hasInsertBeenFound, true, hasTableBeenFound, isExpectingTableName); + } + + // otherwise, we found the token that either contains the databasename.tablename or tablename. + // Recursively handle this, but into has been found. (or rather, it's absent in the query - the "into" keyword is optional) + return parseUserSQLForTableNameDW(hasInsertBeenFound, true, hasTableBeenFound, isExpectingTableName); + } + + // At this point, the next token has to be the table name. + // It could be encapsulated in [], "", or have a database name preceding the table name. + // If it's encapsulated in [] or "", we need be more careful with parsing as anything could go into []/"". + // For ] or ", they can be escaped by ]] or "", watch out for this too. + if (localUserSQL.substring(0, 1).equalsIgnoreCase("[")) { + int tempint = localUserSQL.indexOf("]", 1); + + // keep checking if it's escaped + while (localUserSQL.charAt(tempint + 1) == ']') { + tempint = localUserSQL.indexOf("]", tempint + 2); + } + + // we've found a ] that is actually trying to close the square bracket. + // return tablename + potentially more that's part of the table name + sb.append(localUserSQL.substring(0, tempint + 1)); + localUserSQL = localUserSQL.substring(tempint + 1); + return sb.toString() + parseUserSQLForTableNameDW(true, true, true, false); + } + + // do the same for "" + if (localUserSQL.substring(0, 1).equalsIgnoreCase("\"")) { + int tempint = localUserSQL.indexOf("\"", 1); + + // keep checking if it's escaped + while (localUserSQL.charAt(tempint + 1) == '\"') { + tempint = localUserSQL.indexOf("\"", tempint + 2); + } + + // we've found a " that is actually trying to close the quote. + // return tablename + potentially more that's part of the table name + sb.append(localUserSQL.substring(0, tempint + 1)); + localUserSQL = localUserSQL.substring(tempint + 1); + return sb.toString() + parseUserSQLForTableNameDW(true, true, true, false); + } + + // At this point, the next chunk of string is the table name, without starting with [ or ". + while (localUserSQL.length() > 0) { + // Keep going until the end of the table name is signalled - either a ., whitespace, or comment is encountered + if (localUserSQL.charAt(0) == '.' || Character.isWhitespace(localUserSQL.charAt(0)) || checkAndRemoveComments()) { + return sb.toString() + parseUserSQLForTableNameDW(true, true, true, false); + } else { + sb.append(localUserSQL.charAt(0)); + localUserSQL = localUserSQL.substring(1); + } + } + + // It shouldn't come here. If we did, something is wrong. + throw new IllegalArgumentException("localUserSQL"); + } + + private ArrayList parseUserSQLForColumnListDW() { + localUserSQL = localUserSQL.trim(); + + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForColumnListDW(); + } + + //check if optional column list was provided + // Columns can have the form of c1, [c1] or "c1". It can escape ] or " by ]] or "". + if (localUserSQL.substring(0, 1).equalsIgnoreCase("(")) { + localUserSQL = localUserSQL.substring(1); + return parseUserSQLForColumnListDWHelper(new ArrayList()); + } + return null; + } + + private ArrayList parseUserSQLForColumnListDWHelper(ArrayList listOfColumns) { + localUserSQL = localUserSQL.trim(); + + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForColumnListDWHelper(listOfColumns); + } + + if (localUserSQL.charAt(0) == ')') { + localUserSQL = localUserSQL.substring(1); + return listOfColumns; + } + + if (localUserSQL.charAt(0) == ',') { + localUserSQL = localUserSQL.substring(1); + return parseUserSQLForColumnListDWHelper(listOfColumns); + } + + if (localUserSQL.charAt(0) == '[') { + int tempint = localUserSQL.indexOf("]", 1); + + // keep checking if it's escaped + while (localUserSQL.charAt(tempint + 1) == ']') { + localUserSQL = localUserSQL.substring(0, tempint) + localUserSQL.substring(tempint + 1); + tempint = localUserSQL.indexOf("]", tempint + 1); + } + + // we've found a ] that is actually trying to close the square bracket. + String tempstr = localUserSQL.substring(1, tempint); + localUserSQL = localUserSQL.substring(tempint + 1); + listOfColumns.add(tempstr); + return parseUserSQLForColumnListDWHelper(listOfColumns); + } + + if (localUserSQL.charAt(0) == '\"') { + int tempint = localUserSQL.indexOf("\"", 1); + + // keep checking if it's escaped + while (localUserSQL.charAt(tempint + 1) == '\"') { + localUserSQL = localUserSQL.substring(0, tempint) + localUserSQL.substring(tempint + 1); + tempint = localUserSQL.indexOf("\"", tempint + 1); + } + + // we've found a " that is actually trying to close the quote. + String tempstr = localUserSQL.substring(1, tempint); + localUserSQL = localUserSQL.substring(tempint + 1); + listOfColumns.add(tempstr); + return parseUserSQLForColumnListDWHelper(listOfColumns); + } + + // At this point, the next chunk of string is the column name, without starting with [ or ". + StringBuilder sb = new StringBuilder(); + while (localUserSQL.length() > 0) { + if (localUserSQL.charAt(0) == ',') { + localUserSQL = localUserSQL.substring(1); + listOfColumns.add(sb.toString()); + return parseUserSQLForColumnListDWHelper(listOfColumns); + } else if (localUserSQL.charAt(0) == ')'){ + localUserSQL = localUserSQL.substring(1); + listOfColumns.add(sb.toString()); + return listOfColumns; + } else if (checkAndRemoveComments()) { + localUserSQL = localUserSQL.trim(); + } else { + sb.append(localUserSQL.charAt(0)); + localUserSQL = localUserSQL.substring(1); + localUserSQL = localUserSQL.trim(); + } + } + + // It shouldn't come here. If we did, something is wrong. + throw new IllegalArgumentException("localUserSQL"); + } + + + private ArrayList parseUserSQLForValueListDW(boolean hasValuesBeenFound) { + localUserSQL = localUserSQL.trim(); + + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForValueListDW(hasValuesBeenFound); + } + + if (!hasValuesBeenFound) { + // look for keyword "VALUES" + if (localUserSQL.substring(0, 6).equalsIgnoreCase("VALUES")) { + localUserSQL = localUserSQL.substring(6); + + localUserSQL = localUserSQL.trim(); + + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForValueListDW(true); + } + + if (localUserSQL.substring(0, 1).equalsIgnoreCase("(")) { + localUserSQL = localUserSQL.substring(1); + return parseUserSQLForValueListDWHelper(new ArrayList()); + } + } + } else { + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForValueListDW(hasValuesBeenFound); + } + + if (localUserSQL.substring(0, 1).equalsIgnoreCase("(")) { + localUserSQL = localUserSQL.substring(1); + return parseUserSQLForValueListDWHelper(new ArrayList()); + } + } + + // shouldn't come here, as the list of values is mandatory. + throw new IllegalArgumentException("localUserSQL"); + } + + private ArrayList parseUserSQLForValueListDWHelper(ArrayList listOfValues) { + localUserSQL = localUserSQL.trim(); + + // ignore all comments + if (checkAndRemoveComments()) { + return parseUserSQLForValueListDWHelper(listOfValues); + } + + if (localUserSQL.charAt(0) == ')') { + localUserSQL = localUserSQL.substring(1); + return listOfValues; + } + + if (localUserSQL.charAt(0) == ',') { + localUserSQL = localUserSQL.substring(1); + return parseUserSQLForValueListDWHelper(listOfValues); + } + + if (localUserSQL.charAt(0) == '\'') { + int tempint = localUserSQL.indexOf("\'", 1); + + // keep checking if it's escaped + while (localUserSQL.charAt(tempint + 1) == '\'') { + localUserSQL = localUserSQL.substring(0, tempint) + localUserSQL.substring(tempint + 1); + tempint = localUserSQL.indexOf("\'", tempint + 1); + } + + // we've found a ' that is actually trying to close the quote. + // Include 's around the string as well, so we can distinguish '?' and ? later on. + String tempstr = localUserSQL.substring(0, tempint + 1); + localUserSQL = localUserSQL.substring(tempint + 1); + listOfValues.add(tempstr); + return parseUserSQLForValueListDWHelper(listOfValues); + } + + // At this point, the next chunk of string is the value, without starting with ' (most likely a ?). + StringBuilder sb = new StringBuilder(); + while (localUserSQL.length() > 0) { + if (localUserSQL.charAt(0) == ',' || localUserSQL.charAt(0) == ')') { + if (localUserSQL.charAt(0) == ',') { + localUserSQL = localUserSQL.substring(1); + listOfValues.add(sb.toString()); + return parseUserSQLForValueListDWHelper(listOfValues); + } else { + localUserSQL = localUserSQL.substring(1); + listOfValues.add(sb.toString()); + return listOfValues; + } + } else if (checkAndRemoveComments()) { + localUserSQL = localUserSQL.trim(); + } else { + sb.append(localUserSQL.charAt(0)); + localUserSQL = localUserSQL.substring(1); + localUserSQL = localUserSQL.trim(); + } + } + + // It shouldn't come here. If we did, something is wrong. + throw new IllegalArgumentException("localUserSQL"); + } + + private boolean checkAndRemoveComments() { + if (null == localUserSQL || localUserSQL.length() < 2) { + return false; + } + + if (localUserSQL.substring(0, 2).equalsIgnoreCase("/*")) { + int temp = localUserSQL.indexOf("*/") + 2; + localUserSQL = localUserSQL.substring(temp); + return true; + } + + if (localUserSQL.substring(0, 2).equalsIgnoreCase("--")) { + int temp = localUserSQL.indexOf("\n") + 2; + localUserSQL = localUserSQL.substring(temp); + return true; + } + return false; + } private final class PrepStmtBatchExecCmd extends TDSCommand { private final SQLServerPreparedStatement stmt; @@ -2555,7 +2645,7 @@ private final class PrepStmtBatchExecCmd extends TDSCommand { long updateCounts[]; PrepStmtBatchExecCmd(SQLServerPreparedStatement stmt) { - super(stmt.toString() + " executeBatch", queryTimeout, cancelQueryTimeoutSeconds); + super(stmt.toString() + " executeBatch", queryTimeout, cancelQueryTimeoutSeconds); this.stmt = stmt; } @@ -2596,23 +2686,18 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th // Create the parameter array that we'll use for all the items in this batch. Parameter[] batchParam = new Parameter[inOutParam.length]; - -/* - TDSWriter tdsWriter = null; - while (numBatchesExecuted < numBatches) { - // Fill in the parameter values for this batch - Parameter paramValues[] = batchParamValues.get(numBatchesPrepared); - assert paramValues.length == batchParam.length; - System.arraycopy(paramValues, 0, batchParam, 0, paramValues.length); - - boolean hasExistingTypeDefinitions = preparedTypeDefinitions != null; - boolean hasNewTypeDefinitions = buildPreparedStrings(batchParam, false); - - // Get the encryption metadata for the first batch only. - if ((0 == numBatchesExecuted) && (Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < batchParam.length) - && !isInternalEncryptionQuery && !encryptionMetadataIsRetrieved) { - getParameterEncryptionMetadata(batchParam); -*/ + /* + * TDSWriter tdsWriter = null; while (numBatchesExecuted < numBatches) { // Fill in the parameter values for this batch Parameter + * paramValues[] = batchParamValues.get(numBatchesPrepared); assert paramValues.length == batchParam.length; System.arraycopy(paramValues, 0, + * batchParam, 0, paramValues.length); + * + * boolean hasExistingTypeDefinitions = preparedTypeDefinitions != null; boolean hasNewTypeDefinitions = buildPreparedStrings(batchParam, + * false); + * + * // Get the encryption metadata for the first batch only. if ((0 == numBatchesExecuted) && + * (Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < batchParam.length) && !isInternalEncryptionQuery && + * !encryptionMetadataIsRetrieved) { getParameterEncryptionMetadata(batchParam); + */ TDSWriter tdsWriter = null; while (numBatchesExecuted < numBatches) { @@ -2675,7 +2760,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th // that repreparation is necessary. ++numBatchesPrepared; needsPrepare = doPrepExec(tdsWriter, batchParam, hasNewTypeDefinitions, hasExistingTypeDefinitions); - if ( needsPrepare || numBatchesPrepared == numBatches) { + if (needsPrepare || numBatchesPrepared == numBatches) { ensureExecuteResultsReader(batchCommand.startResponse(getIsResponseBufferingAdaptive())); boolean retry = false; @@ -2720,8 +2805,8 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th // so just record the failure for the particular batch item. updateCount = Statement.EXECUTE_FAILED; if (null == batchCommand.batchException) - batchCommand.batchException = e; - + batchCommand.batchException = e; + } // In batch execution, we have a special update count @@ -2760,6 +2845,7 @@ else if (null != batchCommand.batchException) { } } + @Override public final void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2769,6 +2855,7 @@ public final void setCharacterStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setCharacterStream(int n, java.io.Reader reader, int length) throws SQLServerException { @@ -2779,6 +2866,7 @@ public final void setCharacterStream(int n, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { @@ -2789,6 +2877,7 @@ public final void setCharacterStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setCharacterStream"); } + @Override public final void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2798,6 +2887,7 @@ public final void setNCharacterStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNCharacterStream"); } + @Override public final void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { @@ -2808,11 +2898,13 @@ public final void setNCharacterStream(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNCharacterStream"); } - /* L0 */ public final void setRef(int i, - java.sql.Ref x) throws SQLServerException { - NotImplemented(); + @Override + public final void setRef(int i, + java.sql.Ref x) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final void setBlob(int i, java.sql.Blob x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2822,6 +2914,7 @@ public final void setBlob(int i, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } + @Override public final void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2831,6 +2924,7 @@ public final void setBlob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } + @Override public final void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { @@ -2841,6 +2935,7 @@ public final void setBlob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setBlob"); } + @Override public final void setClob(int parameterIndex, java.sql.Clob clobValue) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2850,6 +2945,7 @@ public final void setClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setClob(int parameterIndex, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2859,6 +2955,7 @@ public final void setClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setClob(int parameterIndex, Reader reader, long length) throws SQLException { @@ -2869,6 +2966,7 @@ public final void setClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setClob"); } + @Override public final void setNClob(int parameterIndex, NClob value) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2878,6 +2976,7 @@ public final void setNClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } + @Override public final void setNClob(int parameterIndex, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2887,6 +2986,7 @@ public final void setNClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } + @Override public final void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { @@ -2897,11 +2997,13 @@ public final void setNClob(int parameterIndex, loggerExternal.exiting(getClassNameLogging(), "setNClob"); } - /* L0 */ public final void setArray(int i, - java.sql.Array x) throws SQLServerException { - NotImplemented(); + @Override + public final void setArray(int i, + java.sql.Array x) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final void setDate(int n, java.sql.Date x, java.util.Calendar cal) throws SQLServerException { @@ -2912,25 +3014,7 @@ public final void setDate(int n, loggerExternal.exiting(getClassNameLogging(), "setDate"); } - /** - * Sets the designated parameter to the given java.sql.Date value, using the given Calendar object. The driver uses the - * Calendar object to construct an SQL DATE value, which the driver then sends to the database. With a - * Calendar object, the driver can calculate the date taking into account a custom timezone. If no Calendar object is - * specified, the driver uses the default timezone, which is that of the virtual machine running the application. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param cal - * the Calendar object the driver will use to construct the date - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setDate(int n, java.sql.Date x, java.util.Calendar cal, @@ -2942,6 +3026,7 @@ public final void setDate(int n, loggerExternal.exiting(getClassNameLogging(), "setDate"); } + @Override public final void setTime(int n, java.sql.Time x, java.util.Calendar cal) throws SQLServerException { @@ -2952,23 +3037,7 @@ public final void setTime(int n, loggerExternal.exiting(getClassNameLogging(), "setTime"); } - /** - * Sets the designated parameter to the given java.sql.Time value. The driver converts this to an SQL TIME value when it - * sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param cal - * the Calendar object the driver will use to construct the date - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTime(int n, java.sql.Time x, java.util.Calendar cal, @@ -2980,6 +3049,7 @@ public final void setTime(int n, loggerExternal.exiting(getClassNameLogging(), "setTime"); } + @Override public final void setTimestamp(int n, java.sql.Timestamp x, java.util.Calendar cal) throws SQLServerException { @@ -2990,23 +3060,7 @@ public final void setTimestamp(int n, loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } - /** - * Sets the designated parameter to the given java.sql.Timestamp value. The driver converts this to an SQL TIMESTAMP - * value when it sends it to the database. - * - * @param n - * the first parameter is 1, the second is 2, ... - * @param x - * the parameter value - * @param cal - * the Calendar object the driver will use to construct the date - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public final void setTimestamp(int n, java.sql.Timestamp x, java.util.Calendar cal, @@ -3018,6 +3072,7 @@ public final void setTimestamp(int n, loggerExternal.exiting(getClassNameLogging(), "setTimestamp"); } + @Override public final void setNull(int paramIndex, int sqlType, String typeName) throws SQLServerException { @@ -3033,17 +3088,7 @@ public final void setNull(int paramIndex, loggerExternal.exiting(getClassNameLogging(), "setNull"); } - /** - * Returns parameter metadata for the prepared statement. - * - * @param forceRefresh: - * If true the cache will not be used to retrieve the metadata. - * - * @return - * Per the description. - * - * @throws SQLServerException when an error occurs - */ + @Override public final ParameterMetaData getParameterMetaData(boolean forceRefresh) throws SQLServerException { SQLServerParameterMetaData pmd = this.connection.getCachedParameterMetadata(sqlTextCacheKey); @@ -3055,32 +3100,32 @@ public final ParameterMetaData getParameterMetaData(boolean forceRefresh) throws loggerExternal.entering(getClassNameLogging(), "getParameterMetaData"); checkClosed(); pmd = new SQLServerParameterMetaData(this, userSQL); - connection.registerCachedParameterMetadata(sqlTextCacheKey, pmd); - loggerExternal.exiting(getClassNameLogging(), "getParameterMetaData", pmd); - return pmd; } } /* JDBC 3.0 */ - /* L3 */ public final ParameterMetaData getParameterMetaData() throws SQLServerException { - return getParameterMetaData(false); + @Override + public final ParameterMetaData getParameterMetaData() throws SQLServerException { + return getParameterMetaData(false); } - /* L3 */ public final void setURL(int parameterIndex, - java.net.URL x) throws SQLServerException { - NotImplemented(); + @Override + public final void setURL(int parameterIndex, + java.net.URL x) throws SQLException { + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final void setRowId(int parameterIndex, RowId x) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(connection, this); } + @Override public final void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3091,28 +3136,32 @@ public final void setSQLXML(int parameterIndex, } /* make sure we throw here */ - /* L0 */ public final int executeUpdate(String sql) throws SQLServerException { + @Override + public final int executeUpdate(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "executeUpdate", sql); MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_cannotTakeArgumentsPreparedOrCallable")); Object[] msgArgs = {"executeUpdate()"}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } - /* L0 */ public final boolean execute(String sql) throws SQLServerException { + @Override + public final boolean execute(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "execute", sql); MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_cannotTakeArgumentsPreparedOrCallable")); Object[] msgArgs = {"execute()"}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } - /* L0 */ public final java.sql.ResultSet executeQuery(String sql) throws SQLServerException { + @Override + public final java.sql.ResultSet executeQuery(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "executeQuery", sql); MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_cannotTakeArgumentsPreparedOrCallable")); Object[] msgArgs = {"executeQuery()"}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } - /* L0 */ public void addBatch(String sql) throws SQLServerException { + @Override + public void addBatch(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "addBatch", sql); MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_cannotTakeArgumentsPreparedOrCallable")); Object[] msgArgs = {"addBatch()"}; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42.java deleted file mode 100644 index d0957cbb2..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * - * This class is separated from SQLServerPreparedStatement class in order to resolve compiling error of missing Java 8 Types when running with Java 7. - * - * This class will be initialized instead of SQLServerPreparedStatement when Java 8 and JDBC 4.2 are used. - * - * It shares the same PreparedStatement implementation with SQLServerCallableStatement42. - * - */ -public class SQLServerPreparedStatement42 extends SQLServerPreparedStatement implements ISQLServerPreparedStatement42 { - - SQLServerPreparedStatement42(SQLServerConnection conn, - String sql, - int nRSType, - int nRSConcur, - SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException { - super(conn, sql, nRSType, nRSConcur, stmtColEncSetting); - } - - public final void setObject(int index, - Object obj, - SQLType jdbcType) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, index, obj, jdbcType); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - int scaleOrLength) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, scaleOrLength); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, precision, scale); - } - - public final void setObject(int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale, - boolean forceEncrypt) throws SQLServerException { - SQLServerPreparedStatement42Helper.setObject(this, parameterIndex, x, targetSqlType, precision, scale, forceEncrypt); - } -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42Helper.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42Helper.java deleted file mode 100644 index efd9c1774..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement42Helper.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * - * This class provides the underlying implementation of ISQLServerPreparedStatement42 interface to SQLServerPreparedStatement42 and - * SQLServerCallableStatement42, so that SQLServerPreparedStatement42 and SQLServerCallableStatement42 have the same implementation for same methods. - * - */ -class SQLServerPreparedStatement42Helper { - - static final void setObject(SQLServerPreparedStatement ps, - int index, - Object obj, - SQLType jdbcType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (SQLServerStatement.loggerExternal.isLoggable(java.util.logging.Level.FINER)) - SQLServerStatement.loggerExternal.entering(ps.getClassNameLogging(), "setObject", new Object[] {index, obj, jdbcType}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - ps.setObject(index, obj, jdbcType.getVendorTypeNumber()); - - SQLServerStatement.loggerExternal.exiting(ps.getClassNameLogging(), "setObject"); - } - - static final void setObject(SQLServerPreparedStatement ps, - int parameterIndex, - Object x, - SQLType targetSqlType, - int scaleOrLength) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (SQLServerStatement.loggerExternal.isLoggable(java.util.logging.Level.FINER)) - SQLServerStatement.loggerExternal.entering(ps.getClassNameLogging(), "setObject", - new Object[] {parameterIndex, x, targetSqlType, scaleOrLength}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - ps.setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), scaleOrLength); - - SQLServerStatement.loggerExternal.exiting(ps.getClassNameLogging(), "setObject"); - } - - static final void setObject(SQLServerPreparedStatement ps, - int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (SQLServerStatement.loggerExternal.isLoggable(java.util.logging.Level.FINER)) - SQLServerStatement.loggerExternal.entering(ps.getClassNameLogging(), "setObject", - new Object[] {parameterIndex, x, targetSqlType, precision, scale}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - ps.setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), precision, scale, false); - - SQLServerStatement.loggerExternal.exiting(ps.getClassNameLogging(), "setObject"); - } - - static final void setObject(SQLServerPreparedStatement ps, - int parameterIndex, - Object x, - SQLType targetSqlType, - Integer precision, - Integer scale, - boolean forceEncrypt) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (SQLServerStatement.loggerExternal.isLoggable(java.util.logging.Level.FINER)) - SQLServerStatement.loggerExternal.entering(ps.getClassNameLogging(), "setObject", - new Object[] {parameterIndex, x, targetSqlType, precision, scale, forceEncrypt}); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - ps.setObject(parameterIndex, x, targetSqlType.getVendorTypeNumber(), precision, scale, forceEncrypt); - - SQLServerStatement.loggerExternal.exiting(ps.getClassNameLogging(), "setObject"); - } -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 884be5c93..afe0799bb 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -40,7 +40,6 @@ protected Object[][] getContents() { {"R_unknownJDBCType", "Invalid JDBC data type {0}."}, {"R_notSQLServer", "The driver received an unexpected pre-login response. Verify the connection properties and check that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. This driver can be used only with SQL Server 2005 or later."}, {"R_tcpOpenFailed", "{0}. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall."}, - {"R_unsupportedJREVersion", "Java Runtime Environment (JRE) version {0} is not supported by this driver. Use the sqljdbc4.jar class library, which provides support for JDBC 4.0."}, {"R_unsupportedServerVersion", "SQL Server version {0} is not supported by this driver."}, {"R_noServerResponse", "SQL Server did not return a response. The connection has been closed."}, {"R_truncatedServerResponse", "SQL Server returned an incomplete response. The connection has been closed."}, @@ -227,8 +226,8 @@ protected Object[][] getContents() { {"R_invalidTransactionOption", "UseInternalTransaction option cannot be set to TRUE when used with a Connection object."}, {"R_invalidNegativeArg", "The {0} argument cannot be negative."}, {"R_BulkColumnMappingsIsEmpty", "Cannot perform bulk copy operation if the only mapping is an identity column and KeepIdentity is set to false."}, - {"R_CSVDataSchemaMismatch", "Source data does not match source schema."}, - {"R_BulkCSVDataDuplicateColumn", "Duplicate column names are not allowed."}, + {"R_DataSchemaMismatch", "Source data does not match source schema."}, + {"R_BulkDataDuplicateColumn", "Duplicate column names are not allowed."}, {"R_invalidColumnOrdinal", "Column {0} is invalid. Column number should be greater than zero."}, {"R_unsupportedEncoding", "The encoding {0} is not supported."}, {"R_UnexpectedDescribeParamFormat", "Internal error. The format of the resultset returned by sp_describe_parameter_encryption is invalid. One of the resultsets is missing."}, @@ -393,5 +392,12 @@ protected Object[][] getContents() { {"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1, and TLSv1.2 are supported."}, {"R_cancelQueryTimeoutPropertyDescription", "The number of seconds to wait to cancel sending a query timeout."}, {"R_invalidCancelQueryTimeout", "The cancel timeout value {0} is not valid."}, + {"R_useBulkCopyForBatchInsertPropertyDescription", "Whether the driver will use bulk copy API for batch insert operations"}, + {"R_UnknownDataClsTokenNumber", "Unknown token for Data Classification."}, // From Server + {"R_InvalidDataClsVersionNumber", "Invalid version number {0} for Data Classification."}, // From Server + {"R_unknownUTF8SupportValue", "Unknown value for UTF8 support."}, + {"R_illegalWKT", "Illegal Well-Known text. Please make sure Well-Known text is valid."}, + {"R_illegalTypeForGeometry", "{0} is not supported for Geometry."}, + {"R_illegalWKTposition", "Illegal character in Well-Known text at position {0}."}, }; -} \ No newline at end of file +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java index e3a2296e3..b7b2370c9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java @@ -22,7 +22,7 @@ import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLType; import java.sql.SQLWarning; import java.sql.SQLXML; import java.text.MessageFormat; @@ -31,6 +31,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; +import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification; + /** * Indicates the type of the row received from the server */ @@ -43,7 +45,12 @@ enum RowType { /** * Top-level JDBC ResultSet implementation */ -public class SQLServerResultSet implements ISQLServerResultSet { +public class SQLServerResultSet implements ISQLServerResultSet, java.io.Serializable { + + /** + * Always refresh SerialVersionUID when prompted + */ + private static final long serialVersionUID = -1624082547992040463L; /** Generate the statement's logging ID */ private static final AtomicInteger lastResultSetID = new AtomicInteger(0); @@ -55,6 +62,7 @@ private static int nextResultSetID() { final static java.util.logging.Logger logger = java.util.logging.Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerResultSet"); + @Override public String toString() { return traceID; } @@ -84,7 +92,7 @@ String getClassNameLogging() { private boolean isClosed = false; private final int serverCursorId; - + protected int getServerCursorId() { return serverCursorId; } @@ -206,13 +214,18 @@ private void skipColumns(int columnsToSkip, /** TDS reader from which row values are read */ private TDSReader tdsReader; - + protected TDSReader getTDSReader() { return tdsReader; } private final FetchBuffer fetchBuffer; + @Override + public SensitivityClassification getSensitivityClassification() { + return tdsReader.sensitivityClassification; + } + /** * Make a new result set * @@ -394,6 +407,7 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { } } + @Override public boolean isWrapperFor(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "isWrapperFor"); boolean f = iface.isInstance(this); @@ -401,6 +415,7 @@ public boolean isWrapperFor(Class iface) throws SQLException { return f; } + @Override public T unwrap(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "unwrap"); T t; @@ -421,7 +436,7 @@ public T unwrap(Class iface) throws SQLException { * * @throws SQLServerException */ - /* L0 */ void checkClosed() throws SQLServerException { + void checkClosed() throws SQLServerException { if (isClosed) { SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_resultsetClosed"), null, false); @@ -436,6 +451,7 @@ public T unwrap(Class iface) throws SQLException { throw rowErrorException; } + @Override public boolean isClosed() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isClosed"); boolean result = isClosed || stmt.isClosed(); @@ -446,10 +462,11 @@ public boolean isClosed() throws SQLException { /** * Called by ResultSet API methods to disallow method use on forward only result sets. * - * @throws SQLServerException + * @throws SQLException * if the result set is forward only. + * @throws SQLFeatureNotSupportedException */ - private void throwNotScrollable() throws SQLServerException { + private void throwNotScrollable() throws SQLException { SQLServerException.makeFromDriverError(stmt.connection, this, SQLServerException.getErrString("R_requestedOpNotSupportedOnForward"), null, true); } @@ -462,7 +479,7 @@ private boolean isDynamic() { return 0 != serverCursorId && TDS.SCROLLOPT_DYNAMIC == stmt.getCursorType(); } - private void verifyResultSetIsScrollable() throws SQLServerException { + private void verifyResultSetIsScrollable() throws SQLException { if (isForwardOnly()) throwNotScrollable(); } @@ -591,6 +608,7 @@ private void closeInternal() { stmt.decrResultSetCount(); } + @Override public void close() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "close"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -609,6 +627,7 @@ public void close() throws SQLServerException { * If any errors occur. * @return the column index */ + @Override public int findColumn(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "findColumn", columnName); checkClosed(); @@ -670,7 +689,7 @@ final Column getColumn(int columnIndex) throws SQLServerException { // before moving to another one. if (null != activeStream) { try { - fillLOBs(); + fillLOBs(); activeStream.close(); } catch (IOException e) { @@ -731,17 +750,14 @@ private Column loadColumn(int index) throws SQLServerException { return getColumn(index); } - /* L0 */ private void NotImplemented() throws SQLServerException { - SQLServerException.makeFromDriverError(stmt.connection, stmt, SQLServerException.getErrString("R_notSupported"), null, false); - } - /** * Clear result set warnings * * @throws SQLServerException * when an error occurs */ - /* L0 */ public void clearWarnings() throws SQLServerException { + @Override + public void clearWarnings() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "clearWarnings"); loggerExternal.exiting(getClassNameLogging(), "clearWarnings"); } @@ -749,12 +765,13 @@ private Column loadColumn(int index) throws SQLServerException { /* ----------------- JDBC API methods ------------------ */ private void moverInit() throws SQLServerException { - fillLOBs(); + fillLOBs(); cancelInsert(); cancelUpdates(); } - public boolean relative(int rows) throws SQLServerException { + @Override + public boolean relative(int rows) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "relative", rows); @@ -943,6 +960,7 @@ private void updateCurrentRow(int rowsToMove) { * * @return false when there are no more rows to read */ + @Override public boolean next() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "next"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -968,7 +986,7 @@ public boolean next() throws SQLServerException { moveFirst(); else moveForward(1); - + boolean value = hasCurrentRow(); loggerExternal.exiting(getClassNameLogging(), "next", value); return value; @@ -1035,6 +1053,7 @@ public boolean next() throws SQLServerException { return false; } + @Override public boolean wasNull() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "wasNull"); checkClosed(); @@ -1046,7 +1065,8 @@ public boolean wasNull() throws SQLServerException { /** * @return true if the cursor is before the first row in this result set, returns false otherwise or if the result set contains no rows. */ - public boolean isBeforeFirst() throws SQLServerException { + @Override + public boolean isBeforeFirst() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isBeforeFirst"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1105,7 +1125,8 @@ public boolean isBeforeFirst() throws SQLServerException { return value; } - public boolean isAfterLast() throws SQLServerException { + @Override + public boolean isAfterLast() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isAfterLast"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1140,14 +1161,24 @@ public boolean isAfterLast() throws SQLServerException { } /** - * Determines whether the cursor is on the first row in this ResultSet object. - * + * Retrieves whether the cursor is on the first row of this ResultSet object. + * * This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. + * + *

+ * Note:Support for the isFirst method is optional for ResultSets with a result set type of + * TYPE_FORWARD_ONLY * - * @return true if the cursor is on the first row in this result set + * @return true if the cursor is on the first row; false otherwise + * + * @exception SQLException + * if a database access error occurs or this method is called on a closed result set + * + * @since 1.2 */ - public boolean isFirst() throws SQLServerException { + @Override + public boolean isFirst() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isFirst"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1177,14 +1208,27 @@ public boolean isFirst() throws SQLServerException { } /** - * Determines whether the cursor is on the last row in this ResultSet object. - * + * Retrieves whether the cursor is on the last row of this ResultSet object. Note: Calling the method + * isLast may be expensive because the JDBC driver might need to fetch ahead one row in order to determine whether the current row is + * the last row in the result set. + * + *

* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. - * - * @return true if the cursor is on the last row in this result set + *

+ * + * Note: Support for the isLast method is optional for ResultSets with a result set type of + * TYPE_FORWARD_ONLY + * + * @return true if the cursor is on the last row; false otherwise + * + * @exception SQLException + * if a database access error occurs or this method is called on a closed result set + * + * @since 1.2 */ - public boolean isLast() throws SQLServerException { + @Override + public boolean isLast() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isLast"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1234,7 +1278,8 @@ public boolean isLast() throws SQLServerException { return isLast; } - public void beforeFirst() throws SQLServerException { + @Override + public void beforeFirst() throws SQLException { loggerExternal.entering(getClassNameLogging(), "beforeFirst"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -1265,7 +1310,8 @@ private void moveBeforeFirst() throws SQLServerException { currentRow = BEFORE_FIRST_ROW; } - public void afterLast() throws SQLServerException { + @Override + public void afterLast() throws SQLException { loggerExternal.entering(getClassNameLogging(), "afterLast"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -1297,14 +1343,23 @@ private void moveAfterLast() throws SQLServerException { } /** - * Moves the cursor to the first row in this ResultSet object. + * Moves the cursor to the first row in this ResultSet object. * + *

* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. - * - * @return true if the cursor is on a valid row, otherwise returns false if there are no rows in this ResultSet object + *

+ * + * @return true if the cursor is on a valid row; false if there are no rows in the result set + * + * @exception SQLException + * if a database access error occurs; this method is called on a closed result set or the result set type is + * TYPE_FORWARD_ONLY + * + * @since 1.2 */ - public boolean first() throws SQLServerException { + @Override + public boolean first() throws SQLException { loggerExternal.entering(getClassNameLogging(), "first"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1347,14 +1402,21 @@ private void moveFirst() throws SQLServerException { } /** - * Moves the cursor to the last row in this ResultSet object. - * + * Moves the cursor to the last row in this ResultSet object. + * * This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. * - * @return true if the cursor is on a valid row, otherwise returns false if there are no rows in this ResultSet object + * @return true if the cursor is on a valid row; false if there are no rows in the result set + * + * @exception SQLException + * if a database access error occurs; this method is called on a closed result set or the result set type is + * TYPE_FORWARD_ONLY + * + * @since 1.2 */ - public boolean last() throws SQLServerException { + @Override + public boolean last() throws SQLException { loggerExternal.entering(getClassNameLogging(), "last"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1401,12 +1463,8 @@ private void moveLast() throws SQLServerException { currentRow = isDynamic() ? UNKNOWN_ROW : rowCount; } - /** - * Retrieves the number of the current row in this ResultSet object. The first row is number 1, the second is 2, and so on. - * - * @return the number of the current row; 0 if there is no current row - */ - public int getRow() throws SQLServerException { + @Override + public int getRow() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getRow"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1435,15 +1493,48 @@ public int getRow() throws SQLServerException { } /** - * Moves the cursor to the specified row in this ResultSet object. The specified row may be positive, negative or zero. + * Moves the cursor to the given row number in this ResultSet object. * + *

* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. + *

+ * + *

+ * If the row number is positive, the cursor moves to the given row number with respect to the beginning of the result set. The first row is row + * 1, the second is row 2, and so on. + * + *

+ * If the given row number is negative, the cursor moves to an absolute row position with respect to the end of the result set. For example, + * calling the method absolute(-1) positions the cursor on the last row; calling the method absolute(-2) moves the + * cursor to the next-to-last row, and so on. + * + *

+ * If the row number specified is zero, the cursor is moved to before the first row. * - * @return true if the cursor is on a valid row in this result set, otherwise returns false if the cursor is before the first row or after the - * last row + *

+ * An attempt to position the cursor beyond the first/last row in the result set leaves the cursor before the first row or after the last row. + * + *

+ * Note: Calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as + * calling last(). + * + * @param row + * the number of the row to which the cursor should move. A value of zero indicates that the cursor will be positioned before the first + * row; a positive number indicates the row number counting from the beginning of the result set; a negative number indicates the row + * number counting from the end of the result set + * + * @return true if the cursor is moved to a position in this ResultSet object; false if the cursor is + * before the first row or after the last row + * + * @exception SQLException + * if a database access error occurs; this method is called on a closed result set or the result set type is + * TYPE_FORWARD_ONLY + * + * @since 1.2 */ - public boolean absolute(int row) throws SQLServerException { + @Override + public boolean absolute(int row) throws SQLException { loggerExternal.entering(getClassNameLogging(), "absolute"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -1751,14 +1842,21 @@ private int clientMoveAbsolute(int row) throws SQLServerException { } /** - * Moves the cursor to the previous row in this ResultSet object. + * Moves the cursor to the previous row in this ResultSet object. * * This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE, * TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC. * - * @return true if the cursor is on a valid row in this result set + * @return true if the cursor is now positioned on a valid row; false if the cursor is positioned before the first row + * + * @exception SQLException + * if a database access error occurs; this method is called on a closed result set or the result set type is + * TYPE_FORWARD_ONLY + * + * @since 1.2 */ - public boolean previous() throws SQLServerException { + @Override + public boolean previous() throws SQLException { loggerExternal.entering(getClassNameLogging(), "previous"); if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString() + logCursorState()); @@ -1793,17 +1891,19 @@ private void cancelInsert() { /** Clear any updated column values for the current row in the result set. */ final void clearColumnsValues() { - int l = columns.length; - for (Column column : columns) column.cancelUpdates(); + for (Column column : columns) + column.cancelUpdates(); } - /* L0 */ public SQLWarning getWarnings() throws SQLServerException { + @Override + public SQLWarning getWarnings() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getWarnings"); loggerExternal.exiting(getClassNameLogging(), "getWarnings", null); return null; } - public void setFetchDirection(int direction) throws SQLServerException { + @Override + public void setFetchDirection(int direction) throws SQLException { loggerExternal.entering(getClassNameLogging(), "setFetchDirection", direction); checkClosed(); @@ -1824,13 +1924,15 @@ public void setFetchDirection(int direction) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setFetchDirection"); } - public int getFetchDirection() throws SQLServerException { + @Override + public int getFetchDirection() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getFetchDirection"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getFetchDirection", fetchDirection); return fetchDirection; } + @Override public void setFetchSize(int rows) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setFetchSize", rows); checkClosed(); @@ -1841,14 +1943,16 @@ public void setFetchSize(int rows) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setFetchSize"); } - /* L0 */ public int getFetchSize() throws SQLServerException { + @Override + public int getFetchSize() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getFetchSize"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getFloat", fetchSize); return fetchSize; } - /* L0 */ public int getType() throws SQLServerException { + @Override + public int getType() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getType"); checkClosed(); @@ -1857,7 +1961,8 @@ public void setFetchSize(int rows) throws SQLServerException { return value; } - /* L0 */ public int getConcurrency() throws SQLServerException { + @Override + public int getConcurrency() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getConcurrency"); checkClosed(); int value = stmt.getResultSetConcurrency(); @@ -1925,15 +2030,16 @@ private Object getValue(int columnIndex, lastValueWasNull = (null == o); return o; } - - void setInternalVariantType(int columnIndex, SqlVariant type) throws SQLServerException{ + + void setInternalVariantType(int columnIndex, + SqlVariant type) throws SQLServerException { getterGetColumn(columnIndex).setInternalVariant(type); } - + SqlVariant getVariantInternalType(int columnIndex) throws SQLServerException { return getterGetColumn(columnIndex).getInternalVariant(); - } - + } + private Object getStream(int columnIndex, StreamType streamType) throws SQLServerException { Object value = getValue(columnIndex, streamType.getJDBCType(), @@ -1952,6 +2058,7 @@ private SQLXML getSQLXMLInternal(int columnIndex) throws SQLServerException { return value; } + @Override public java.io.InputStream getAsciiStream(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getAsciiStream", columnIndex); checkClosed(); @@ -1960,6 +2067,7 @@ public java.io.InputStream getAsciiStream(int columnIndex) throws SQLServerExcep return value; } + @Override public java.io.InputStream getAsciiStream(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getAsciiStream", columnName); checkClosed(); @@ -1969,6 +2077,7 @@ public java.io.InputStream getAsciiStream(String columnName) throws SQLServerExc } @Deprecated + @Override public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1982,6 +2091,7 @@ public BigDecimal getBigDecimal(int columnIndex, } @Deprecated + @Override public BigDecimal getBigDecimal(String columnName, int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -1994,6 +2104,7 @@ public BigDecimal getBigDecimal(String columnName, return value; } + @Override public java.io.InputStream getBinaryStream(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBinaryStream", columnIndex); checkClosed(); @@ -2002,6 +2113,7 @@ public java.io.InputStream getBinaryStream(int columnIndex) throws SQLServerExce return value; } + @Override public java.io.InputStream getBinaryStream(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBinaryStream", columnName); checkClosed(); @@ -2010,6 +2122,7 @@ public java.io.InputStream getBinaryStream(String columnName) throws SQLServerEx return value; } + @Override public boolean getBoolean(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBoolean", columnIndex); checkClosed(); @@ -2018,6 +2131,7 @@ public boolean getBoolean(int columnIndex) throws SQLServerException { return null != value ? value : false; } + @Override public boolean getBoolean(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBoolean", columnName); checkClosed(); @@ -2026,6 +2140,7 @@ public boolean getBoolean(String columnName) throws SQLServerException { return null != value ? value : false; } + @Override public byte getByte(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getByte", columnIndex); checkClosed(); @@ -2034,6 +2149,7 @@ public byte getByte(int columnIndex) throws SQLServerException { return null != value ? value.byteValue() : 0; } + @Override public byte getByte(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getByte", columnName); checkClosed(); @@ -2042,6 +2158,7 @@ public byte getByte(String columnName) throws SQLServerException { return null != value ? value.byteValue() : 0; } + @Override public byte[] getBytes(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBytes", columnIndex); checkClosed(); @@ -2050,6 +2167,7 @@ public byte[] getBytes(int columnIndex) throws SQLServerException { return value; } + @Override public byte[] getBytes(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBytes", columnName); checkClosed(); @@ -2058,6 +2176,7 @@ public byte[] getBytes(String columnName) throws SQLServerException { return value; } + @Override public java.sql.Date getDate(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDate", columnIndex); checkClosed(); @@ -2066,6 +2185,7 @@ public java.sql.Date getDate(int columnIndex) throws SQLServerException { return value; } + @Override public java.sql.Date getDate(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDate", columnName); checkClosed(); @@ -2074,6 +2194,7 @@ public java.sql.Date getDate(String columnName) throws SQLServerException { return value; } + @Override public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2084,6 +2205,7 @@ public java.sql.Date getDate(int columnIndex, return value; } + @Override public java.sql.Date getDate(String colName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2094,6 +2216,7 @@ public java.sql.Date getDate(String colName, return value; } + @Override public double getDouble(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDouble", columnIndex); checkClosed(); @@ -2102,6 +2225,7 @@ public double getDouble(int columnIndex) throws SQLServerException { return null != value ? value : 0; } + @Override public double getDouble(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDouble", columnName); checkClosed(); @@ -2110,6 +2234,7 @@ public double getDouble(String columnName) throws SQLServerException { return null != value ? value : 0; } + @Override public float getFloat(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnIndex); checkClosed(); @@ -2118,6 +2243,7 @@ public float getFloat(int columnIndex) throws SQLServerException { return null != value ? value : 0; } + @Override public float getFloat(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnName); checkClosed(); @@ -2125,7 +2251,8 @@ public float getFloat(String columnName) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "getFloat", value); return null != value ? value : 0; } - + + @Override public Geometry getGeometry(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnIndex); checkClosed(); @@ -2134,6 +2261,7 @@ public Geometry getGeometry(int columnIndex) throws SQLServerException { return value; } + @Override public Geometry getGeometry(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnName); checkClosed(); @@ -2141,7 +2269,8 @@ public Geometry getGeometry(String columnName) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "getFloat", value); return value; } - + + @Override public Geography getGeography(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnIndex); checkClosed(); @@ -2150,6 +2279,7 @@ public Geography getGeography(int columnIndex) throws SQLServerException { return value; } + @Override public Geography getGeography(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFloat", columnName); checkClosed(); @@ -2158,6 +2288,7 @@ public Geography getGeography(String columnName) throws SQLServerException { return value; } + @Override public int getInt(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getInt", columnIndex); checkClosed(); @@ -2166,6 +2297,7 @@ public int getInt(int columnIndex) throws SQLServerException { return null != value ? value : 0; } + @Override public int getInt(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getInt", columnName); checkClosed(); @@ -2174,6 +2306,7 @@ public int getInt(String columnName) throws SQLServerException { return null != value ? value : 0; } + @Override public long getLong(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getLong", columnIndex); checkClosed(); @@ -2182,6 +2315,7 @@ public long getLong(int columnIndex) throws SQLServerException { return null != value ? value : 0; } + @Override public long getLong(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getLong", columnName); checkClosed(); @@ -2190,6 +2324,7 @@ public long getLong(String columnName) throws SQLServerException { return null != value ? value : 0; } + @Override public java.sql.ResultSetMetaData getMetaData() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMetaData"); checkClosed(); @@ -2199,6 +2334,7 @@ public java.sql.ResultSetMetaData getMetaData() throws SQLServerException { return metaData; } + @Override public Object getObject(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getObject", columnIndex); checkClosed(); @@ -2207,6 +2343,7 @@ public Object getObject(int columnIndex) throws SQLServerException { return value; } + @Override public T getObject(int columnIndex, Class type) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getObject", columnIndex); @@ -2289,6 +2426,7 @@ else if (type == Double.class) { return type.cast(returnValue); } + @Override public Object getObject(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getObject", columnName); checkClosed(); @@ -2297,6 +2435,7 @@ public Object getObject(String columnName) throws SQLServerException { return value; } + @Override public T getObject(String columnName, Class type) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getObject", columnName); @@ -2306,6 +2445,7 @@ public T getObject(String columnName, return value; } + @Override public short getShort(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getShort", columnIndex); checkClosed(); @@ -2314,6 +2454,7 @@ public short getShort(int columnIndex) throws SQLServerException { return null != value ? value : 0; } + @Override public short getShort(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getShort", columnName); checkClosed(); @@ -2322,6 +2463,7 @@ public short getShort(String columnName) throws SQLServerException { return null != value ? value : 0; } + @Override public String getString(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getString", columnIndex); checkClosed(); @@ -2335,6 +2477,7 @@ public String getString(int columnIndex) throws SQLServerException { return value; } + @Override public String getString(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getString", columnName); checkClosed(); @@ -2348,6 +2491,7 @@ public String getString(String columnName) throws SQLServerException { return value; } + @Override public String getNString(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNString", columnIndex); checkClosed(); @@ -2356,6 +2500,7 @@ public String getNString(int columnIndex) throws SQLException { return value; } + @Override public String getNString(String columnLabel) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNString", columnLabel); checkClosed(); @@ -2364,17 +2509,8 @@ public String getNString(String columnLabel) throws SQLException { return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a microsoft.sql.datetimeoffset object in the Java - * programming language. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLException - * when an error occurs - */ - public String getUniqueIdentifier(int columnIndex) throws SQLException { + @Override + public String getUniqueIdentifier(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getUniqueIdentifier", columnIndex); checkClosed(); String value = (String) getValue(columnIndex, JDBCType.GUID); @@ -2382,17 +2518,8 @@ public String getUniqueIdentifier(int columnIndex) throws SQLException { return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a microsoft.sql.datetimeoffset object in the Java - * programming language. - * - * @param columnLabel - * the name of the column - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLException - * when an error occurs - */ - public String getUniqueIdentifier(String columnLabel) throws SQLException { + @Override + public String getUniqueIdentifier(String columnLabel) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getUniqueIdentifier", columnLabel); checkClosed(); String value = (String) getValue(findColumn(columnLabel), JDBCType.GUID); @@ -2400,6 +2527,7 @@ public String getUniqueIdentifier(String columnLabel) throws SQLException { return value; } + @Override public java.sql.Time getTime(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTime", columnIndex); checkClosed(); @@ -2408,6 +2536,7 @@ public java.sql.Time getTime(int columnIndex) throws SQLServerException { return value; } + @Override public java.sql.Time getTime(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTime", columnName); checkClosed(); @@ -2416,6 +2545,7 @@ public java.sql.Time getTime(String columnName) throws SQLServerException { return value; } + @Override public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2426,6 +2556,7 @@ public java.sql.Time getTime(int columnIndex, return value; } + @Override public java.sql.Time getTime(String colName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2436,6 +2567,7 @@ public java.sql.Time getTime(String colName, return value; } + @Override public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTimestamp", columnIndex); checkClosed(); @@ -2444,6 +2576,7 @@ public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLServerExceptio return value; } + @Override public java.sql.Timestamp getTimestamp(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTimestamp", columnName); checkClosed(); @@ -2452,6 +2585,7 @@ public java.sql.Timestamp getTimestamp(String columnName) throws SQLServerExcept return value; } + @Override public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2462,6 +2596,7 @@ public java.sql.Timestamp getTimestamp(int columnIndex, return value; } + @Override public java.sql.Timestamp getTimestamp(String colName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2472,16 +2607,7 @@ public java.sql.Timestamp getTimestamp(String colName, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public java.sql.Timestamp getDateTime(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDateTime", columnIndex); checkClosed(); @@ -2490,16 +2616,7 @@ public java.sql.Timestamp getDateTime(int columnIndex) throws SQLServerException return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param columnName - * is the name of the column - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getDateTime(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDateTime", columnName); checkClosed(); @@ -2508,19 +2625,7 @@ public java.sql.Timestamp getDateTime(String columnName) throws SQLServerExcepti return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does - * not store timezone information. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @param cal - * the java.util.Calendar object to use in constructing the dateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getDateTime(int columnIndex, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2531,20 +2636,7 @@ public java.sql.Timestamp getDateTime(int columnIndex, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does - * not store timezone information. - * - * @param colName - * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the - * column - * @param cal - * the java.util.Calendar object to use in constructing the dateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getDateTime(String colName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2555,16 +2647,7 @@ public java.sql.Timestamp getDateTime(String colName, return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public java.sql.Timestamp getSmallDateTime(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getSmallDateTime", columnIndex); checkClosed(); @@ -2573,16 +2656,7 @@ public java.sql.Timestamp getSmallDateTime(int columnIndex) throws SQLServerExce return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param columnName - * is the name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getSmallDateTime(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getSmallDateTime", columnName); checkClosed(); @@ -2591,18 +2665,7 @@ public java.sql.Timestamp getSmallDateTime(String columnName) throws SQLServerEx return value; } - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming - * language. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @param cal - * the java.util.Calendar object to use in constructing the smalldateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getSmallDateTime(int columnIndex, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2613,16 +2676,7 @@ public java.sql.Timestamp getSmallDateTime(int columnIndex, return value; } - /** - * - * @param colName - * The name of a column - * @param cal - * the java.util.Calendar object to use in constructing the smalldateTime - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public java.sql.Timestamp getSmallDateTime(String colName, Calendar cal) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2633,7 +2687,8 @@ public java.sql.Timestamp getSmallDateTime(String colName, return value; } - public microsoft.sql.DateTimeOffset getDateTimeOffset(int columnIndex) throws SQLException { + @Override + public microsoft.sql.DateTimeOffset getDateTimeOffset(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDateTimeOffset", columnIndex); checkClosed(); @@ -2647,7 +2702,8 @@ public microsoft.sql.DateTimeOffset getDateTimeOffset(int columnIndex) throws SQ return value; } - public microsoft.sql.DateTimeOffset getDateTimeOffset(String columnName) throws SQLException { + @Override + public microsoft.sql.DateTimeOffset getDateTimeOffset(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getDateTimeOffset", columnName); checkClosed(); @@ -2661,34 +2717,39 @@ public microsoft.sql.DateTimeOffset getDateTimeOffset(String columnName) throws return value; } + @Override @Deprecated - public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLServerException { + public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getUnicodeStream", columnIndex); - NotImplemented(); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } + @Override @Deprecated - public java.io.InputStream getUnicodeStream(String columnName) throws SQLServerException { + public java.io.InputStream getUnicodeStream(String columnName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getUnicodeStream", columnName); - NotImplemented(); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } + @Override public Object getObject(int i, - java.util.Map> map) throws SQLServerException { + java.util.Map> map) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getObject", new Object[] {i, map}); - NotImplemented(); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } - public Ref getRef(int i) throws SQLServerException { + @Override + public Ref getRef(int i) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getRef"); - NotImplemented(); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } + @Override public Blob getBlob(int i) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBlob", i); checkClosed(); @@ -2698,6 +2759,7 @@ public Blob getBlob(int i) throws SQLServerException { return value; } + @Override public Blob getBlob(String colName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getBlob", colName); checkClosed(); @@ -2707,6 +2769,7 @@ public Blob getBlob(String colName) throws SQLServerException { return value; } + @Override public Clob getClob(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getClob", columnIndex); checkClosed(); @@ -2716,6 +2779,7 @@ public Clob getClob(int columnIndex) throws SQLServerException { return value; } + @Override public Clob getClob(String colName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getClob", colName); checkClosed(); @@ -2725,6 +2789,7 @@ public Clob getClob(String colName) throws SQLServerException { return value; } + @Override public NClob getNClob(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNClob", columnIndex); checkClosed(); @@ -2734,6 +2799,7 @@ public NClob getNClob(int columnIndex) throws SQLException { return value; } + @Override public NClob getNClob(String columnLabel) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNClob", columnLabel); checkClosed(); @@ -2743,35 +2809,41 @@ public NClob getNClob(String columnLabel) throws SQLException { return value; } - public Array getArray(int i) throws SQLServerException { - NotImplemented(); + @Override + public Array getArray(int i) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } + @Override public Object getObject(String colName, - java.util.Map> map) throws SQLServerException { - NotImplemented(); + java.util.Map> map) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } - public Ref getRef(String colName) throws SQLServerException { - NotImplemented(); + @Override + public Ref getRef(String colName) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } - public Array getArray(String colName) throws SQLServerException { - NotImplemented(); + @Override + public Array getArray(String colName) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } - public String getCursorName() throws SQLServerException { + @Override + public String getCursorName() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getCursorName"); SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_positionedUpdatesNotSupported"), null, false); loggerExternal.exiting(getClassNameLogging(), "getCursorName", null); return null; } - public java.io.Reader getCharacterStream(int columnIndex) throws SQLServerException { + @Override + public java.io.Reader getCharacterStream(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getCharacterStream", columnIndex); checkClosed(); Reader value = (Reader) getStream(columnIndex, StreamType.CHARACTER); @@ -2779,7 +2851,8 @@ public java.io.Reader getCharacterStream(int columnIndex) throws SQLServerExcept return value; } - public java.io.Reader getCharacterStream(String columnName) throws SQLServerException { + @Override + public java.io.Reader getCharacterStream(String columnName) throws SQLException { checkClosed(); loggerExternal.entering(getClassNameLogging(), "getCharacterStream", columnName); Reader value = (Reader) getStream(findColumn(columnName), StreamType.CHARACTER); @@ -2787,6 +2860,7 @@ public java.io.Reader getCharacterStream(String columnName) throws SQLServerExce return value; } + @Override public Reader getNCharacterStream(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNCharacterStream", columnIndex); checkClosed(); @@ -2795,6 +2869,7 @@ public Reader getNCharacterStream(int columnIndex) throws SQLException { return value; } + @Override public Reader getNCharacterStream(String columnLabel) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getNCharacterStream", columnLabel); checkClosed(); @@ -2803,7 +2878,8 @@ public Reader getNCharacterStream(String columnLabel) throws SQLException { return value; } - public BigDecimal getBigDecimal(int columnIndex) throws SQLServerException { + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getBigDecimal", columnIndex); checkClosed(); BigDecimal value = (BigDecimal) getValue(columnIndex, JDBCType.DECIMAL); @@ -2811,7 +2887,8 @@ public BigDecimal getBigDecimal(int columnIndex) throws SQLServerException { return value; } - public BigDecimal getBigDecimal(String columnName) throws SQLServerException { + @Override + public BigDecimal getBigDecimal(String columnName) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getBigDecimal", columnName); checkClosed(); BigDecimal value = (BigDecimal) getValue(findColumn(columnName), JDBCType.DECIMAL); @@ -2819,15 +2896,7 @@ public BigDecimal getBigDecimal(String columnName) throws SQLServerException { return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param columnIndex - * The zero-based ordinal of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * when an error occurs - */ + @Override public BigDecimal getMoney(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMoney", columnIndex); checkClosed(); @@ -2836,15 +2905,7 @@ public BigDecimal getMoney(int columnIndex) throws SQLServerException { return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param columnName - * is the name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null. - * @throws SQLServerException - * If any errors occur. - */ + @Override public BigDecimal getMoney(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMoney", columnName); checkClosed(); @@ -2853,15 +2914,7 @@ public BigDecimal getMoney(String columnName) throws SQLServerException { return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param columnIndex - * The zero-based ordinal of a column. - * @return the column value; if the value is SQL NULL, the value returned is null - * @throws SQLServerException - * If any errors occur. - */ + @Override public BigDecimal getSmallMoney(int columnIndex) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getSmallMoney", columnIndex); checkClosed(); @@ -2870,15 +2923,7 @@ public BigDecimal getSmallMoney(int columnIndex) throws SQLServerException { return value; } - /** - * Retrieves the value of the column specified as a java.math.BigDecimal object. - * - * @param columnName - * is the name of a column. - * @return the column value; if the value is SQL NULL, the value returned is null. - * @throws SQLServerException - * If any errors occur. - */ + @Override public BigDecimal getSmallMoney(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getSmallMoney", columnName); checkClosed(); @@ -2887,17 +2932,19 @@ public BigDecimal getSmallMoney(String columnName) throws SQLServerException { return value; } + @Override public RowId getRowId(int columnIndex) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); + return null; } + @Override public RowId getRowId(String columnLabel) throws SQLException { - - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); + return null; } + @Override public SQLXML getSQLXML(int columnIndex) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getSQLXML", columnIndex); SQLXML xml = getSQLXMLInternal(columnIndex); @@ -2905,6 +2952,7 @@ public SQLXML getSQLXML(int columnIndex) throws SQLException { return xml; } + @Override public SQLXML getSQLXML(String columnLabel) throws SQLException { loggerExternal.entering(getClassNameLogging(), "getSQLXML", columnLabel); SQLXML xml = getSQLXMLInternal(findColumn(columnLabel)); @@ -2912,6 +2960,7 @@ public SQLXML getSQLXML(String columnLabel) throws SQLException { return xml; } + @Override public boolean rowUpdated() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "rowUpdated"); checkClosed(); @@ -2925,6 +2974,7 @@ public boolean rowUpdated() throws SQLServerException { return false; } + @Override public boolean rowInserted() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "rowInserted"); checkClosed(); @@ -2939,6 +2989,7 @@ public boolean rowInserted() throws SQLServerException { return false; } + @Override public boolean rowDeleted() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "rowDeleted"); checkClosed(); @@ -3056,6 +3107,7 @@ private void updateSQLXMLInternal(int columnIndex, stmt.stmtColumnEncriptionSetting, null, false, columnIndex); } + @Override public void updateNull(int index) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "updateNull", index); @@ -3065,8 +3117,9 @@ public void updateNull(int index) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "updateNull"); } + @Override public void updateBoolean(int index, - boolean x) throws SQLServerException { + boolean x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateBoolean", new Object[] {index, x}); checkClosed(); @@ -3075,22 +3128,7 @@ public void updateBoolean(int index, loggerExternal.exiting(getClassNameLogging(), "updateBoolean"); } - /** - * Updates the designated column with a boolean value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateBoolean(int index, boolean x, boolean forceEncrypt) throws SQLServerException { @@ -3102,8 +3140,9 @@ public void updateBoolean(int index, loggerExternal.exiting(getClassNameLogging(), "updateBoolean"); } + @Override public void updateByte(int index, - byte x) throws SQLServerException { + byte x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateByte", new Object[] {index, x}); @@ -3113,22 +3152,7 @@ public void updateByte(int index, loggerExternal.exiting(getClassNameLogging(), "updateByte"); } - /** - * Updates the designated column with a byte value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateByte(int index, byte x, boolean forceEncrypt) throws SQLServerException { @@ -3141,8 +3165,9 @@ public void updateByte(int index, loggerExternal.exiting(getClassNameLogging(), "updateByte"); } + @Override public void updateShort(int index, - short x) throws SQLServerException { + short x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateShort", new Object[] {index, x}); @@ -3152,22 +3177,7 @@ public void updateShort(int index, loggerExternal.exiting(getClassNameLogging(), "updateShort"); } - /** - * Updates the designated column with a short value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateShort(int index, short x, boolean forceEncrypt) throws SQLServerException { @@ -3180,8 +3190,9 @@ public void updateShort(int index, loggerExternal.exiting(getClassNameLogging(), "updateShort"); } + @Override public void updateInt(int index, - int x) throws SQLServerException { + int x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateInt", new Object[] {index, x}); @@ -3191,22 +3202,7 @@ public void updateInt(int index, loggerExternal.exiting(getClassNameLogging(), "updateInt"); } - /** - * Updates the designated column with an int value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateInt(int index, int x, boolean forceEncrypt) throws SQLServerException { @@ -3219,8 +3215,9 @@ public void updateInt(int index, loggerExternal.exiting(getClassNameLogging(), "updateInt"); } + @Override public void updateLong(int index, - long x) throws SQLServerException { + long x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateLong", new Object[] {index, x}); @@ -3230,22 +3227,7 @@ public void updateLong(int index, loggerExternal.exiting(getClassNameLogging(), "updateLong"); } - /** - * Updates the designated column with a long value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateLong(int index, long x, boolean forceEncrypt) throws SQLServerException { @@ -3258,8 +3240,9 @@ public void updateLong(int index, loggerExternal.exiting(getClassNameLogging(), "updateLong"); } + @Override public void updateFloat(int index, - float x) throws SQLServerException { + float x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateFloat", new Object[] {index, x}); @@ -3269,22 +3252,7 @@ public void updateFloat(int index, loggerExternal.exiting(getClassNameLogging(), "updateFloat"); } - /** - * Updates the designated column with a float value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateFloat(int index, float x, boolean forceEncrypt) throws SQLServerException { @@ -3297,8 +3265,9 @@ public void updateFloat(int index, loggerExternal.exiting(getClassNameLogging(), "updateFloat"); } + @Override public void updateDouble(int index, - double x) throws SQLServerException { + double x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDouble", new Object[] {index, x}); @@ -3308,22 +3277,7 @@ public void updateDouble(int index, loggerExternal.exiting(getClassNameLogging(), "updateDouble"); } - /** - * Updates the designated column with a double value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateDouble(int index, double x, boolean forceEncrypt) throws SQLServerException { @@ -3336,18 +3290,7 @@ public void updateDouble(int index, loggerExternal.exiting(getClassNameLogging(), "updateDouble"); } - /** - * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateMoney(int index, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3358,22 +3301,7 @@ public void updateMoney(int index, loggerExternal.exiting(getClassNameLogging(), "updateMoney"); } - /** - * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateMoney(int index, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -3385,18 +3313,7 @@ public void updateMoney(int index, loggerExternal.exiting(getClassNameLogging(), "updateMoney"); } - /** - * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the column name - * @param x - * the new column value - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateMoney(String columnName, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3407,22 +3324,7 @@ public void updateMoney(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateMoney"); } - /** - * Updates the designated column with a money value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * the column name - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateMoney(String columnName, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -3434,18 +3336,7 @@ public void updateMoney(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateMoney"); } - /** - * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or - * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods - * are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateSmallMoney(int index, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3456,22 +3347,7 @@ public void updateSmallMoney(int index, loggerExternal.exiting(getClassNameLogging(), "updateSmallMoney"); } - /** - * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or - * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods - * are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateSmallMoney(int index, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -3483,18 +3359,7 @@ public void updateSmallMoney(int index, loggerExternal.exiting(getClassNameLogging(), "updateSmallMoney"); } - /** - * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or - * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods - * are called to update the database. - * - * @param columnName - * the column name - * @param x - * the new column value - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateSmallMoney(String columnName, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3505,22 +3370,7 @@ public void updateSmallMoney(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateSmallMoney"); } - /** - * Updates the designated column with a smallmoney value. The updater methods are used to update column values in the current row or - * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods - * are called to update the database. - * - * @param columnName - * the column name - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateSmallMoney(String columnName, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -3532,6 +3382,7 @@ public void updateSmallMoney(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateSmallMoney"); } + @Override public void updateBigDecimal(int index, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3543,22 +3394,7 @@ public void updateBigDecimal(int index, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } - /** - * Updates the designated column with a java.math.BigDecimal value. The updater methods are used to update column values in the - * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or - * insertRow methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateBigDecimal(int index, BigDecimal x, Integer precision, @@ -3572,26 +3408,7 @@ public void updateBigDecimal(int index, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } - /** - * Updates the designated column with a java.math.BigDecimal value. The updater methods are used to update column values in the - * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or - * insertRow methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateBigDecimal(int index, BigDecimal x, Integer precision, @@ -3606,6 +3423,7 @@ public void updateBigDecimal(int index, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } + @Override public void updateString(int columnIndex, String stringValue) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3617,22 +3435,7 @@ public void updateString(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateString"); } - /** - * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnIndex - * the first column is 1, the second is 2, ... - * @param stringValue - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateString(int columnIndex, String stringValue, boolean forceEncrypt) throws SQLServerException { @@ -3645,6 +3448,7 @@ public void updateString(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateString"); } + @Override public void updateNString(int columnIndex, String nString) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3656,26 +3460,10 @@ public void updateNString(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNString"); } - /** - * Updates the designated column with a String value. It is intended for use when updating NCHAR,NVARCHAR - * and LONGNVARCHAR columns. The updater methods are used to update column values in the current row or the insert row. The updater - * methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the - * database. - * - * @param columnIndex - * the first column is 1, the second 2, ... - * @param nString - * the value for the column to be updated - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public void updateNString(int columnIndex, String nString, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateNString", new Object[] {columnIndex, nString, forceEncrypt}); @@ -3685,6 +3473,7 @@ public void updateNString(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNString"); } + @Override public void updateNString(String columnLabel, String nString) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3696,27 +3485,10 @@ public void updateNString(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNString"); } - /** - * Updates the designated column with a String value. It is intended for use when updating NCHAR,NVARCHAR - * and LONGNVARCHAR columns. The updater methods are used to update column values in the current row or the insert row. The updater - * methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the - * database. - * - * @param columnLabel - * the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the - * column - * @param nString - * the value for the column to be updated - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public void updateNString(String columnLabel, String nString, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateNString", new Object[] {columnLabel, nString, forceEncrypt}); @@ -3726,8 +3498,9 @@ public void updateNString(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNString"); } + @Override public void updateBytes(int index, - byte x[]) throws SQLServerException { + byte x[]) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateBytes", new Object[] {index, x}); @@ -3737,22 +3510,7 @@ public void updateBytes(int index, loggerExternal.exiting(getClassNameLogging(), "updateBytes"); } - /** - * Updates the designated column with a byte array value. The updater methods are used to update column values in the current row or - * the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods - * are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateBytes(int index, byte x[], boolean forceEncrypt) throws SQLServerException { @@ -3765,6 +3523,7 @@ public void updateBytes(int index, loggerExternal.exiting(getClassNameLogging(), "updateBytes"); } + @Override public void updateDate(int index, java.sql.Date x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3776,22 +3535,7 @@ public void updateDate(int index, loggerExternal.exiting(getClassNameLogging(), "updateDate"); } - /** - * Updates the designated column with a java.sql.Date value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateDate(int index, java.sql.Date x, boolean forceEncrypt) throws SQLServerException { @@ -3804,6 +3548,7 @@ public void updateDate(int index, loggerExternal.exiting(getClassNameLogging(), "updateDate"); } + @Override public void updateTime(int index, java.sql.Time x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3815,20 +3560,7 @@ public void updateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } - /** - * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateTime(int index, java.sql.Time x, Integer scale) throws SQLServerException { @@ -3841,24 +3573,7 @@ public void updateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } - /** - * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateTime(int index, java.sql.Time x, Integer scale, @@ -3872,6 +3587,7 @@ public void updateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } + @Override public void updateTimestamp(int index, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3883,20 +3599,7 @@ public void updateTimestamp(int index, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateTimestamp(int index, java.sql.Timestamp x, int scale) throws SQLServerException { @@ -3909,24 +3612,7 @@ public void updateTimestamp(int index, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateTimestamp(int index, java.sql.Timestamp x, int scale, @@ -3940,18 +3626,7 @@ public void updateTimestamp(int index, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateDateTime(int index, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -3963,20 +3638,7 @@ public void updateDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateDateTime(int index, java.sql.Timestamp x, Integer scale) throws SQLServerException { @@ -3989,24 +3651,7 @@ public void updateDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateDateTime(int index, java.sql.Timestamp x, Integer scale, @@ -4020,18 +3665,7 @@ public void updateDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateSmallDateTime(int index, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4043,20 +3677,7 @@ public void updateSmallDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateSmallDateTime(int index, java.sql.Timestamp x, Integer scale) throws SQLServerException { @@ -4069,24 +3690,7 @@ public void updateSmallDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateSmallDateTime(int index, java.sql.Timestamp x, Integer scale, @@ -4100,8 +3704,9 @@ public void updateSmallDateTime(int index, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } + @Override public void updateDateTimeOffset(int index, - microsoft.sql.DateTimeOffset x) throws SQLException { + microsoft.sql.DateTimeOffset x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {index, x}); @@ -4111,21 +3716,10 @@ public void updateDateTimeOffset(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the value of the column specified to the DateTimeOffset Class value, given a zero-based column ordinal. - * - * @param index - * The zero-based ordinal of a column. - * @param x - * A DateTimeOffset Class object. - * @param scale - * scale of the column - * @throws SQLException - * when an error occurs - */ + @Override public void updateDateTimeOffset(int index, microsoft.sql.DateTimeOffset x, - Integer scale) throws SQLException { + Integer scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {index, x, scale}); @@ -4135,26 +3729,11 @@ public void updateDateTimeOffset(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the value of the column specified to the DateTimeOffset Class value, given a zero-based column ordinal. - * - * @param index - * The zero-based ordinal of a column. - * @param x - * A DateTimeOffset Class object. - * @param scale - * scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public void updateDateTimeOffset(int index, microsoft.sql.DateTimeOffset x, Integer scale, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {index, x, scale, forceEncrypt}); @@ -4164,20 +3743,9 @@ public void updateDateTimeOffset(int index, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * The zero-based ordinal of a column. - * @param x - * the new column value - * @throws SQLException - * when an error occurs - */ + @Override public void updateUniqueIdentifier(int index, - String x) throws SQLException { + String x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateUniqueIdentifier", new Object[] {index, x}); @@ -4187,25 +3755,10 @@ public void updateUniqueIdentifier(int index, loggerExternal.exiting(getClassNameLogging(), "updateUniqueIdentifier"); } - /** - * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param index - * The zero-based ordinal of a column. - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * when an error occurs - */ + @Override public void updateUniqueIdentifier(int index, String x, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateUniqueIdentifier", new Object[] {index, x, forceEncrypt}); @@ -4215,6 +3768,7 @@ public void updateUniqueIdentifier(int index, loggerExternal.exiting(getClassNameLogging(), "updateUniqueIdentifier"); } + @Override public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4226,8 +3780,9 @@ public void updateAsciiStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateAsciiStream(int index, - java.io.InputStream x, + InputStream x, int length) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateAsciiStream", new Object[] {index, x, length}); @@ -4238,6 +3793,7 @@ public void updateAsciiStream(int index, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { @@ -4249,6 +3805,7 @@ public void updateAsciiStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4260,8 +3817,9 @@ public void updateAsciiStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateAsciiStream(java.lang.String columnName, - java.io.InputStream x, + InputStream x, int length) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateAsciiStream", new Object[] {columnName, x, length}); @@ -4272,6 +3830,7 @@ public void updateAsciiStream(java.lang.String columnName, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateAsciiStream(String columnName, InputStream streamValue, long length) throws SQLException { @@ -4284,6 +3843,7 @@ public void updateAsciiStream(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateAsciiStream"); } + @Override public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4295,6 +3855,7 @@ public void updateBinaryStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateBinaryStream(int columnIndex, InputStream streamValue, int length) throws SQLException { @@ -4307,6 +3868,7 @@ public void updateBinaryStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { @@ -4319,6 +3881,7 @@ public void updateBinaryStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4330,6 +3893,7 @@ public void updateBinaryStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateBinaryStream(String columnName, InputStream streamValue, int length) throws SQLException { @@ -4342,6 +3906,7 @@ public void updateBinaryStream(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { @@ -4354,6 +3919,7 @@ public void updateBinaryStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateBinaryStream"); } + @Override public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4365,6 +3931,7 @@ public void updateCharacterStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateCharacterStream"); } + @Override public void updateCharacterStream(int columnIndex, Reader readerValue, int length) throws SQLServerException { @@ -4377,6 +3944,7 @@ public void updateCharacterStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateCharacterStream"); } + @Override public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { @@ -4389,6 +3957,7 @@ public void updateCharacterStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateCharacterStream"); } + @Override public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4400,6 +3969,7 @@ public void updateCharacterStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateCharacterStream"); } + @Override public void updateCharacterStream(String columnName, Reader readerValue, int length) throws SQLServerException { @@ -4412,6 +3982,7 @@ public void updateCharacterStream(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateCharacterStream"); } + @Override public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { @@ -4424,6 +3995,7 @@ public void updateCharacterStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNCharacterStream"); } + @Override public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4435,6 +4007,7 @@ public void updateNCharacterStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNCharacterStream"); } + @Override public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { @@ -4447,6 +4020,7 @@ public void updateNCharacterStream(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNCharacterStream"); } + @Override public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4458,6 +4032,7 @@ public void updateNCharacterStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNCharacterStream"); } + @Override public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { @@ -4470,6 +4045,7 @@ public void updateNCharacterStream(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNCharacterStream"); } + @Override public void updateObject(int index, Object obj) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4481,6 +4057,7 @@ public void updateObject(int index, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } + @Override public void updateObject(int index, Object x, int scale) throws SQLServerException { @@ -4493,23 +4070,7 @@ public void updateObject(int index, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } - /** - * Updates the designated column with an {@code Object} value. - * - * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying - * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateObject(int index, Object x, int precision, @@ -4523,27 +4084,7 @@ public void updateObject(int index, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } - /** - * Updates the designated column with an {@code Object} value. - * - * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying - * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. - * - * @param index - * the first column is 1, the second is 2, ... - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateObject(int index, Object x, int precision, @@ -4615,6 +4156,7 @@ protected final void updateObject(int index, } } + @Override public void updateNull(String columnName) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "updateNull", columnName); @@ -4625,6 +4167,7 @@ public void updateNull(String columnName) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "updateNull"); } + @Override public void updateBoolean(String columnName, boolean x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4636,22 +4179,7 @@ public void updateBoolean(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBoolean"); } - /** - * Updates the designated column with a boolean value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * when an error occurs - */ + @Override public void updateBoolean(String columnName, boolean x, boolean forceEncrypt) throws SQLServerException { @@ -4664,6 +4192,7 @@ public void updateBoolean(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBoolean"); } + @Override public void updateByte(String columnName, byte x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4675,23 +4204,7 @@ public void updateByte(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateByte"); } - /** - * Updates the designated column with a byte value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * - * @param columnName - * the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateByte(String columnName, byte x, boolean forceEncrypt) throws SQLServerException { @@ -4704,6 +4217,7 @@ public void updateByte(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateByte"); } + @Override public void updateShort(String columnName, short x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4715,22 +4229,7 @@ public void updateShort(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateShort"); } - /** - * Updates the designated column with a short value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateShort(String columnName, short x, boolean forceEncrypt) throws SQLServerException { @@ -4743,6 +4242,7 @@ public void updateShort(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateShort"); } + @Override public void updateInt(String columnName, int x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4754,22 +4254,7 @@ public void updateInt(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateInt"); } - /** - * Updates the designated column with an int value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateInt(String columnName, int x, boolean forceEncrypt) throws SQLServerException { @@ -4782,6 +4267,7 @@ public void updateInt(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateInt"); } + @Override public void updateLong(String columnName, long x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4793,22 +4279,7 @@ public void updateLong(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateLong"); } - /** - * Updates the designated column with a long value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateLong(String columnName, long x, boolean forceEncrypt) throws SQLServerException { @@ -4821,6 +4292,7 @@ public void updateLong(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateLong"); } + @Override public void updateFloat(String columnName, float x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4832,22 +4304,7 @@ public void updateFloat(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateFloat"); } - /** - * Updates the designated column with a float value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateFloat(String columnName, float x, boolean forceEncrypt) throws SQLServerException { @@ -4860,6 +4317,7 @@ public void updateFloat(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateFloat"); } + @Override public void updateDouble(String columnName, double x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4871,22 +4329,7 @@ public void updateDouble(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDouble"); } - /** - * Updates the designated column with a double value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDouble(String columnName, double x, boolean forceEncrypt) throws SQLServerException { @@ -4899,6 +4342,7 @@ public void updateDouble(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDouble"); } + @Override public void updateBigDecimal(String columnName, BigDecimal x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -4910,22 +4354,7 @@ public void updateBigDecimal(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } - /** - * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the - * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or - * insertRow methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateBigDecimal(String columnName, BigDecimal x, boolean forceEncrypt) throws SQLServerException { @@ -4938,23 +4367,7 @@ public void updateBigDecimal(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } - /** - * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the - * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or - * insertRow methods are called to update the database. - * - * @param columnName - * is the name of the column and Always Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set - * to false, the driver will not force encryption on parameters. - * @param x - * BigDecimal value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateBigDecimal(String columnName, BigDecimal x, Integer precision, @@ -4968,27 +4381,7 @@ public void updateBigDecimal(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } - /** - * Updates the designated column with a java.sql.BigDecimal value. The updater methods are used to update column values in the - * current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or - * insertRow methods are called to update the database. - * - * @param columnName - * is the name of the column and Always Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set - * to false, the driver will not force encryption on parameters. - * @param x - * BigDecimal value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateBigDecimal(String columnName, BigDecimal x, Integer precision, @@ -5003,6 +4396,7 @@ public void updateBigDecimal(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBigDecimal"); } + @Override public void updateString(String columnName, String x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5014,22 +4408,7 @@ public void updateString(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateString"); } - /** - * Updates the designated column with a String value. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateString(String columnName, String x, boolean forceEncrypt) throws SQLServerException { @@ -5042,6 +4421,7 @@ public void updateString(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateString"); } + @Override public void updateBytes(String columnName, byte x[]) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5053,23 +4433,7 @@ public void updateBytes(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBytes"); } - /** - * Updates the designated column with a byte array value. - * - * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying - * database; instead the updateRow or insertRow methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateBytes(String columnName, byte x[], boolean forceEncrypt) throws SQLServerException { @@ -5082,6 +4446,7 @@ public void updateBytes(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBytes"); } + @Override public void updateDate(String columnName, java.sql.Date x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5093,22 +4458,7 @@ public void updateDate(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDate"); } - /** - * Updates the designated column with a java.sql.Date value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDate(String columnName, java.sql.Date x, boolean forceEncrypt) throws SQLServerException { @@ -5121,6 +4471,7 @@ public void updateDate(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDate"); } + @Override public void updateTime(String columnName, java.sql.Time x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5132,20 +4483,7 @@ public void updateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } - /** - * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateTime(String columnName, java.sql.Time x, int scale) throws SQLServerException { @@ -5158,24 +4496,7 @@ public void updateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } - /** - * Updates the designated column with a java.sql.Time value. The updater methods are used to update column values in the current row - * or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateTime(String columnName, java.sql.Time x, int scale, @@ -5189,6 +4510,7 @@ public void updateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTime"); } + @Override public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5200,20 +4522,7 @@ public void updateTimestamp(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateTimestamp(String columnName, java.sql.Timestamp x, int scale) throws SQLServerException { @@ -5226,24 +4535,7 @@ public void updateTimestamp(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateTimestamp(String columnName, java.sql.Timestamp x, int scale, @@ -5257,18 +4549,7 @@ public void updateTimestamp(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateTimestamp"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDateTime(String columnName, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5280,20 +4561,7 @@ public void updateDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDateTime(String columnName, java.sql.Timestamp x, int scale) throws SQLServerException { @@ -5306,24 +4574,7 @@ public void updateDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDateTime(String columnName, java.sql.Timestamp x, int scale, @@ -5337,18 +4588,7 @@ public void updateDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateSmallDateTime(String columnName, java.sql.Timestamp x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5360,20 +4600,7 @@ public void updateSmallDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateSmallDateTime(String columnName, java.sql.Timestamp x, int scale) throws SQLServerException { @@ -5386,24 +4613,7 @@ public void updateSmallDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } - /** - * Updates the designated column with a java.sql.Timestamp value. The updater methods are used to update column values in the current - * row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow - * methods are called to update the database. - * - * @param columnName - * is the name of the column - * @param x - * the new column value - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateSmallDateTime(String columnName, java.sql.Timestamp x, int scale, @@ -5417,8 +4627,9 @@ public void updateSmallDateTime(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateSmallDateTime"); } + @Override public void updateDateTimeOffset(String columnName, - microsoft.sql.DateTimeOffset x) throws SQLException { + microsoft.sql.DateTimeOffset x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {columnName, x}); @@ -5428,21 +4639,10 @@ public void updateDateTimeOffset(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the value of the column specified to the DateTimeOffset Class value, given a column name. - * - * @param columnName - * The name of a column. - * @param x - * A DateTimeOffset Class object. - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateDateTimeOffset(String columnName, microsoft.sql.DateTimeOffset x, - int scale) throws SQLException { + int scale) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {columnName, x, scale}); @@ -5452,26 +4652,11 @@ public void updateDateTimeOffset(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the value of the column specified to the DateTimeOffset Class value, given a column name. - * - * @param columnName - * The name of a column. - * @param x - * A DateTimeOffset Class object. - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * If any errors occur. - */ + @Override public void updateDateTimeOffset(String columnName, microsoft.sql.DateTimeOffset x, int scale, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateDateTimeOffset", new Object[] {columnName, x, scale, forceEncrypt}); @@ -5481,20 +4666,9 @@ public void updateDateTimeOffset(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateDateTimeOffset"); } - /** - * Updates the designated column with a Stringvalue. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * The name of a column. - * @param x - * the new column value - * @throws SQLException - * If any errors occur. - */ + @Override public void updateUniqueIdentifier(String columnName, - String x) throws SQLException { + String x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateUniqueIdentifier", new Object[] {columnName, x}); @@ -5504,25 +4678,10 @@ public void updateUniqueIdentifier(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateUniqueIdentifier"); } - /** - * Updates the designated column with a Stringvalue. The updater methods are used to update column values in the current row or the - * insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are - * called to update the database. - * - * @param columnName - * The name of a column. - * @param x - * the new column value - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLException - * If any errors occur. - */ + @Override public void updateUniqueIdentifier(String columnName, String x, - boolean forceEncrypt) throws SQLException { + boolean forceEncrypt) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "updateUniqueIdentifier", new Object[] {columnName, x, forceEncrypt}); @@ -5532,6 +4691,7 @@ public void updateUniqueIdentifier(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateUniqueIdentifier"); } + @Override public void updateObject(String columnName, Object x, int scale) throws SQLServerException { @@ -5544,23 +4704,7 @@ public void updateObject(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } - /** - * Updates the designated column with an {@code Object} value. - * - * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying - * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. - * - * @param columnName - * The name of a column. - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateObject(String columnName, Object x, int precision, @@ -5574,27 +4718,7 @@ public void updateObject(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } - /** - * Updates the designated column with an {@code Object} value. - * - * The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying - * database; instead the {@code updateRow} or {@code insertRow} methods are called to update the database. - * - * @param columnName - * The name of a column. - * @param x - * the new column value - * @param precision - * the precision of the column - * @param scale - * the scale of the column - * @param forceEncrypt - * If the boolean forceEncrypt is set to true, the query parameter will only be set if the designation column is encrypted and Always - * Encrypted is enabled on the connection or on the statement. If the boolean forceEncrypt is set to false, the driver will not force - * encryption on parameters. - * @throws SQLServerException - * If any errors occur. - */ + @Override public void updateObject(String columnName, Object x, int precision, @@ -5609,6 +4733,7 @@ public void updateObject(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } + @Override public void updateObject(String columnName, Object x) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5620,18 +4745,19 @@ public void updateObject(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateObject"); } + @Override public void updateRowId(int columnIndex, RowId x) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } + @Override public void updateRowId(String columnLabel, RowId x) throws SQLException { - // Not implemented - throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported")); + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } + @Override public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5640,6 +4766,7 @@ public void updateSQLXML(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateSQLXML"); } + @Override public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -5648,6 +4775,7 @@ public void updateSQLXML(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateSQLXML"); } + @Override public int getHoldability() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getHoldability"); @@ -5671,7 +4799,8 @@ public int getHoldability() throws SQLException { /* ----------------------- Update result set ------------------------- */ - public void insertRow() throws SQLServerException { + @Override + public void insertRow() throws SQLException { loggerExternal.entering(getClassNameLogging(), "insertRow"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -5762,7 +4891,8 @@ private void doInsertRowRPC(TDSCommand command, if (hasUpdatedColumns()) { tdsWriter.writeRPCStringUnicode(tableName); - for (Column column : columns) column.sendByRPC(tdsWriter, stmt.connection); + for (Column column : columns) + column.sendByRPC(tdsWriter, stmt.connection); } else { tdsWriter.writeRPCStringUnicode(""); @@ -5772,7 +4902,8 @@ private void doInsertRowRPC(TDSCommand command, TDSParser.parse(command.startResponse(), command.getLogContext()); } - public void updateRow() throws SQLServerException { + @Override + public void updateRow() throws SQLException { loggerExternal.entering(getClassNameLogging(), "updateRow"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -5836,7 +4967,8 @@ private void doUpdateRowRPC(TDSCommand command) throws SQLServerException { assert hasUpdatedColumns(); - for (Column column : columns) column.sendByRPC(tdsWriter, stmt.connection); + for (Column column : columns) + column.sendByRPC(tdsWriter, stmt.connection); TDSParser.parse(command.startResponse(), command.getLogContext()); } @@ -5850,7 +4982,8 @@ final boolean hasUpdatedColumns() { return false; } - public void deleteRow() throws SQLServerException { + @Override + public void deleteRow() throws SQLException { loggerExternal.entering(getClassNameLogging(), "deleteRow"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -5909,7 +5042,8 @@ private void doDeleteRowRPC(TDSCommand command) throws SQLServerException { TDSParser.parse(command.startResponse(), command.getLogContext()); } - public void refreshRow() throws SQLServerException { + @Override + public void refreshRow() throws SQLException { loggerExternal.entering(getClassNameLogging(), "refreshRow"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); @@ -5988,6 +5122,7 @@ private void cancelUpdates() { clearColumnsValues(); } + @Override public void cancelRowUpdates() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "cancelRowUpdates"); checkClosed(); @@ -6002,6 +5137,7 @@ public void cancelRowUpdates() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "cancelRowUpdates"); } + @Override public void moveToInsertRow() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "moveToInsertRow"); if (logger.isLoggable(java.util.logging.Level.FINER)) @@ -6018,6 +5154,7 @@ public void moveToInsertRow() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "moveToInsertRow"); } + @Override public void moveToCurrentRow() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "moveToCurrentRow"); if (logger.isLoggable(java.util.logging.Level.FINER)) @@ -6038,7 +5175,8 @@ public void moveToCurrentRow() throws SQLServerException { } - /* L0 */ public java.sql.Statement getStatement() throws SQLServerException { + @Override + public java.sql.Statement getStatement() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getStatement"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getStatement", stmt); @@ -6047,6 +5185,7 @@ public void moveToCurrentRow() throws SQLServerException { /* JDBC 3.0 */ + @Override public void updateClob(int columnIndex, Clob clobValue) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6058,6 +5197,7 @@ public void updateClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateClob(int columnIndex, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6069,6 +5209,7 @@ public void updateClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { @@ -6081,6 +5222,7 @@ public void updateClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateClob(String columnName, Clob clobValue) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6092,6 +5234,7 @@ public void updateClob(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateClob(String columnLabel, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6103,6 +5246,7 @@ public void updateClob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { @@ -6115,6 +5259,7 @@ public void updateClob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateClob"); } + @Override public void updateNClob(int columnIndex, NClob nClob) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6126,6 +5271,7 @@ public void updateNClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateNClob(int columnIndex, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6137,6 +5283,7 @@ public void updateNClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { @@ -6149,6 +5296,7 @@ public void updateNClob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateNClob(String columnLabel, NClob nClob) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6160,6 +5308,7 @@ public void updateNClob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateNClob(String columnLabel, Reader reader) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6171,6 +5320,7 @@ public void updateNClob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { @@ -6183,6 +5333,7 @@ public void updateNClob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateNClob"); } + @Override public void updateBlob(int columnIndex, Blob blobValue) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6194,6 +5345,7 @@ public void updateBlob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } + @Override public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6205,6 +5357,7 @@ public void updateBlob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } + @Override public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { @@ -6217,6 +5370,7 @@ public void updateBlob(int columnIndex, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } + @Override public void updateBlob(String columnName, Blob blobValue) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6228,6 +5382,7 @@ public void updateBlob(String columnName, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } + @Override public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -6239,6 +5394,7 @@ public void updateBlob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } + @Override public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { @@ -6251,33 +5407,39 @@ public void updateBlob(String columnLabel, loggerExternal.exiting(getClassNameLogging(), "updateBlob"); } - /* L3 */ public void updateArray(int columnIndex, - Array x) throws SQLServerException { - stmt.NotImplemented(); + @Override + public void updateArray(int columnIndex, + Array x) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } - /* L3 */ public void updateArray(java.lang.String columnName, - Array x) throws SQLServerException { - stmt.NotImplemented(); + @Override + public void updateArray(java.lang.String columnName, + Array x) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } - /* L3 */ public void updateRef(int columnIndex, - Ref x) throws SQLServerException { - stmt.NotImplemented(); + @Override + public void updateRef(int columnIndex, + Ref x) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } - /* L3 */ public void updateRef(java.lang.String columnName, - Ref x) throws SQLServerException { - stmt.NotImplemented(); + @Override + public void updateRef(java.lang.String columnName, + Ref x) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); } - /* L3 */ public java.net.URL getURL(int columnIndex) throws SQLServerException { - stmt.NotImplemented(); + @Override + public java.net.URL getURL(int columnIndex) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } - /* L3 */ public java.net.URL getURL(String sColumn) throws SQLServerException { - stmt.NotImplemented(); + @Override + public java.net.URL getURL(String sColumn) throws SQLException { + SQLServerException.throwNotSupportedException(stmt.connection, stmt); return null; } @@ -6341,16 +5503,16 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { int token = tdsReader.peekTokenType(); StreamDone doneToken = new StreamDone(); doneToken.setFromTDS(tdsReader); - + int packetType = tdsReader.peekTokenType(); if (-1 != packetType && TDS.TDS_DONEINPROC == token) { - switch (packetType) { - case TDS.TDS_ENV_CHG: - case TDS.TDS_ERR: - return true; - default: - break; - } + switch (packetType) { + case TDS.TDS_ENV_CHG: + case TDS.TDS_ERR: + return true; + default: + break; + } } // Done with all the rows in this fetch buffer and done with parsing @@ -6561,24 +5723,26 @@ final void doServerFetch(int fetchType, scrollWindow.reset(); } } - + /* - * Checks for any LOBs which need to be available after the RS is closed, and loads their contents from stream into memory. - * Closed LOBs will not be populated. + * Checks for any LOBs which need to be available after the RS is closed, and loads their contents from stream into memory. Closed LOBs will not + * be populated. */ private void fillLOBs() { - if (null != activeLOB) { - try { - activeLOB.fillFromStream(); - } catch (SQLException e) { - if (logger.isLoggable(java.util.logging.Level.FINER)) { - logger.finer(toString() + "Filling Lobs before closing: " + e.getMessage()); - } - } finally { - activeLOB = null; - } - } - } + if (null != activeLOB) { + try { + activeLOB.fillFromStream(); + } + catch (SQLException e) { + if (logger.isLoggable(java.util.logging.Level.FINER)) { + logger.finer(toString() + "Filling Lobs before closing: " + e.getMessage()); + } + } + finally { + activeLOB = null; + } + } + } /** * Discards the contents of the current fetch buffer. @@ -6591,8 +5755,8 @@ private void fillLOBs() { * fetch buffer is considered to be discarded. */ private void discardFetchBuffer() { - //fills blobs before discarding anything - fillLOBs(); + // fills blobs before discarding anything + fillLOBs(); // Clear the TDSReader mark at the start of the fetch buffer fetchBuffer.clearStartMark(); @@ -6662,4 +5826,104 @@ final boolean doExecute() throws SQLServerException { logger.finer(toString() + " Closed cursor:" + serverCursorId); } } + + @Override + public void updateObject(int index, + Object obj, + SQLType targetSqlType) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType}); + + checkClosed(); + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(index, obj, null, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + + @Override + public void updateObject(int index, + Object obj, + SQLType targetSqlType, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType, scale}); + + checkClosed(); + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(index, obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + + @Override + public void updateObject(int index, + Object obj, + SQLType targetSqlType, + int scale, + boolean forceEncrypt) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType, scale, forceEncrypt}); + + checkClosed(); + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(index, obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, forceEncrypt); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + + @Override + public void updateObject(String columnName, + Object obj, + SQLType targetSqlType, + int scale) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType, scale}); + + checkClosed(); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(findColumn(columnName), obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + + @Override + public void updateObject(String columnName, + Object obj, + SQLType targetSqlType, + int scale, + boolean forceEncrypt) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType, scale, forceEncrypt}); + + checkClosed(); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(findColumn(columnName), obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, forceEncrypt); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + + @Override + public void updateObject(String columnName, + Object obj, + SQLType targetSqlType) throws SQLServerException { + + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType}); + + checkClosed(); + + // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types + updateObject(findColumn(columnName), obj, null, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); + + loggerExternal.exiting(getClassNameLogging(), "updateObject"); + } + } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet42.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet42.java deleted file mode 100644 index cc900e65f..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet42.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) Microsoft Corporation All rights reserved. - * - * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.sql.SQLType; - -/** - * - * This class is separated from SQLServerResultSet class in order to resolve compiling error of missing Java 8 Types when running with Java 7. - * - * This class will be initialized instead of SQLServerResultSet when Java 8 and JDBC 4.2 are used. - * - */ -public class SQLServerResultSet42 extends SQLServerResultSet implements ISQLServerResultSet42 { - - /** - * Makes a new result set - * - * @param stmtIn - * the generating statement - * @throws SQLServerException - * when an error occurs - */ - public SQLServerResultSet42(SQLServerStatement stmtIn) throws SQLServerException { - super(stmtIn); - } - - public void updateObject(int index, - Object obj, - SQLType targetSqlType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType}); - - checkClosed(); - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(index, obj, null, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - - public void updateObject(int index, - Object obj, - SQLType targetSqlType, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType, scale}); - - checkClosed(); - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(index, obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - - public void updateObject(int index, - Object obj, - SQLType targetSqlType, - int scale, - boolean forceEncrypt) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {index, obj, targetSqlType, scale, forceEncrypt}); - - checkClosed(); - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(index, obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, forceEncrypt); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType, - int scale) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType, scale}); - - checkClosed(); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(findColumn(columnName), obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType, - int scale, - boolean forceEncrypt) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType, scale, forceEncrypt}); - - checkClosed(); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(findColumn(columnName), obj, scale, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, forceEncrypt); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - - public void updateObject(String columnName, - Object obj, - SQLType targetSqlType) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); - - if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) - loggerExternal.entering(getClassNameLogging(), "updateObject", new Object[] {columnName, obj, targetSqlType}); - - checkClosed(); - - // getVendorTypeNumber() returns the same constant integer values as in java.sql.Types - updateObject(findColumn(columnName), obj, null, JDBCType.of(targetSqlType.getVendorTypeNumber()), null, false); - - loggerExternal.exiting(getClassNameLogging(), "updateObject"); - } - -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java index c9aa686a6..e3b7679fa 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java @@ -18,7 +18,7 @@ * details. */ -public final class SQLServerResultSetMetaData implements java.sql.ResultSetMetaData { +public final class SQLServerResultSetMetaData implements ISQLServerResultSetMetaData { private SQLServerConnection con; private final SQLServerResultSet rs; static final private java.util.logging.Logger logger = java.util.logging.Logger @@ -44,7 +44,7 @@ final public String toString() { * @param rs * the parent result set */ - /* L0 */ SQLServerResultSetMetaData(SQLServerConnection con, + SQLServerResultSetMetaData(SQLServerConnection con, SQLServerResultSet rs) { traceID = " SQLServerResultSetMetaData:" + nextInstanceID(); this.con = con; @@ -57,11 +57,13 @@ final public String toString() { /* ------------------ JDBC API Methods --------------------- */ + @Override public boolean isWrapperFor(Class iface) throws SQLException { boolean f = iface.isInstance(this); return f; } + @Override public T unwrap(Class iface) throws SQLException { T t; try { @@ -73,14 +75,17 @@ public T unwrap(Class iface) throws SQLException { return t; } + @Override public String getCatalogName(int column) throws SQLServerException { return rs.getColumn(column).getTableName().getDatabaseName(); } - /* L0 */ public int getColumnCount() throws SQLServerException { + @Override + public int getColumnCount() throws SQLServerException { return rs.getColumnCount(); } + @Override public int getColumnDisplaySize(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -90,14 +95,17 @@ public int getColumnDisplaySize(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().getDisplaySize(); } + @Override public String getColumnLabel(int column) throws SQLServerException { return rs.getColumn(column).getColumnName(); } + @Override public String getColumnName(int column) throws SQLServerException { return rs.getColumn(column).getColumnName(); } + @Override public int getColumnType(int column) throws SQLServerException { // under Katmai map the max types to non max to be inline with DBMD. TypeInfo typeInfo = rs.getColumn(column).getTypeInfo(); @@ -152,6 +160,7 @@ public int getColumnType(int column) throws SQLServerException { return r; } + @Override public String getColumnTypeName(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -161,6 +170,7 @@ public String getColumnTypeName(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().getSSTypeName(); } + @Override public int getPrecision(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -170,6 +180,7 @@ public int getPrecision(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().getPrecision(); } + @Override public int getScale(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -179,14 +190,17 @@ public int getScale(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().getScale(); } + @Override public String getSchemaName(int column) throws SQLServerException { return rs.getColumn(column).getTableName().getSchemaName(); } + @Override public String getTableName(int column) throws SQLServerException { return rs.getColumn(column).getTableName().getObjectName(); } + @Override public boolean isAutoIncrement(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -196,6 +210,7 @@ public boolean isAutoIncrement(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().isIdentity(); } + @Override public boolean isCaseSensitive(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -205,6 +220,7 @@ public boolean isCaseSensitive(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().isCaseSensitive(); } + @Override public boolean isCurrency(int column) throws SQLServerException { SSType ssType = rs.getColumn(column).getTypeInfo().getSSType(); @@ -216,6 +232,7 @@ public boolean isCurrency(int column) throws SQLServerException { return SSType.MONEY == ssType || SSType.SMALLMONEY == ssType; } + @Override public boolean isDefinitelyWritable(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -225,6 +242,7 @@ public boolean isDefinitelyWritable(int column) throws SQLServerException { return TypeInfo.UPDATABLE_READ_WRITE == rs.getColumn(column).getTypeInfo().getUpdatability(); } + @Override public int isNullable(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -234,6 +252,7 @@ public int isNullable(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().isNullable() ? columnNullable : columnNoNulls; } + @Override public boolean isReadOnly(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -243,6 +262,7 @@ public boolean isReadOnly(int column) throws SQLServerException { return TypeInfo.UPDATABLE_READ_ONLY == rs.getColumn(column).getTypeInfo().getUpdatability(); } + @Override public boolean isSearchable(int column) throws SQLServerException { SSType ssType = null; CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); @@ -267,6 +287,7 @@ public boolean isSearchable(int column) throws SQLServerException { } } + @Override public boolean isSigned(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -276,15 +297,7 @@ public boolean isSigned(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().getSSType().getJDBCType().isSigned(); } - /** - * Returns true if the column is a SQLServer SparseColumnSet - * - * @param column - * The column number - * @return true if a column in a result set is a sparse column set, otherwise false. - * @throws SQLServerException - * when an error occurs - */ + @Override public boolean isSparseColumnSet(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { @@ -294,6 +307,7 @@ public boolean isSparseColumnSet(int column) throws SQLServerException { return rs.getColumn(column).getTypeInfo().isSparseColumnSet(); } + @Override public boolean isWritable(int column) throws SQLServerException { int updatability = -1; CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); @@ -306,6 +320,7 @@ public boolean isWritable(int column) throws SQLServerException { return TypeInfo.UPDATABLE_READ_WRITE == updatability || TypeInfo.UPDATABLE_UNKNOWN == updatability; } + @Override public String getColumnClassName(int column) throws SQLServerException { CryptoMetadata cryptoMetadata = rs.getColumn(column).getCryptoMetadata(); if (null != cryptoMetadata) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java index 3e99ab41f..da860456a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java @@ -158,7 +158,8 @@ else if (null != docValue) { InputStream getStream() { return contents; } - + + @Override public void free() throws SQLException { if (!isFreed) { isFreed = true; @@ -209,6 +210,7 @@ void checkWriteXML() throws SQLException { * when an error occurs * @return the input stream to that contains the SQLXML data */ + @Override public InputStream getBinaryStream() throws SQLException { checkClosed(); checkReadXML(); @@ -224,6 +226,7 @@ public InputStream getBinaryStream() throws SQLException { * when an error occurs * @return OutputStream */ + @Override public java.io.OutputStream setBinaryStream() throws SQLException { checkClosed(); checkWriteXML(); @@ -232,6 +235,7 @@ public java.io.OutputStream setBinaryStream() throws SQLException { return outputStreamValue; } + @Override public java.io.Writer setCharacterStream() throws SQLException { checkClosed(); checkWriteXML(); @@ -240,6 +244,7 @@ public java.io.Writer setCharacterStream() throws SQLException { return new OutputStreamWriter(outputStreamValue, Encoding.UNICODE.charset()); } + @Override public Reader getCharacterStream() throws SQLException { checkClosed(); checkReadXML(); @@ -261,6 +266,7 @@ public Reader getCharacterStream() throws SQLException { return rd; } + @Override public String getString() throws SQLException { checkClosed(); checkReadXML(); @@ -279,6 +285,7 @@ public String getString() throws SQLException { return new String(byteContents, 0, byteContents.length, Encoding.UNICODE.charset()); } + @Override public void setString(String value) throws SQLException { checkClosed(); checkWriteXML(); @@ -289,6 +296,7 @@ public void setString(String value) throws SQLException { } // Support the following DOMSource, SAXSource, StAX and Stream. Also, null means default which is stream source + @Override public T getSource(Class iface) throws SQLException { checkClosed(); checkReadXML(); @@ -324,6 +332,7 @@ else if (StreamSource.class == iface) { return src; } + @Override public T setResult(Class resultClass) throws SQLException { checkClosed(); checkWriteXML(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java index 9c0b62ed8..0d10816f5 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java @@ -8,7 +8,6 @@ package com.microsoft.sqlserver.jdbc; -import java.sql.Savepoint; import java.text.MessageFormat; /** @@ -19,7 +18,7 @@ * details. */ -public final class SQLServerSavepoint implements Savepoint { +public final class SQLServerSavepoint implements ISQLServerSavepoint { private final String sName; private final int nId; private final SQLServerConnection con; @@ -45,17 +44,14 @@ public SQLServerSavepoint(SQLServerConnection con, } } + @Override public String getSavepointName() throws SQLServerException { if (sName == null) SQLServerException.makeFromDriverError(con, null, SQLServerException.getErrString("R_savepointNotNamed"), null, false); return sName; } - /** - * Get the savepoint label - * - * @return the name - */ + @Override public String getLabel() { if (sName == null) return "S" + nId; @@ -63,15 +59,12 @@ public String getLabel() { return sName; } - /** - * Checks if the savepoint label is null - * - * @return true is the savepoint is named. Otherwise, false. - */ + @Override public boolean isNamed() { return sName != null; } + @Override public int getSavepointId() throws SQLServerException { if (sName != null) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_savepointNamed")); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java index a5256aa10..4c75590c3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java @@ -10,15 +10,18 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; abstract class SQLServerSpatialDatatype { - - /**WKT = Well-Known-Text, WKB = Well-Knwon-Binary */ - /**As a general rule, the ~IndexEnd variables are non-inclusive (i.e. pointIndexEnd = 8 means the shape using it will - * only go up to the 7th index of the array) */ + + /** WKT = Well-Known-Text, WKB = Well-Knwon-Binary */ + /** + * As a general rule, the ~IndexEnd variables are non-inclusive (i.e. pointIndexEnd = 8 means the shape using it will only go up to the 7th index + * of the array) + */ protected ByteBuffer buffer; protected InternalSpatialDatatype internalType; protected String wkt; @@ -44,7 +47,7 @@ abstract class SQLServerSpatialDatatype { protected Shape shapes[]; protected Segment segments[]; - //serialization properties + // serialization properties protected boolean hasZvalues = false; protected boolean hasMvalues = false; protected boolean isValid = false; @@ -52,16 +55,16 @@ abstract class SQLServerSpatialDatatype { protected boolean isSingleLineSegment = false; protected boolean isLargerThanHemisphere = false; protected boolean isNull = true; - + protected final byte FA_INTERIOR_RING = 0; protected final byte FA_STROKE = 1; protected final byte FA_EXTERIOR_RING = 2; - + protected final byte FA_POINT = 0; protected final byte FA_LINE = 1; protected final byte FA_ARC = 2; protected final byte FA_COMPOSITE_CURVE = 3; - + // WKT to WKB properties protected int currentWktPos = 0; protected List pointList = new ArrayList(); @@ -69,52 +72,67 @@ abstract class SQLServerSpatialDatatype { protected List shapeList = new ArrayList(); protected List segmentList = new ArrayList(); protected byte serializationProperties = 0; - + private final byte SEGMENT_LINE = 0; private final byte SEGMENT_ARC = 1; private final byte SEGMENT_FIRST_LINE = 2; private final byte SEGMENT_FIRST_ARC = 3; - - private final byte hasZvaluesMask = 0b00000001; - private final byte hasMvaluesMask = 0b00000010; - private final byte isValidMask = 0b00000100; - private final byte isSinglePointMask = 0b00001000; - private final byte isSingleLineSegmentMask = 0b00010000; - private final byte isLargerThanHemisphereMask = 0b00100000; - + + private final byte hasZvaluesMask = 0b00000001; + private final byte hasMvaluesMask = 0b00000010; + private final byte isValidMask = 0b00000100; + private final byte isSinglePointMask = 0b00001000; + private final byte isSingleLineSegmentMask = 0b00010000; + private final byte isLargerThanHemisphereMask = 0b00100000; + private List version_one_shape_indexes = new ArrayList(); - + /** * Serializes the Geogemetry/Geography instance to WKB. * - * @param noZM flag to indicate if Z and M coordinates should be included + * @param noZM + * flag to indicate if Z and M coordinates should be included */ protected abstract void serializeToWkb(boolean noZM); - + /** - * Deserialize the buffer (that contains WKB representation of Geometry/Geography data), and stores it - * into multiple corresponding data structures. + * Deserialize the buffer (that contains WKB representation of Geometry/Geography data), and stores it into multiple corresponding data + * structures. * */ protected abstract void parseWkb(); - + /** * Create the WKT representation of Geometry/Geography from the deserialized data. * - * @param sd the Geometry/Geography instance. - * @param isd internal spatial datatype object - * @param pointIndexEnd upper bound for reading points - * @param figureIndexEnd upper bound for reading figures - * @param segmentIndexEnd upper bound for reading segments - * @param shapeIndexEnd upper bound for reading shapes + * @param sd + * the Geometry/Geography instance. + * @param isd + * internal spatial datatype object + * @param pointIndexEnd + * upper bound for reading points + * @param figureIndexEnd + * upper bound for reading figures + * @param segmentIndexEnd + * upper bound for reading segments + * @param shapeIndexEnd + * upper bound for reading shapes + * @throws SQLServerException + * if an exception occurs */ - protected void constructWKT(SQLServerSpatialDatatype sd, InternalSpatialDatatype isd, int pointIndexEnd, int figureIndexEnd, - int segmentIndexEnd, int shapeIndexEnd) { + protected void constructWKT(SQLServerSpatialDatatype sd, + InternalSpatialDatatype isd, + int pointIndexEnd, + int figureIndexEnd, + int segmentIndexEnd, + int shapeIndexEnd) throws SQLServerException { if (null == points || numberOfPoints == 0) { if (isd.getTypeCode() == 11) { // FULLGLOBE if (sd instanceof Geometry) { - throw new IllegalArgumentException("Fullglobe is not supported for Geometry."); - } else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalTypeForGeometry")); + throw new SQLServerException(form.format(new Object[] {"Fullglobe"}), null, 0, null); + } + else { appendToWKTBuffers("FULLGLOBE"); return; } @@ -123,15 +141,15 @@ protected void constructWKT(SQLServerSpatialDatatype sd, InternalSpatialDatatype if (isd.getTypeCode() == 7 && currentShapeIndex != shapeIndexEnd - 1) { currentShapeIndex++; appendToWKTBuffers(isd.getTypeName() + "("); - constructWKT(this, InternalSpatialDatatype.valueOf(shapes[currentShapeIndex].getOpenGISType()), - numberOfPoints, numberOfFigures, numberOfSegments, numberOfShapes); + constructWKT(this, InternalSpatialDatatype.valueOf(shapes[currentShapeIndex].getOpenGISType()), numberOfPoints, numberOfFigures, + numberOfSegments, numberOfShapes); appendToWKTBuffers(")"); - return; + return; } appendToWKTBuffers(isd.getTypeName() + " EMPTY"); return; } - + appendToWKTBuffers(isd.getTypeName()); appendToWKTBuffers("("); @@ -163,31 +181,42 @@ protected void constructWKT(SQLServerSpatialDatatype sd, InternalSpatialDatatype constructCurvepolygonWKT(currentFigureIndex, figureIndexEnd, currentSegmentIndex, segmentIndexEnd); break; default: - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } - + appendToWKTBuffers(")"); } - + /** * Parses WKT and populates the data structures of the Geometry/Geography instance. * - * @param sd the Geometry/Geography instance. - * @param startPos The index to start from from the WKT. - * @param parentShapeIndex The index of the parent's Shape in the shapes array. Used to determine this shape's parent. - * @param isGeoCollection flag to indicate if this is part of a GeometryCollection. + * @param sd + * the Geometry/Geography instance. + * @param startPos + * The index to start from from the WKT. + * @param parentShapeIndex + * The index of the parent's Shape in the shapes array. Used to determine this shape's parent. + * @param isGeoCollection + * flag to indicate if this is part of a GeometryCollection. + * @throws SQLServerException + * if an exception occurs */ - protected void parseWKTForSerialization(SQLServerSpatialDatatype sd, int startPos, int parentShapeIndex, boolean isGeoCollection) { - //after every iteration of this while loop, the currentWktPosition will be set to the - //end of the geometry/geography shape, except for the very first iteration of it. - //This means that there has to be comma (that separates the previous shape with the next shape), - //or we expect a ')' that will close the entire shape and exit the method. - + protected void parseWKTForSerialization(SQLServerSpatialDatatype sd, + int startPos, + int parentShapeIndex, + boolean isGeoCollection) throws SQLServerException { + // after every iteration of this while loop, the currentWktPosition will be set to the + // end of the geometry/geography shape, except for the very first iteration of it. + // This means that there has to be comma (that separates the previous shape with the next shape), + // or we expect a ')' that will close the entire shape and exit the method. + while (hasMoreToken()) { if (startPos != 0) { if (wkt.charAt(currentWktPos) == ')') { return; - } else if (wkt.charAt(currentWktPos) == ',') { + } + else if (wkt.charAt(currentWktPos) == ',') { currentWktPos++; } } @@ -199,49 +228,51 @@ protected void parseWKTForSerialization(SQLServerSpatialDatatype sd, int startPo isd = InternalSpatialDatatype.valueOf(nextToken); } catch (Exception e) { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } byte fa = 0; - - if (version == 1 && (nextToken.equals("CIRCULARSTRING") || nextToken.equals("COMPOUNDCURVE") || - nextToken.equals("CURVEPOLYGON"))) { + + if (version == 1 && (nextToken.equals("CIRCULARSTRING") || nextToken.equals("COMPOUNDCURVE") || nextToken.equals("CURVEPOLYGON"))) { version = 2; } - + // check for FULLGLOBE before reading the first open bracket, since FULLGLOBE doesn't have one. if (nextToken.equals("FULLGLOBE")) { if (sd instanceof Geometry) { - throw new IllegalArgumentException("Fullglobe is not supported for Geometry."); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalTypeForGeometry")); + throw new SQLServerException(form.format(new Object[] {"Fullglobe"}), null, 0, null); } - + if (startPos != 0) { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } - + shapeList.add(new Shape(parentShapeIndex, -1, isd.getTypeCode())); isLargerThanHemisphere = true; version = 2; break; } - // if next keyword is empty, continue the loop. + // if next keyword is empty, continue the loop. if (checkEmptyKeyword(parentShapeIndex, isd, false)) { continue; } - + readOpenBracket(); - + switch (nextToken) { case "POINT": if (startPos == 0 && nextToken.toUpperCase().equals("POINT")) { isSinglePoint = true; } - + if (isGeoCollection) { shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); figureList.add(new Figure(FA_LINE, pointList.size())); } - + readPointWkt(); break; case "LINESTRING": @@ -249,9 +280,9 @@ protected void parseWKTForSerialization(SQLServerSpatialDatatype sd, int startPo shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); fa = isd.getTypeCode() == InternalSpatialDatatype.LINESTRING.getTypeCode() ? FA_STROKE : FA_EXTERIOR_RING; figureList.add(new Figure(fa, pointList.size())); - + readLineWkt(); - + if (startPos == 0 && nextToken.toUpperCase().equals("LINESTRING") && pointList.size() == 2) { isSingleLineSegment = true; } @@ -261,52 +292,53 @@ protected void parseWKTForSerialization(SQLServerSpatialDatatype sd, int startPo case "MULTILINESTRING": thisShapeIndex = shapeList.size(); shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); - + readShapeWkt(thisShapeIndex, nextToken); break; case "MULTIPOLYGON": thisShapeIndex = shapeList.size(); shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); - + readMultiPolygonWkt(thisShapeIndex, nextToken); - + break; case "COMPOUNDCURVE": shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); figureList.add(new Figure(FA_COMPOSITE_CURVE, pointList.size())); - + readCompoundCurveWkt(true); - + break; case "CURVEPOLYGON": shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); readCurvePolygon(); - + break; case "GEOMETRYCOLLECTION": thisShapeIndex = shapeList.size(); shapeList.add(new Shape(parentShapeIndex, figureList.size(), isd.getTypeCode())); - + parseWKTForSerialization(this, currentWktPos, thisShapeIndex, true); - + break; default: - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } readCloseBracket(); } - + populateStructures(); } - + /** - * Constructs and appends a Point type in WKT form to the stringbuffer. - * There are two stringbuffers - WKTsb and WKTsbNoZM. WKTsb contains the X, Y, Z and M coordinates, - * whereas WKTsbNoZM contains only X and Y coordinates. + * Constructs and appends a Point type in WKT form to the stringbuffer. There are two stringbuffers - WKTsb and WKTsbNoZM. WKTsb contains the X, + * Y, Z and M coordinates, whereas WKTsbNoZM contains only X and Y coordinates. * - * @param pointIndex indicates which point to append to the stringbuffer. + * @param pointIndex + * indicates which point to append to the stringbuffer. * */ protected void constructPointWKT(int pointIndex) { @@ -314,80 +346,92 @@ protected void constructPointWKT(int pointIndex) { int secondPointIndex = firstPointIndex + 1; int zValueIndex = pointIndex; int mValueIndex = pointIndex; - + if (points[firstPointIndex] % 1 == 0) { appendToWKTBuffers((int) points[firstPointIndex]); - } else { + } + else { appendToWKTBuffers(points[firstPointIndex]); } appendToWKTBuffers(" "); if (points[secondPointIndex] % 1 == 0) { appendToWKTBuffers((int) points[secondPointIndex]); - } else { + } + else { appendToWKTBuffers(points[secondPointIndex]); } appendToWKTBuffers(" "); - + if (hasZvalues && !Double.isNaN(zValues[zValueIndex]) && !(zValues[zValueIndex] == 0)) { if (zValues[zValueIndex] % 1 == 0) { WKTsb.append((int) zValues[zValueIndex]); - } else { + } + else { WKTsb.append(zValues[zValueIndex]); } WKTsb.append(" "); - + if (hasMvalues && !Double.isNaN(mValues[mValueIndex]) && !(mValues[mValueIndex] <= 0)) { if (mValues[mValueIndex] % 1 == 0) { WKTsb.append((int) mValues[mValueIndex]); - } else { + } + else { WKTsb.append(mValues[mValueIndex]); } WKTsb.append(" "); } } - + currentPointIndex++; // truncate last space WKTsb.setLength(WKTsb.length() - 1); WKTsbNoZM.setLength(WKTsbNoZM.length() - 1); } - /** + /** * Constructs a line in WKT form. * - * @param pointStartIndex . - * @param pointEndIndex . + * @param pointStartIndex + * . + * @param pointEndIndex + * . */ - protected void constructLineWKT(int pointStartIndex, int pointEndIndex) { + protected void constructLineWKT(int pointStartIndex, + int pointEndIndex) { for (int i = pointStartIndex; i < pointEndIndex; i++) { constructPointWKT(i); - + // add ', ' to separate points, except for the last point if (i != pointEndIndex - 1) { appendToWKTBuffers(", "); } } } - + /** * Constructs a shape (simple Geometry/Geography entities that are contained within a single bracket) in WKT form. * - * @param figureStartIndex . - * @param figureEndIndex . + * @param figureStartIndex + * . + * @param figureEndIndex + * . */ - protected void constructShapeWKT(int figureStartIndex, int figureEndIndex) { + protected void constructShapeWKT(int figureStartIndex, + int figureEndIndex) { for (int i = figureStartIndex; i < figureEndIndex; i++) { appendToWKTBuffers("("); - if (i != numberOfFigures - 1) { //not the last figure + if (i != numberOfFigures - 1) { // not the last figure constructLineWKT(figures[i].getPointOffset(), figures[i + 1].getPointOffset()); - } else { + } + else { constructLineWKT(figures[i].getPointOffset(), numberOfPoints); } - + if (i != figureEndIndex - 1) { appendToWKTBuffers("), "); - } else { + } + else { appendToWKTBuffers(")"); } } @@ -396,14 +440,18 @@ protected void constructShapeWKT(int figureStartIndex, int figureEndIndex) { /** * Constructs a mutli-shape (MultiPoint / MultiLineString) in WKT form. * - * @param shapeStartIndex . - * @param shapeEndIndex . + * @param shapeStartIndex + * . + * @param shapeEndIndex + * . */ - protected void constructMultiShapeWKT(int shapeStartIndex, int shapeEndIndex) { + protected void constructMultiShapeWKT(int shapeStartIndex, + int shapeEndIndex) { for (int i = shapeStartIndex + 1; i < shapeEndIndex; i++) { if (shapes[i].getFigureOffset() == -1) { // EMPTY appendToWKTBuffers("EMPTY"); - } else { + } + else { constructShapeWKT(shapes[i].getFigureOffset(), shapes[i].getFigureOffset() + 1); } if (i != shapeEndIndex - 1) { @@ -411,24 +459,29 @@ protected void constructMultiShapeWKT(int shapeStartIndex, int shapeEndIndex) { } } } - + /** * Constructs a CompoundCurve in WKT form. * - * @param segmentStartIndex . - * @param segmentEndIndex . - * @param pointEndIndex . + * @param segmentStartIndex + * . + * @param segmentEndIndex + * . + * @param pointEndIndex + * . */ - protected void constructCompoundcurveWKT(int segmentStartIndex, int segmentEndIndex, int pointEndIndex) { + protected void constructCompoundcurveWKT(int segmentStartIndex, + int segmentEndIndex, + int pointEndIndex) { for (int i = segmentStartIndex; i < segmentEndIndex; i++) { byte segment = segments[i].getSegmentType(); constructSegmentWKT(i, segment, pointEndIndex); - + if (i == segmentEndIndex - 1) { appendToWKTBuffers(")"); break; } - + switch (segment) { case 0: case 2: @@ -447,17 +500,20 @@ protected void constructCompoundcurveWKT(int segmentStartIndex, int segmentEndIn } } } - + /** * Constructs a MultiPolygon in WKT form. * - * @param shapeStartIndex . - * @param shapeEndIndex . + * @param shapeStartIndex + * . + * @param shapeEndIndex + * . */ - protected void constructMultipolygonWKT(int shapeStartIndex, int shapeEndIndex) { + protected void constructMultipolygonWKT(int shapeStartIndex, + int shapeEndIndex) { int figureStartIndex; int figureEndIndex; - + for (int i = shapeStartIndex + 1; i < shapeEndIndex; i++) { figureEndIndex = figures.length; if (shapes[i].getFigureOffset() == -1) { // EMPTY @@ -470,7 +526,8 @@ protected void constructMultipolygonWKT(int shapeStartIndex, int shapeEndIndex) figureStartIndex = shapes[i].getFigureOffset(); if (i == shapes.length - 1) { // last shape figureEndIndex = figures.length; - } else { + } + else { // look ahead and find the next shape that doesn't have -1 as its figure offset (which signifies EMPTY) int tempCurrentShapeIndex = i + 1; // We need to iterate this through until the very end of the shapes list, since if the last shape @@ -479,7 +536,8 @@ protected void constructMultipolygonWKT(int shapeStartIndex, int shapeEndIndex) if (shapes[tempCurrentShapeIndex].getFigureOffset() == -1) { tempCurrentShapeIndex++; continue; - } else { + } + else { figureEndIndex = shapes[tempCurrentShapeIndex].getFigureOffset(); break; } @@ -487,83 +545,96 @@ protected void constructMultipolygonWKT(int shapeStartIndex, int shapeEndIndex) } appendToWKTBuffers("("); - + for (int j = figureStartIndex; j < figureEndIndex; j++) { appendToWKTBuffers("(");// interior ring - + if (j == figures.length - 1) { // last figure constructLineWKT(figures[j].getPointOffset(), numberOfPoints); - } else { + } + else { constructLineWKT(figures[j].getPointOffset(), figures[j + 1].getPointOffset()); } - + if (j == figureEndIndex - 1) { // last polygon of this multipolygon, close off the Multipolygon appendToWKTBuffers(")"); - } else { // not the last polygon, followed by an interior ring + } + else { // not the last polygon, followed by an interior ring appendToWKTBuffers("), "); } } - + appendToWKTBuffers(")"); - + if (!(i == shapeEndIndex - 1)) { // not the last exterior polygon of this multipolygon, add a comma appendToWKTBuffers(", "); } } } - + /** * Constructs a CurvePolygon in WKT form. * - * @param figureStartIndex . - * @param figureEndIndex . - * @param segmentStartIndex . - * @param segmentEndIndex . + * @param figureStartIndex + * . + * @param figureEndIndex + * . + * @param segmentStartIndex + * . + * @param segmentEndIndex + * . */ - protected void constructCurvepolygonWKT(int figureStartIndex, int figureEndIndex, int segmentStartIndex, int segmentEndIndex) { + protected void constructCurvepolygonWKT(int figureStartIndex, + int figureEndIndex, + int segmentStartIndex, + int segmentEndIndex) { for (int i = figureStartIndex; i < figureEndIndex; i++) { switch (figures[i].getFiguresAttribute()) { case 1: // line appendToWKTBuffers("("); - + if (i == figures.length - 1) { constructLineWKT(currentPointIndex, numberOfPoints); - } else { + } + else { constructLineWKT(currentPointIndex, figures[i + 1].getPointOffset()); } - + appendToWKTBuffers(")"); break; case 2: // arc appendToWKTBuffers("CIRCULARSTRING("); - + if (i == figures.length - 1) { constructLineWKT(currentPointIndex, numberOfPoints); - } else { + } + else { constructLineWKT(currentPointIndex, figures[i + 1].getPointOffset()); } - + appendToWKTBuffers(")"); - + break; case 3: // composite curve appendToWKTBuffers("COMPOUNDCURVE("); - + int pointEndIndex = 0; - + if (i == figures.length - 1) { pointEndIndex = numberOfPoints; - } else { + } + else { pointEndIndex = figures[i + 1].getPointOffset(); } - + while (currentPointIndex < pointEndIndex) { byte segment = segments[segmentStartIndex].getSegmentType(); constructSegmentWKT(segmentStartIndex, segment, pointEndIndex); - + if (!(currentPointIndex < pointEndIndex)) { appendToWKTBuffers("))"); - } else { + } + else { switch (segment) { case 0: case 2: @@ -584,53 +655,59 @@ protected void constructCurvepolygonWKT(int figureStartIndex, int figureEndIndex segmentStartIndex++; } - + break; default: return; } - - //Append a comma if this is not the last figure of the shape. + + // Append a comma if this is not the last figure of the shape. if (i != figureEndIndex - 1) { appendToWKTBuffers(", "); } } } - + /** - * Constructs a Segment in WKT form. - * SQL Server re-uses the last point of a segment if the following segment is of type 3 (first arc) or - * type 2 (first line). This makes sense because the last point of a segment and the first point of the next - * segment have to match for a valid curve. This means that the code has to look ahead and decide to decrement - * the currentPointIndex depending on what segment comes next, since it may have been reused (and it's reflected - * in the array of points) + * Constructs a Segment in WKT form. SQL Server re-uses the last point of a segment if the following segment is of type 3 (first arc) or type 2 + * (first line). This makes sense because the last point of a segment and the first point of the next segment have to match for a valid curve. + * This means that the code has to look ahead and decide to decrement the currentPointIndex depending on what segment comes next, since it may + * have been reused (and it's reflected in the array of points) * - * @param currentSegment . - * @param segment . - * @param pointEndIndex . + * @param currentSegment + * . + * @param segment + * . + * @param pointEndIndex + * . */ - protected void constructSegmentWKT(int currentSegment, byte segment, int pointEndIndex) { + protected void constructSegmentWKT(int currentSegment, + byte segment, + int pointEndIndex) { switch (segment) { case 0: appendToWKTBuffers(", "); constructLineWKT(currentPointIndex, currentPointIndex + 1); - + if (currentSegment == segments.length - 1) { // last segment break; - } else if (segments[currentSegment + 1].getSegmentType() != 0) { // not being followed by another line, but not the last segment + } + else if (segments[currentSegment + 1].getSegmentType() != 0) { // not being followed by another line, but not the last segment currentPointIndex = currentPointIndex - 1; incrementPointNumStartIfPointNotReused(pointEndIndex); } break; - + case 1: appendToWKTBuffers(", "); constructLineWKT(currentPointIndex, currentPointIndex + 2); - + if (currentSegment == segments.length - 1) { // last segment break; - } else if (segments[currentSegment + 1].getSegmentType() != 1) { // not being followed by another arc, but not the last segment - currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last point will be reused + } + else if (segments[currentSegment + 1].getSegmentType() != 1) { // not being followed by another arc, but not the last segment + currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last + // point will be reused incrementPointNumStartIfPointNotReused(pointEndIndex); } @@ -638,23 +715,27 @@ protected void constructSegmentWKT(int currentSegment, byte segment, int pointEn case 2: appendToWKTBuffers("("); constructLineWKT(currentPointIndex, currentPointIndex + 2); - + if (currentSegment == segments.length - 1) { // last segment break; - } else if (segments[currentSegment + 1].getSegmentType() != 0) { // not being followed by another line, but not the last segment - currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last point will be reused + } + else if (segments[currentSegment + 1].getSegmentType() != 0) { // not being followed by another line, but not the last segment + currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last + // point will be reused incrementPointNumStartIfPointNotReused(pointEndIndex); } - + break; case 3: appendToWKTBuffers("CIRCULARSTRING("); constructLineWKT(currentPointIndex, currentPointIndex + 3); - + if (currentSegment == segments.length - 1) { // last segment break; - } else if (segments[currentSegment + 1].getSegmentType() != 1) { // not being followed by another arc - currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last point will be reused + } + else if (segments[currentSegment + 1].getSegmentType() != 1) { // not being followed by another arc + currentPointIndex = currentPointIndex - 1; // only increment pointNumStart by one less than what we should be, since the last + // point will be reused incrementPointNumStartIfPointNotReused(pointEndIndex); } @@ -663,70 +744,76 @@ protected void constructSegmentWKT(int currentSegment, byte segment, int pointEn return; } } - + /** * The starting point for constructing a GeometryCollection type in WKT form. * - * @param shapeEndIndex . + * @param shapeEndIndex + * . + * @throws SQLServerException + * if an exception occurs */ - protected void constructGeometryCollectionWKT(int shapeEndIndex) { + protected void constructGeometryCollectionWKT(int shapeEndIndex) throws SQLServerException { currentShapeIndex++; constructGeometryCollectionWKThelper(shapeEndIndex); } - + /** - * Reads Point WKT and adds it to the list of points. - * This method will read up until and including the comma that may come at the end of the Point WKT. + * Reads Point WKT and adds it to the list of points. This method will read up until and including the comma that may come at the end of the Point + * WKT. + * + * @throws SQLServerException + * if an exception occurs */ - protected void readPointWkt() { + protected void readPointWkt() throws SQLServerException { int numOfCoordinates = 0; double sign; double coords[] = new double[4]; - + while (numOfCoordinates < 4) { sign = 1; if (wkt.charAt(currentWktPos) == '-') { sign = -1; currentWktPos++; } - + int startPos = currentWktPos; - + if (wkt.charAt(currentWktPos) == ')') { break; } - - while (currentWktPos < wkt.length() && - (Character.isDigit(wkt.charAt(currentWktPos)) - || wkt.charAt(currentWktPos) == '.' - || wkt.charAt(currentWktPos) == 'E' - || wkt.charAt(currentWktPos) == 'e')) { + + while (currentWktPos < wkt.length() && (Character.isDigit(wkt.charAt(currentWktPos)) || wkt.charAt(currentWktPos) == '.' + || wkt.charAt(currentWktPos) == 'E' || wkt.charAt(currentWktPos) == 'e')) { currentWktPos++; } - + try { - coords[numOfCoordinates] = sign * - new BigDecimal(wkt.substring(startPos, currentWktPos)).doubleValue(); - } catch (Exception e) { //modify to conversion exception - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + coords[numOfCoordinates] = sign * new BigDecimal(wkt.substring(startPos, currentWktPos)).doubleValue(); + } + catch (Exception e) { // modify to conversion exception + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } - + numOfCoordinates++; - + skipWhiteSpaces(); - + // After skipping white space after the 4th coordinate has been read, the next // character has to be either a , or ), or the WKT is invalid. if (numOfCoordinates == 4) { if (wkt.charAt(currentWktPos) != ',' && wkt.charAt(currentWktPos) != ')') { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } - + if (wkt.charAt(currentWktPos) == ',') { // need at least 2 coordinates if (numOfCoordinates == 1) { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } currentWktPos++; skipWhiteSpaces(); @@ -734,84 +821,101 @@ protected void readPointWkt() { } skipWhiteSpaces(); } - + if (numOfCoordinates == 4) { hasZvalues = true; hasMvalues = true; - } else if (numOfCoordinates == 3) { + } + else if (numOfCoordinates == 3) { hasZvalues = true; } - + pointList.add(new Point(coords[0], coords[1], coords[2], coords[3])); } - + /** * Reads a series of Point types. + * + * @throws SQLServerException + * if an exception occurs */ - protected void readLineWkt() { + protected void readLineWkt() throws SQLServerException { while (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { readPointWkt(); } } - + /** * Reads a shape (simple Geometry/Geography entities that are contained within a single bracket) WKT. * - * @param parentShapeIndex shape index of the parent shape that called this method - * @param nextToken next string token + * @param parentShapeIndex + * shape index of the parent shape that called this method + * @param nextToken + * next string token + * @throws SQLServerException + * if an exception occurs */ - protected void readShapeWkt(int parentShapeIndex, String nextToken) { + protected void readShapeWkt(int parentShapeIndex, + String nextToken) throws SQLServerException { byte fa = FA_POINT; while (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { - + // if next keyword is empty, continue the loop. // Do not check this for polygon. - if (!nextToken.equals("POLYGON") && - checkEmptyKeyword(parentShapeIndex, InternalSpatialDatatype.valueOf(nextToken), true)) { + if (!nextToken.equals("POLYGON") && checkEmptyKeyword(parentShapeIndex, InternalSpatialDatatype.valueOf(nextToken), true)) { continue; } - + if (nextToken.equals("MULTIPOINT")) { shapeList.add(new Shape(parentShapeIndex, figureList.size(), InternalSpatialDatatype.POINT.getTypeCode())); - } else if (nextToken.equals("MULTILINESTRING")) { + } + else if (nextToken.equals("MULTILINESTRING")) { shapeList.add(new Shape(parentShapeIndex, figureList.size(), InternalSpatialDatatype.LINESTRING.getTypeCode())); } - + if (version == 1) { if (nextToken.equals("MULTIPOINT")) { fa = FA_STROKE; - } else if (nextToken.equals("MULTILINESTRING") || nextToken.equals("POLYGON")) { + } + else if (nextToken.equals("MULTILINESTRING") || nextToken.equals("POLYGON")) { fa = FA_EXTERIOR_RING; } version_one_shape_indexes.add(figureList.size()); - } else if (version == 2) { - if (nextToken.equals("MULTIPOINT") || nextToken.equals("MULTILINESTRING") || - nextToken.equals("POLYGON") || nextToken.equals("MULTIPOLYGON")) { + } + else if (version == 2) { + if (nextToken.equals("MULTIPOINT") || nextToken.equals("MULTILINESTRING") || nextToken.equals("POLYGON") + || nextToken.equals("MULTIPOLYGON")) { fa = FA_LINE; } } - + figureList.add(new Figure(fa, pointList.size())); readOpenBracket(); readLineWkt(); readCloseBracket(); skipWhiteSpaces(); - + if (wkt.charAt(currentWktPos) == ',') { // more rings to follow readComma(); - } else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop + } + else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop continue; - } else { // unexpected input - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { // unexpected input + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } } - + /** * Reads a CurvePolygon WKT + * + * @throws SQLServerException + * if an exception occurs */ - protected void readCurvePolygon() { + protected void readCurvePolygon() throws SQLServerException { while (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { String nextPotentialToken = getNextStringToken().toUpperCase(Locale.US); if (nextPotentialToken.equals("CIRCULARSTRING")) { @@ -819,26 +923,33 @@ protected void readCurvePolygon() { readOpenBracket(); readLineWkt(); readCloseBracket(); - } else if (nextPotentialToken.equals("COMPOUNDCURVE")) { + } + else if (nextPotentialToken.equals("COMPOUNDCURVE")) { figureList.add(new Figure(FA_COMPOSITE_CURVE, pointList.size())); readOpenBracket(); readCompoundCurveWkt(true); readCloseBracket(); - } else if (wkt.charAt(currentWktPos) == '(') { //LineString + } + else if (wkt.charAt(currentWktPos) == '(') { // LineString figureList.add(new Figure(FA_LINE, pointList.size())); readOpenBracket(); readLineWkt(); readCloseBracket(); - } else { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); } - + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); + } + if (wkt.charAt(currentWktPos) == ',') { // more polygons to follow readComma(); - } else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop + } + else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop continue; - } else { // unexpected input - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { // unexpected input + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } } @@ -846,59 +957,74 @@ protected void readCurvePolygon() { /** * Reads a MultiPolygon WKT * - * @param thisShapeIndex shape index of current shape - * @param nextToken next string token + * @param thisShapeIndex + * shape index of current shape + * @param nextToken + * next string token + * @throws SQLServerException + * if an exception occurs */ - protected void readMultiPolygonWkt(int thisShapeIndex, String nextToken) { + protected void readMultiPolygonWkt(int thisShapeIndex, + String nextToken) throws SQLServerException { while (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { if (checkEmptyKeyword(thisShapeIndex, InternalSpatialDatatype.valueOf(nextToken), true)) { continue; } - shapeList.add(new Shape(thisShapeIndex, figureList.size(), InternalSpatialDatatype.POLYGON.getTypeCode())); //exterior polygon + shapeList.add(new Shape(thisShapeIndex, figureList.size(), InternalSpatialDatatype.POLYGON.getTypeCode())); // exterior polygon readOpenBracket(); readShapeWkt(thisShapeIndex, nextToken); readCloseBracket(); - + if (wkt.charAt(currentWktPos) == ',') { // more polygons to follow readComma(); - } else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop + } + else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop continue; - } else { // unexpected input - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { // unexpected input + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } } - + /** * Reads a Segment WKT * - * @param segmentType segment type - * @param isFirstIteration flag that indicates if this is the first iteration from the loop outside + * @param segmentType + * segment type + * @param isFirstIteration + * flag that indicates if this is the first iteration from the loop outside + * @throws SQLServerException + * if an exception occurs */ - protected void readSegmentWkt(int segmentType, boolean isFirstIteration) { + protected void readSegmentWkt(int segmentType, + boolean isFirstIteration) throws SQLServerException { segmentList.add(new Segment((byte) segmentType)); - + int segmentLength = segmentType; - + // under 2 means 0 or 1 (possible values). 0 (line) has 1 point, and 1 (arc) has 2 points, so increment by one - if (segmentLength < 2) { + if (segmentLength < 2) { segmentLength++; } - + for (int i = 0; i < segmentLength; i++) { - //If a segment type of 2 (first line) or 3 (first arc) is not from the very first iteration of the while loop, - //then the first point has to be a duplicate point from the previous segment, so skip the first point. + // If a segment type of 2 (first line) or 3 (first arc) is not from the very first iteration of the while loop, + // then the first point has to be a duplicate point from the previous segment, so skip the first point. if (i == 0 && !isFirstIteration && segmentType >= 2) { skipFirstPointWkt(); - } else { + } + else { readPointWkt(); } } - + if (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { if (segmentType == SEGMENT_FIRST_ARC || segmentType == SEGMENT_ARC) { readSegmentWkt(SEGMENT_ARC, false); - } else if (segmentType == SEGMENT_FIRST_LINE | segmentType == SEGMENT_LINE) { + } + else if (segmentType == SEGMENT_FIRST_LINE | segmentType == SEGMENT_LINE) { readSegmentWkt(SEGMENT_LINE, false); } } @@ -907,38 +1033,46 @@ protected void readSegmentWkt(int segmentType, boolean isFirstIteration) { /** * Reads a CompoundCurve WKT * - * @param isFirstIteration flag that indicates if this is the first iteration from the loop outside + * @param isFirstIteration + * flag that indicates if this is the first iteration from the loop outside + * @throws SQLServerException + * if an exception occurs */ - protected void readCompoundCurveWkt(boolean isFirstIteration) { + protected void readCompoundCurveWkt(boolean isFirstIteration) throws SQLServerException { while (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { String nextPotentialToken = getNextStringToken().toUpperCase(Locale.US); if (nextPotentialToken.equals("CIRCULARSTRING")) { readOpenBracket(); readSegmentWkt(SEGMENT_FIRST_ARC, isFirstIteration); readCloseBracket(); - } else if (wkt.charAt(currentWktPos) == '(') {//LineString + } + else if (wkt.charAt(currentWktPos) == '(') {// LineString readOpenBracket(); readSegmentWkt(SEGMENT_FIRST_LINE, isFirstIteration); readCloseBracket(); - } else { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); } - + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); + } + isFirstIteration = false; - + if (wkt.charAt(currentWktPos) == ',') { // more polygons to follow readComma(); - } else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop + } + else if (wkt.charAt(currentWktPos) == ')') { // about to exit while loop continue; - } else { // unexpected input - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); } - } + else { // unexpected input + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); + } + } } /** - * Reads the next string token (usually POINT, LINESTRING, etc.). - * Then increments currentWktPos to the end of the string token. + * Reads the next string token (usually POINT, LINESTRING, etc.). Then increments currentWktPos to the end of the string token. * * @return the next string token */ @@ -951,7 +1085,7 @@ protected String getNextStringToken() { int temp = currentWktPos; currentWktPos = endIndex; skipWhiteSpaces(); - + return wkt.substring(temp, endIndex); } @@ -960,20 +1094,20 @@ protected String getNextStringToken() { */ protected void populateStructures() { if (pointList.size() > 0) { - points = new double[pointList.size() * 2]; - + points = new double[pointList.size() * 2]; + for (int i = 0; i < pointList.size(); i++) { points[i * 2] = pointList.get(i).getX(); points[i * 2 + 1] = pointList.get(i).getY(); } - + if (hasZvalues) { zValues = new double[pointList.size()]; for (int i = 0; i < pointList.size(); i++) { zValues[i] = pointList.get(i).getZ(); } } - + if (hasMvalues) { mValues = new double[pointList.size()]; for (int i = 0; i < pointList.size(); i++) { @@ -981,7 +1115,7 @@ protected void populateStructures() { } } } - + // if version is 2, then we need to check for potential shapes (polygon & multi-shapes) that were // given their figure attributes as if it was version 1, since we don't know what would be the // version of the geometry/geography before we parse the entire WKT. @@ -990,15 +1124,15 @@ protected void populateStructures() { figureList.get(version_one_shape_indexes.get(i)).setFiguresAttribute((byte) 1); } } - + if (figureList.size() > 0) { figures = new Figure[figureList.size()]; - + for (int i = 0; i < figureList.size(); i++) { figures[i] = figureList.get(i); } } - + // There is an edge case of empty GeometryCollections being inside other GeometryCollections. In this case, // the figure offset of the very first shape (GeometryCollections) has to be -1, but this is not possible to know until // We've parsed through the entire WKT and confirmed that there are 0 points. @@ -1006,46 +1140,50 @@ protected void populateStructures() { if (pointList.size() == 0 && shapeList.size() > 0 && shapeList.get(0).getOpenGISType() == 7) { shapeList.get(0).setFigureOffset(-1); } - + if (shapeList.size() > 0) { shapes = new Shape[shapeList.size()]; - + for (int i = 0; i < shapeList.size(); i++) { shapes[i] = shapeList.get(i); } } - + if (segmentList.size() > 0) { segments = new Segment[segmentList.size()]; - + for (int i = 0; i < segmentList.size(); i++) { segments[i] = segmentList.get(i); } } - + numberOfPoints = pointList.size(); numberOfFigures = figureList.size(); numberOfShapes = shapeList.size(); numberOfSegments = segmentList.size(); } - - protected void readOpenBracket() { + + protected void readOpenBracket() throws SQLServerException { skipWhiteSpaces(); if (wkt.charAt(currentWktPos) == '(') { currentWktPos++; skipWhiteSpaces(); - } else { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } - - protected void readCloseBracket() { + + protected void readCloseBracket() throws SQLServerException { skipWhiteSpaces(); if (wkt.charAt(currentWktPos) == ')') { currentWktPos++; skipWhiteSpaces(); - } else { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } @@ -1053,80 +1191,82 @@ protected boolean hasMoreToken() { skipWhiteSpaces(); return currentWktPos < wkt.length(); } - + protected void createSerializationProperties() { serializationProperties = 0; if (hasZvalues) { serializationProperties += hasZvaluesMask; } - + if (hasMvalues) { serializationProperties += hasMvaluesMask; } - + if (isValid) { serializationProperties += isValidMask; } - + if (isSinglePoint) { serializationProperties += isSinglePointMask; } - + if (isSingleLineSegment) { serializationProperties += isSingleLineSegmentMask; } - + if (version == 2) { if (isLargerThanHemisphere) { serializationProperties += isLargerThanHemisphereMask; } } } - + protected int determineWkbCapacity() { int totalSize = 0; - - totalSize+=6; // SRID + version + SerializationPropertiesByte - + + totalSize += 6; // SRID + version + SerializationPropertiesByte + if (isSinglePoint || isSingleLineSegment) { totalSize += 16 * numberOfPoints; - + if (hasZvalues) { totalSize += 8 * numberOfPoints; } - + if (hasMvalues) { totalSize += 8 * numberOfPoints; } - + return totalSize; } - + int pointSize = 16; if (hasZvalues) { pointSize += 8; } - + if (hasMvalues) { pointSize += 8; } - + totalSize += 12; // 4 bytes for 3 ints, each representing the number of points, shapes and figures totalSize += numberOfPoints * pointSize; totalSize += numberOfFigures * 5; totalSize += numberOfShapes * 9; - + if (version == 2) { totalSize += 4; // 4 bytes for 1 int, representing the number of segments totalSize += numberOfSegments; } - + return totalSize; } - + /** * Append the data to both stringbuffers. - * @param o data to append to the stringbuffers. + * + * @param o + * data to append to the stringbuffers. */ protected void appendToWKTBuffers(Object o) { WKTsb.append(o); @@ -1141,35 +1281,37 @@ protected void interpretSerializationPropBytes() { isSingleLineSegment = (serializationProperties & isSingleLineSegmentMask) != 0; isLargerThanHemisphere = (serializationProperties & isLargerThanHemisphereMask) != 0; } - + protected void readNumberOfPoints() { if (isSinglePoint) { numberOfPoints = 1; - } else if (isSingleLineSegment) { + } + else if (isSingleLineSegment) { numberOfPoints = 2; - } else { + } + else { numberOfPoints = buffer.getInt(); } } - + protected void readZvalues() { zValues = new double[numberOfPoints]; for (int i = 0; i < numberOfPoints; i++) { zValues[i] = buffer.getDouble(); } } - + protected void readMvalues() { mValues = new double[numberOfPoints]; for (int i = 0; i < numberOfPoints; i++) { mValues[i] = buffer.getDouble(); } } - + protected void readNumberOfFigures() { numberOfFigures = buffer.getInt(); } - + protected void readFigures() { byte fa; int po; @@ -1180,11 +1322,11 @@ protected void readFigures() { figures[i] = new Figure(fa, po); } } - + protected void readNumberOfShapes() { numberOfShapes = buffer.getInt(); } - + protected void readShapes() { int po; int fo; @@ -1197,11 +1339,11 @@ protected void readShapes() { shapes[i] = new Shape(po, fo, ogt); } } - + protected void readNumberOfSegments() { numberOfSegments = buffer.getInt(); } - + protected void readSegments() { byte st; segments = new Segment[numberOfSegments]; @@ -1214,36 +1356,46 @@ protected void readSegments() { protected void determineInternalType() { if (isSinglePoint) { internalType = InternalSpatialDatatype.POINT; - } else if (isSingleLineSegment) { + } + else if (isSingleLineSegment) { internalType = InternalSpatialDatatype.LINESTRING; - } else { + } + else { internalType = InternalSpatialDatatype.valueOf(shapes[0].getOpenGISType()); } } - - protected boolean checkEmptyKeyword(int parentShapeIndex, InternalSpatialDatatype isd, boolean isInsideAnotherShape) { + + protected boolean checkEmptyKeyword(int parentShapeIndex, + InternalSpatialDatatype isd, + boolean isInsideAnotherShape) throws SQLServerException { String potentialEmptyKeyword = getNextStringToken().toUpperCase(Locale.US); if (potentialEmptyKeyword.equals("EMPTY")) { - + byte typeCode = 0; - + if (isInsideAnotherShape) { byte parentTypeCode = isd.getTypeCode(); if (parentTypeCode == 4) { // MultiPoint typeCode = InternalSpatialDatatype.POINT.getTypeCode(); - } else if (parentTypeCode == 5) { // MultiLineString + } + else if (parentTypeCode == 5) { // MultiLineString typeCode = InternalSpatialDatatype.LINESTRING.getTypeCode(); - } else if (parentTypeCode == 6) { // MultiPolygon + } + else if (parentTypeCode == 6) { // MultiPolygon typeCode = InternalSpatialDatatype.POLYGON.getTypeCode(); - } else if (parentTypeCode == 7) { // GeometryCollection + } + else if (parentTypeCode == 7) { // GeometryCollection typeCode = InternalSpatialDatatype.GEOMETRYCOLLECTION.getTypeCode(); - } else { - throw new IllegalArgumentException("Illegal parentTypeCode."); } - } else { + else { + String strError = SQLServerException.getErrString("R_illegalWKT"); + throw new SQLServerException(strError, null, 0, null); + } + } + else { typeCode = isd.getTypeCode(); } - + shapeList.add(new Shape(parentShapeIndex, -1, typeCode)); skipWhiteSpaces(); if (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) == ',') { @@ -1252,13 +1404,14 @@ protected boolean checkEmptyKeyword(int parentShapeIndex, InternalSpatialDatatyp } return true; } - + if (!potentialEmptyKeyword.equals("")) { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } return false; } - + private void incrementPointNumStartIfPointNotReused(int pointEndIndex) { // We need to increment PointNumStart if the last point was actually not re-used in the points array. // 0 for pointNumEnd indicates that this check is not applicable. @@ -1266,17 +1419,20 @@ private void incrementPointNumStartIfPointNotReused(int pointEndIndex) { currentPointIndex++; } } - + /** * Helper used for resurcive iteration for constructing GeometryCollection in WKT form. * - * @param shapeEndIndex . + * @param shapeEndIndex + * . + * @throws SQLServerException + * if an exception occurs */ - private void constructGeometryCollectionWKThelper(int shapeEndIndex) { - //phase 1: assume that there is no multi - stuff and no geometrycollection + private void constructGeometryCollectionWKThelper(int shapeEndIndex) throws SQLServerException { + // phase 1: assume that there is no multi - stuff and no geometrycollection while (currentShapeIndex < shapeEndIndex) { InternalSpatialDatatype isd = InternalSpatialDatatype.valueOf(shapes[currentShapeIndex].getOpenGISType()); - + int figureIndex = shapes[currentShapeIndex].getFigureOffset(); int pointIndexEnd = numberOfPoints; int figureIndexEnd = numberOfFigures; @@ -1287,7 +1443,7 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { int shapeIndexIncrement = 0; int localCurrentSegmentIndex = 0; int localCurrentShapeIndex = 0; - + switch (isd) { case POINT: figureIndexIncrement++; @@ -1304,27 +1460,28 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { if (currentShapeIndex < shapes.length - 1) { figureIndexEnd = shapes[currentShapeIndex + 1].getFigureOffset(); } - + figureIndexIncrement = figureIndexEnd - currentFigureIndex; currentShapeIndex++; - + // Needed to keep track of which segment we are at, inside the for loop localCurrentSegmentIndex = currentSegmentIndex; - + if (isd.equals(InternalSpatialDatatype.CURVEPOLYGON)) { // assume Version 2 for (int i = currentFigureIndex; i < figureIndexEnd; i++) { // Only Compoundcurves (with figure attribute 3) can have segments if (figures[i].getFiguresAttribute() == 3) { - + int pointOffsetEnd; if (i == figures.length - 1) { pointOffsetEnd = numberOfPoints; - } else { + } + else { pointOffsetEnd = figures[i + 1].getPointOffset(); } - + int increment = calculateSegmentIncrement(localCurrentSegmentIndex, pointOffsetEnd - figures[i].getPointOffset()); segmentIndexIncrement = segmentIndexIncrement + increment; @@ -1332,42 +1489,41 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { } } } - + segmentIndexEnd = localCurrentSegmentIndex; - + break; case MULTIPOINT: case MULTILINESTRING: case MULTIPOLYGON: - //Multipoint and MultiLineString can go on for multiple Shapes, but eventually - //the parentOffset will signal the end of the object, or it's reached the end of the - //shapes array. - //There is also no possibility that a MultiPoint or MultiLineString would branch - //into another parent. - + // Multipoint and MultiLineString can go on for multiple Shapes, but eventually + // the parentOffset will signal the end of the object, or it's reached the end of the + // shapes array. + // There is also no possibility that a MultiPoint or MultiLineString would branch + // into another parent. + int thisShapesParentOffset = shapes[currentShapeIndex].getParentOffset(); - + int tempShapeIndex = currentShapeIndex; - + // Increment shapeStartIndex to account for the shape index that either Multipoint, MultiLineString // or MultiPolygon takes up tempShapeIndex++; - while (tempShapeIndex < shapes.length && - shapes[tempShapeIndex].getParentOffset() != thisShapesParentOffset) { + while (tempShapeIndex < shapes.length && shapes[tempShapeIndex].getParentOffset() != thisShapesParentOffset) { if (!(tempShapeIndex == shapes.length - 1) && // last iteration, don't check for shapes[tempShapeIndex + 1] !(shapes[tempShapeIndex + 1].getFigureOffset() == -1)) { // disregard EMPTY cases figureIndexEnd = shapes[tempShapeIndex + 1].getFigureOffset(); } tempShapeIndex++; } - + figureIndexIncrement = figureIndexEnd - currentFigureIndex; shapeIndexIncrement = tempShapeIndex - currentShapeIndex; shapeIndexEnd = tempShapeIndex; break; case GEOMETRYCOLLECTION: appendToWKTBuffers(isd.getTypeName()); - + // handle Empty GeometryCollection cases if (shapes[currentShapeIndex].getFigureOffset() == -1) { appendToWKTBuffers(" EMPTY"); @@ -1377,28 +1533,29 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { } continue; } - + appendToWKTBuffers("("); - + int geometryCollectionParentIndex = shapes[currentShapeIndex].getParentOffset(); - + // Needed to keep track of which shape we are at, inside the for loop localCurrentShapeIndex = currentShapeIndex; - - while (localCurrentShapeIndex < shapes.length - 1 && - shapes[localCurrentShapeIndex + 1].getParentOffset() > geometryCollectionParentIndex) { + + while (localCurrentShapeIndex < shapes.length - 1 + && shapes[localCurrentShapeIndex + 1].getParentOffset() > geometryCollectionParentIndex) { localCurrentShapeIndex++; } // increment localCurrentShapeIndex one more time since it will be used as a shapeEndIndex parameter // for constructGeometryCollectionWKT, and the shapeEndIndex parameter is used non-inclusively localCurrentShapeIndex++; - + currentShapeIndex++; constructGeometryCollectionWKThelper(localCurrentShapeIndex); - + if (currentShapeIndex < shapeEndIndex) { appendToWKTBuffers("), "); - } else { + } + else { appendToWKTBuffers(")"); } @@ -1406,12 +1563,12 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { case COMPOUNDCURVE: if (currentFigureIndex == figures.length - 1) { pointIndexEnd = numberOfPoints; - } else { + } + else { pointIndexEnd = figures[currentFigureIndex + 1].getPointOffset(); } - int increment = calculateSegmentIncrement(currentSegmentIndex, pointIndexEnd - - figures[currentFigureIndex].getPointOffset()); + int increment = calculateSegmentIncrement(currentSegmentIndex, pointIndexEnd - figures[currentFigureIndex].getPointOffset()); segmentIndexIncrement = increment; segmentIndexEnd = currentSegmentIndex + increment; @@ -1424,12 +1581,12 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { default: break; } - + constructWKT(this, isd, pointIndexEnd, figureIndexEnd, segmentIndexEnd, shapeIndexEnd); currentFigureIndex = currentFigureIndex + figureIndexIncrement; currentSegmentIndex = currentSegmentIndex + segmentIndexIncrement; currentShapeIndex = currentShapeIndex + shapeIndexIncrement; - + if (currentShapeIndex < shapeEndIndex) { appendToWKTBuffers(", "); } @@ -1437,54 +1594,59 @@ private void constructGeometryCollectionWKThelper(int shapeEndIndex) { } /** - * Calculates how many segments will be used by this shape. - * Needed to determine when the shape that uses segments (e.g. CompoundCurve) needs to stop reading - * in cases where the CompoundCurve is included as part of GeometryCollection. + * Calculates how many segments will be used by this shape. Needed to determine when the shape that uses segments (e.g. CompoundCurve) needs to + * stop reading in cases where the CompoundCurve is included as part of GeometryCollection. * - * @param segmentStart . - * @param pointDifference number of points that were assigned to this segment to be used. + * @param segmentStart + * . + * @param pointDifference + * number of points that were assigned to this segment to be used. * @return the number of segments that will be used by this shape. */ private int calculateSegmentIncrement(int segmentStart, int pointDifference) { - + int segmentIncrement = 0; - + while (pointDifference > 0) { switch (segments[segmentStart].getSegmentType()) { case 0: pointDifference = pointDifference - 1; - + if (segmentStart == segments.length - 1 || pointDifference < 1) { // last segment break; - } else if (segments[segmentStart + 1].getSegmentType() != 0) { // one point will be reused + } + else if (segments[segmentStart + 1].getSegmentType() != 0) { // one point will be reused pointDifference = pointDifference + 1; } break; case 1: pointDifference = pointDifference - 2; - + if (segmentStart == segments.length - 1 || pointDifference < 1) { // last segment break; - } else if (segments[segmentStart + 1].getSegmentType() != 1) { // one point will be reused + } + else if (segments[segmentStart + 1].getSegmentType() != 1) { // one point will be reused pointDifference = pointDifference + 1; } break; case 2: pointDifference = pointDifference - 2; - + if (segmentStart == segments.length - 1 || pointDifference < 1) { // last segment break; - } else if (segments[segmentStart + 1].getSegmentType() != 0) { // one point will be reused + } + else if (segments[segmentStart + 1].getSegmentType() != 0) { // one point will be reused pointDifference = pointDifference + 1; } break; case 3: pointDifference = pointDifference - 3; - + if (segmentStart == segments.length - 1 || pointDifference < 1) { // last segment break; - } else if (segments[segmentStart + 1].getSegmentType() != 1) { // one point will be reused + } + else if (segments[segmentStart + 1].getSegmentType() != 1) { // one point will be reused pointDifference = pointDifference + 1; } break; @@ -1494,30 +1656,27 @@ private int calculateSegmentIncrement(int segmentStart, segmentStart++; segmentIncrement++; } - + return segmentIncrement; } private void skipFirstPointWkt() { int numOfCoordinates = 0; - + while (numOfCoordinates < 4) { if (wkt.charAt(currentWktPos) == '-') { currentWktPos++; } - + if (wkt.charAt(currentWktPos) == ')') { break; } - - while (currentWktPos < wkt.length() && - (Character.isDigit(wkt.charAt(currentWktPos)) - || wkt.charAt(currentWktPos) == '.' - || wkt.charAt(currentWktPos) == 'E' - || wkt.charAt(currentWktPos) == 'e')) { + + while (currentWktPos < wkt.length() && (Character.isDigit(wkt.charAt(currentWktPos)) || wkt.charAt(currentWktPos) == '.' + || wkt.charAt(currentWktPos) == 'E' || wkt.charAt(currentWktPos) == 'e')) { currentWktPos++; } - + skipWhiteSpaces(); if (wkt.charAt(currentWktPos) == ',') { currentWktPos++; @@ -1526,21 +1685,23 @@ private void skipFirstPointWkt() { break; } skipWhiteSpaces(); - + numOfCoordinates++; } } - - private void readComma() { + + private void readComma() throws SQLServerException { skipWhiteSpaces(); if (wkt.charAt(currentWktPos) == ',') { currentWktPos++; skipWhiteSpaces(); - } else { - throw new IllegalArgumentException("Illegal character at wkt position " + currentWktPos); + } + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_illegalWKTposition")); + throw new SQLServerException(form.format(new Object[] {currentWktPos}), null, 0, null); } } - + private void skipWhiteSpaces() { while (currentWktPos < wkt.length() && Character.isWhitespace(wkt.charAt(currentWktPos))) { currentWktPos++; @@ -1555,20 +1716,21 @@ private void skipWhiteSpaces() { class Figure { private byte figuresAttribute; private int pointOffset; - - Figure(byte figuresAttribute, int pointOffset) { + + Figure(byte figuresAttribute, + int pointOffset) { this.figuresAttribute = figuresAttribute; this.pointOffset = pointOffset; } - + public byte getFiguresAttribute() { return figuresAttribute; } - + public int getPointOffset() { return pointOffset; } - + public void setFiguresAttribute(byte fa) { figuresAttribute = fa; } @@ -1582,29 +1744,31 @@ class Shape { private int parentOffset; private int figureOffset; private byte openGISType; - - Shape(int parentOffset, int figureOffset, byte openGISType) { + + Shape(int parentOffset, + int figureOffset, + byte openGISType) { this.parentOffset = parentOffset; this.figureOffset = figureOffset; this.openGISType = openGISType; } - + public int getParentOffset() { return parentOffset; } - + public int getFigureOffset() { return figureOffset; } - + public byte getOpenGISType() { return openGISType; } - + public void setFigureOffset(int fo) { figureOffset = fo; } - + } /** @@ -1613,11 +1777,11 @@ public void setFigureOffset(int fo) { */ class Segment { private byte segmentType; - + Segment(byte segmentType) { this.segmentType = segmentType; } - + public byte getSegmentType() { return segmentType; } @@ -1632,26 +1796,29 @@ class Point { private final double y; private final double z; private final double m; - - Point(double x, double y, double z, double m) { + + Point(double x, + double y, + double z, + double m) { this.x = x; this.y = y; this.z = z; this.m = m; } - + public double getX() { return x; } - + public double getY() { return y; } - + public double getZ() { return z; } - + public double getM() { return m; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index 441d8b5b0..cd56a7b84 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -154,6 +154,9 @@ String getClassNameLogging() { */ protected SQLServerStatementColumnEncryptionSetting stmtColumnEncriptionSetting = SQLServerStatementColumnEncryptionSetting.UseConnectionSetting; + protected SQLServerStatementColumnEncryptionSetting getStmtColumnEncriptionSetting() { + return stmtColumnEncriptionSetting; + } /** * ExecuteProperties encapsulates a subset of statement property values as they were set at execution time. */ @@ -447,6 +450,7 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { .getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerStatement"); /** The statement's id for logging info */ + @Override public String toString() { return traceID; } @@ -494,7 +498,6 @@ private static int nextStatementID() { stmtPoolable = false; connection = con; bIsClosed = false; - final int nTypes = 5; // Validate result set type ... if (ResultSet.TYPE_FORWARD_ONLY != nType && ResultSet.TYPE_SCROLL_SENSITIVE != nType && ResultSet.TYPE_SCROLL_INSENSITIVE != nType @@ -612,14 +615,7 @@ private void setDefaultQueryTimeout() { final java.util.logging.Logger getStatementLogger() { return stmtlogger; } - - /** - * Standard handler for unsupported data types. - */ - /* L0 */ final void NotImplemented() throws SQLServerException { - SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_notSupported"), null, false); - } - + /** * Close the statement. * @@ -631,15 +627,17 @@ void closeInternal() { // Regardless what happens when cleaning up, // the statement is considered closed. assert !bIsClosed; - discardLastExecutionResults(); bIsClosed = true; autoGeneratedKeys = null; sqlWarnings = null; inOutParam = null; + + connection.removeOpenStatement(this); } + @Override public void close() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "close"); @@ -649,6 +647,7 @@ public void close() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "close"); } + @Override public void closeOnCompletion() throws SQLException { loggerExternal.entering(getClassNameLogging(), "closeOnCompletion"); @@ -660,15 +659,7 @@ public void closeOnCompletion() throws SQLException { loggerExternal.exiting(getClassNameLogging(), "closeOnCompletion"); } - /** - * Execute a result set query - * - * @param sql - * the SQL query - * @exception SQLServerException - * The SQL was invalid. - * @return a JDBC result set. - */ + @Override public java.sql.ResultSet executeQuery(String sql) throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeQuery", sql); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -686,15 +677,7 @@ final SQLServerResultSet executeQueryInternal(String sql) throws SQLServerExcept return resultSet; } - /** - * Execute a JDBC update - * - * @param sql - * the SQL query - * @exception SQLServerException - * The SQL was invalid. - * @return The number of rows updated. - */ + @Override public int executeUpdate(String sql) throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeUpdate", sql); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -712,17 +695,8 @@ public int executeUpdate(String sql) throws SQLServerException, SQLTimeoutExcept return (int) updateCount; } - /** - * Execute a JDBC update - * - * @param sql - * the SQL query - * @exception SQLServerException - * The SQL was invalid. - * @return The number of rows updated. - */ + @Override public long executeLargeUpdate(String sql) throws SQLServerException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); loggerExternal.entering(getClassNameLogging(), "executeLargeUpdate", sql); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -735,15 +709,7 @@ public long executeLargeUpdate(String sql) throws SQLServerException, SQLTimeout return updateCount; } - /** - * Execute an update or query. - * - * @param sql - * The update or query. - * @exception SQLServerException - * The SQL statement was not valid. - * @return True if a result set was generated. - */ + @Override public boolean execute(String sql) throws SQLServerException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "execute", sql); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -964,18 +930,40 @@ final void resetForReexecute() throws SQLServerException { * * @param sql * The statment SQL. - * @return True is the statement is a select. + * @return True if the statement is a select. */ - /* L0 */ final boolean isSelect(String sql) throws SQLServerException { + final boolean isSelect(String sql) throws SQLServerException { checkClosed(); // Used to check just the first letter which would cause // "Set" commands to return true... String temp = sql.trim(); - char c = temp.charAt(0); - if (c != 's' && c != 'S') + if (null == sql || sql.length() < 6) { return false; + } return temp.substring(0, 6).equalsIgnoreCase("select"); } + + /** + * Determine if the SQL is a INSERT. + * + * @param sql + * The statment SQL. + * @return True if the statement is an insert. + */ + /* L0 */ final boolean isInsert(String sql) throws SQLServerException { + checkClosed(); + // Used to check just the first letter which would cause + // "Set" commands to return true... + String temp = sql.trim(); + if (null == sql || sql.length() < 6) { + return false; + } + if (temp.substring(0, 2).equalsIgnoreCase("/*")) { + int index = temp.indexOf("*/") + 2; + return isInsert(temp.substring(index)); + } + return temp.substring(0, 6).equalsIgnoreCase("insert"); + } /** * Replace a JDBC parameter marker with the parameter's string value @@ -988,7 +976,7 @@ final void resetForReexecute() throws SQLServerException { * the param value * @return String */ - /* L0 */ static String replaceParameterWithString(String str, + static String replaceParameterWithString(String str, char marker, String replaceStr) { int index = 0; @@ -1005,7 +993,7 @@ final void resetForReexecute() throws SQLServerException { * the parameter syntax * @return the result */ - /* L0 */ static String replaceMarkerWithNull(String sql) { + static String replaceMarkerWithNull(String sql) { if (!sql.contains("'")) { String retStr = replaceParameterWithString(sql, '?', "null"); return retStr; @@ -1035,7 +1023,7 @@ final void resetForReexecute() throws SQLServerException { } } - /* L0 */ void checkClosed() throws SQLServerException { + void checkClosed() throws SQLServerException { // Check the connection first so that Statement methods // throw a "Connection closed" exception if the reason // that the statement was closed is because the connection @@ -1048,14 +1036,16 @@ final void resetForReexecute() throws SQLServerException { /* ---------------- JDBC API methods ------------------ */ - /* L0 */ public final int getMaxFieldSize() throws SQLServerException { + @Override + public final int getMaxFieldSize() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMaxFieldSize"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getMaxFieldSize", maxFieldSize); return maxFieldSize; } - /* L0 */ public final void setMaxFieldSize(int max) throws SQLServerException { + @Override + public final void setMaxFieldSize(int max) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setMaxFieldSize", max); checkClosed(); if (max < 0) { @@ -1067,15 +1057,16 @@ final void resetForReexecute() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setMaxFieldSize"); } - /* L0 */ public final int getMaxRows() throws SQLServerException { + @Override + public final int getMaxRows() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMaxRows"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getMaxRows", maxRows); return maxRows; } + @Override public final long getLargeMaxRows() throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); loggerExternal.entering(getClassNameLogging(), "getLargeMaxRows"); @@ -1086,7 +1077,8 @@ public final long getLargeMaxRows() throws SQLServerException { return (long) getMaxRows(); } - /* L0 */ public final void setMaxRows(int max) throws SQLServerException { + @Override + public final void setMaxRows(int max) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setMaxRows", max); checkClosed(); @@ -1104,8 +1096,8 @@ public final long getLargeMaxRows() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setMaxRows"); } + @Override public final void setLargeMaxRows(long max) throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setLargeMaxRows", max); @@ -1119,7 +1111,8 @@ public final void setLargeMaxRows(long max) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setLargeMaxRows"); } - /* L0 */ public final void setEscapeProcessing(boolean enable) throws SQLServerException { + @Override + public final void setEscapeProcessing(boolean enable) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setEscapeProcessing", enable); checkClosed(); @@ -1127,14 +1120,16 @@ public final void setLargeMaxRows(long max) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setEscapeProcessing"); } - /* L0 */ public final int getQueryTimeout() throws SQLServerException { + @Override + public final int getQueryTimeout() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getQueryTimeout"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getQueryTimeout", queryTimeout); return queryTimeout; } - /* L0 */ public final void setQueryTimeout(int seconds) throws SQLServerException { + @Override + public final void setQueryTimeout(int seconds) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setQueryTimeout", seconds); checkClosed(); if (seconds < 0) { @@ -1146,14 +1141,16 @@ public final void setLargeMaxRows(long max) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setQueryTimeout"); } - /* L0 */ public final int getCancelQueryTimeout() throws SQLServerException { + @Override + public final int getCancelQueryTimeout() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getCancelQueryTimeout"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getCancelQueryTimeout", cancelQueryTimeoutSeconds); return cancelQueryTimeoutSeconds; } - /* L0 */ public final void setCancelQueryTimeout(int seconds) throws SQLServerException { + @Override + public final void setCancelQueryTimeout(int seconds) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setCancelQueryTimeout", seconds); checkClosed(); if (seconds < 0) { @@ -1165,6 +1162,7 @@ public final void setLargeMaxRows(long max) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setCancelQueryTimeout"); } + @Override public final void cancel() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "cancel"); checkClosed(); @@ -1177,7 +1175,8 @@ public final void cancel() throws SQLServerException { Vector sqlWarnings; // the SQL warnings chain - /* L0 */ public final SQLWarning getWarnings() throws SQLServerException { + @Override + public final SQLWarning getWarnings() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getWarnings"); checkClosed(); if (sqlWarnings == null) @@ -1187,14 +1186,16 @@ public final void cancel() throws SQLServerException { return warn; } - /* L0 */ public final void clearWarnings() throws SQLServerException { + @Override + public final void clearWarnings() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "clearWarnings"); checkClosed(); sqlWarnings = null; loggerExternal.exiting(getClassNameLogging(), "clearWarnings"); } - /* L0 */ public final void setCursorName(String name) throws SQLServerException { + @Override + public final void setCursorName(String name) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setCursorName", name); checkClosed(); cursorName = name; @@ -1205,6 +1206,7 @@ final String getCursorName() { return cursorName; } + @Override public final java.sql.ResultSet getResultSet() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getResultSet"); checkClosed(); @@ -1212,7 +1214,8 @@ public final java.sql.ResultSet getResultSet() throws SQLServerException { return resultSet; } - /* L0 */ public final int getUpdateCount() throws SQLServerException { + @Override + public final int getUpdateCount() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getUpdateCount"); checkClosed(); @@ -1226,8 +1229,8 @@ public final java.sql.ResultSet getResultSet() throws SQLServerException { return (int) updateCount; } + @Override public final long getLargeUpdateCount() throws SQLServerException { - DriverJDBCVersion.checkSupportsJDBC42(); loggerExternal.entering(getClassNameLogging(), "getUpdateCount"); checkClosed(); @@ -1298,7 +1301,8 @@ final void processResults() throws SQLServerException { * @return true if the next result is a ResultSet object; false if it is an integer (indicating that it is an update count or there are no more * results). */ - /* L0 */ public final boolean getMoreResults() throws SQLServerException { + @Override + public final boolean getMoreResults() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getMoreResults"); checkClosed(); @@ -1588,14 +1592,7 @@ boolean onInfo(TDSReader tdsReader) throws SQLServerException { // Not an error. Is it a result set? else if (nextResult.isResultSet()) { - // Make sure SQLServerResultSet42 is used for 4.2 and above - if (Util.use42Wrapper() || Util.use43Wrapper()) { - resultSet = new SQLServerResultSet42(this); - } - else { - resultSet = new SQLServerResultSet(this); - } - + resultSet = new SQLServerResultSet(this); return true; } @@ -1646,6 +1643,7 @@ boolean consumeExecOutParam(TDSReader tdsReader) throws SQLServerException { // --------------------------JDBC 2.0----------------------------- + @Override public final void setFetchDirection(int nDir) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setFetchDirection", nDir); @@ -1663,6 +1661,7 @@ public final void setFetchDirection(int nDir) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setFetchDirection"); } + @Override public final int getFetchDirection() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFetchDirection"); checkClosed(); @@ -1670,7 +1669,8 @@ public final int getFetchDirection() throws SQLServerException { return nFetchDirection; } - /* L0 */ public final void setFetchSize(int rows) throws SQLServerException { + @Override + public final void setFetchSize(int rows) throws SQLServerException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "setFetchSize", rows); checkClosed(); @@ -1681,27 +1681,31 @@ public final int getFetchDirection() throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "setFetchSize"); } - /* L0 */ public final int getFetchSize() throws SQLServerException { + @Override + public final int getFetchSize() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getFetchSize"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getFetchSize", nFetchSize); return nFetchSize; } - /* L0 */ public final int getResultSetConcurrency() throws SQLServerException { + @Override + public final int getResultSetConcurrency() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getResultSetConcurrency"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getResultSetConcurrency", resultSetConcurrency); return resultSetConcurrency; } - /* L0 */ public final int getResultSetType() throws SQLServerException { + @Override + public final int getResultSetType() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getResultSetType"); checkClosed(); loggerExternal.exiting(getClassNameLogging(), "getResultSetType", appResultSetType); return appResultSetType; } + @Override public void addBatch(String sql) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "addBatch", sql); checkClosed(); @@ -1715,6 +1719,7 @@ public void addBatch(String sql) throws SQLServerException { loggerExternal.exiting(getClassNameLogging(), "addBatch"); } + @Override public void clearBatch() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "clearBatch"); checkClosed(); @@ -1725,6 +1730,7 @@ public void clearBatch() throws SQLServerException { /** * Send a batch of statements to the database. */ + @Override public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQLTimeoutException { loggerExternal.entering(getClassNameLogging(), "executeBatch"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1802,8 +1808,8 @@ public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQL } } // executeBatch + @Override public long[] executeLargeBatch() throws SQLServerException, BatchUpdateException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); loggerExternal.entering(getClassNameLogging(), "executeLargeBatch"); if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) { @@ -1888,7 +1894,8 @@ public long[] executeLargeBatch() throws SQLServerException, BatchUpdateExceptio * when an error occurs * @return the connection */ - /* L0 */ public final java.sql.Connection getConnection() throws SQLServerException { + @Override + public final java.sql.Connection getConnection() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getConnection"); if (bIsClosed) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_statementIsClosed"), null, false); @@ -1989,7 +1996,8 @@ private void doExecuteCursored(StmtExecCmd execCmd, /* JDBC 3.0 */ - /* L3 */ public final int getResultSetHoldability() throws SQLException { + @Override + public final int getResultSetHoldability() throws SQLException { loggerExternal.entering(getClassNameLogging(), "getResultSetHoldability"); checkClosed(); int holdability = connection.getHoldability(); // For SQL Server must be the same as the connection @@ -1997,6 +2005,7 @@ private void doExecuteCursored(StmtExecCmd execCmd, return holdability; } + @Override public final boolean execute(java.lang.String sql, int autoGeneratedKeys) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) { @@ -2017,6 +2026,7 @@ public final boolean execute(java.lang.String sql, return null != resultSet; } + @Override public final boolean execute(java.lang.String sql, int[] columnIndexes) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2030,6 +2040,7 @@ public final boolean execute(java.lang.String sql, return fSuccess; } + @Override public final boolean execute(java.lang.String sql, java.lang.String[] columnNames) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2043,6 +2054,7 @@ public final boolean execute(java.lang.String sql, return fSuccess; } + @Override public final int executeUpdate(String sql, int autoGeneratedKeys) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) { @@ -2068,9 +2080,9 @@ public final int executeUpdate(String sql, return (int) updateCount; } + @Override public final long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLServerException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) { loggerExternal.entering(getClassNameLogging(), "executeLargeUpdate", new Object[] {sql, autoGeneratedKeys}); @@ -2089,6 +2101,7 @@ public final long executeLargeUpdate(String sql, return updateCount; } + @Override public final int executeUpdate(java.lang.String sql, int[] columnIndexes) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2102,9 +2115,9 @@ public final int executeUpdate(java.lang.String sql, return count; } + @Override public final long executeLargeUpdate(java.lang.String sql, int[] columnIndexes) throws SQLServerException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "executeLargeUpdate", new Object[] {sql, columnIndexes}); @@ -2117,6 +2130,7 @@ public final long executeLargeUpdate(java.lang.String sql, return count; } + @Override public final int executeUpdate(java.lang.String sql, String[] columnNames) throws SQLServerException, SQLTimeoutException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) @@ -2130,9 +2144,9 @@ public final int executeUpdate(java.lang.String sql, return count; } + @Override public final long executeLargeUpdate(java.lang.String sql, String[] columnNames) throws SQLServerException, SQLTimeoutException { - DriverJDBCVersion.checkSupportsJDBC42(); if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "executeLargeUpdate", new Object[] {sql, columnNames}); @@ -2145,6 +2159,7 @@ public final long executeLargeUpdate(java.lang.String sql, return count; } + @Override public final ResultSet getGeneratedKeys() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getGeneratedKeys"); checkClosed(); @@ -2166,12 +2181,14 @@ public final ResultSet getGeneratedKeys() throws SQLServerException { return autoGeneratedKeys; } - /* L3 */ public final boolean getMoreResults(int mode) throws SQLServerException { + @Override + public final boolean getMoreResults(int mode) throws SQLException { if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getMoreResults", mode); checkClosed(); - if (KEEP_CURRENT_RESULT == mode) - NotImplemented(); + if (KEEP_CURRENT_RESULT == mode) { + SQLServerException.throwNotSupportedException(connection, this); + } if (CLOSE_CURRENT_RESULT != mode && CLOSE_ALL_RESULTS != mode) SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_modeSuppliedNotValid"), null, true); @@ -2191,6 +2208,7 @@ public final ResultSet getGeneratedKeys() throws SQLServerException { return fResults; } + @Override public boolean isClosed() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isClosed"); boolean result = bIsClosed || connection.isSessionUnAvailable(); @@ -2198,6 +2216,7 @@ public boolean isClosed() throws SQLException { return result; } + @Override public boolean isCloseOnCompletion() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isCloseOnCompletion"); checkClosed(); @@ -2205,6 +2224,7 @@ public boolean isCloseOnCompletion() throws SQLException { return isCloseOnCompletion; } + @Override public boolean isPoolable() throws SQLException { loggerExternal.entering(getClassNameLogging(), "isPoolable"); checkClosed(); @@ -2212,6 +2232,7 @@ public boolean isPoolable() throws SQLException { return stmtPoolable; } + @Override public void setPoolable(boolean poolable) throws SQLException { loggerExternal.entering(getClassNameLogging(), "setPoolable", poolable); checkClosed(); @@ -2219,6 +2240,7 @@ public void setPoolable(boolean poolable) throws SQLException { loggerExternal.exiting(getClassNameLogging(), "setPoolable"); } + @Override public boolean isWrapperFor(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "isWrapperFor"); boolean f = iface.isInstance(this); @@ -2226,6 +2248,7 @@ public boolean isWrapperFor(Class iface) throws SQLException { return f; } + @Override public T unwrap(Class iface) throws SQLException { loggerExternal.entering(getClassNameLogging(), "unwrap"); T t; @@ -2257,6 +2280,8 @@ public T unwrap(Class iface) throws SQLException { // Enables handling very large responses, values // Disadvantages // Reduced concurrency on the server + + @Override public final void setResponseBuffering(String value) throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "setResponseBuffering", value); checkClosed(); @@ -2276,6 +2301,7 @@ else if ("adaptive".equalsIgnoreCase(value)) { loggerExternal.exiting(getClassNameLogging(), "setResponseBuffering"); } + @Override public final String getResponseBuffering() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getResponseBuffering"); checkClosed(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java index 424fe52ce..ad7a73a4a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java @@ -29,7 +29,7 @@ public final class SQLServerXAConnection extends SQLServerPooledConnection imple private SQLServerConnection physicalControlConnection; private Logger xaLogger; - /* L0 */ SQLServerXAConnection(SQLServerDataSource ds, + SQLServerXAConnection(SQLServerDataSource ds, String user, String pwd) throws java.sql.SQLException { super(ds, user, pwd); @@ -60,7 +60,8 @@ public final class SQLServerXAConnection extends SQLServerPooledConnection imple xaLogger.finer(ds.toString() + " user:" + user); } - /* L0 */ public synchronized XAResource getXAResource() throws java.sql.SQLException { + @Override + public synchronized XAResource getXAResource() throws java.sql.SQLException { // All connections handed out from this physical connection have a common XAResource // for transaction control. IE the XAResource is one to one with the physical connection. @@ -72,6 +73,7 @@ public final class SQLServerXAConnection extends SQLServerPooledConnection imple /** * Closes the physical connection that this PooledConnection object represents. */ + @Override public void close() throws SQLException { synchronized (this) { if (XAResource != null) { @@ -85,5 +87,4 @@ public void close() throws SQLException { } super.close(); } - } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXADataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXADataSource.java index 286ff216d..baaa331ef 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXADataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXADataSource.java @@ -52,7 +52,8 @@ public final class SQLServerXADataSource extends SQLServerConnectionPoolDataSour * @exception SQLException * The database connection failed. */ - /* L0 */ public XAConnection getXAConnection(String user, + @Override + public XAConnection getXAConnection(String user, String password) throws SQLException { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getXAConnection", new Object[] {user, "Password not traced"}); @@ -84,7 +85,8 @@ public final class SQLServerXADataSource extends SQLServerConnectionPoolDataSour * @exception SQLException * The database connection failed. */ - /* L0 */ public XAConnection getXAConnection() throws SQLException { + @Override + public XAConnection getXAConnection() throws SQLException { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getXAConnection"); return getXAConnection(getUser(), getPassword()); @@ -92,6 +94,7 @@ public final class SQLServerXADataSource extends SQLServerConnectionPoolDataSour // Implement javax.naming.Referenceable interface methods. + @Override public Reference getReference() { if (loggerExternal.isLoggable(Level.FINER)) loggerExternal.entering(getClassNameLogging(), "getReference"); @@ -129,5 +132,4 @@ private Object readResolve() { return ds; } } - } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java index be00a276a..7ba25de95 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java @@ -51,7 +51,7 @@ final class XidImpl implements Xid { * @param bqual * branch id */ - /* L0 */ public XidImpl(int formatId, + public XidImpl(int formatId, byte gtrid[], byte bqual[]) { this.formatId = formatId; @@ -60,15 +60,15 @@ final class XidImpl implements Xid { traceID = " XID:" + xidDisplay(this); } - /* L0 */ public byte[] getGlobalTransactionId() { + public byte[] getGlobalTransactionId() { return gtrid; } - /* L0 */ public byte[] getBranchQualifier() { + public byte[] getBranchQualifier() { return bqual; } - /* L0 */ public int getFormatId() { + public int getFormatId() { return formatId; } @@ -172,11 +172,12 @@ public final class SQLServerXAResource implements javax.transaction.xa.XAResourc xaInitLock = new Object(); } + @Override public String toString() { return traceID; } - /* L0 */ SQLServerXAResource(SQLServerConnection original, + SQLServerXAResource(SQLServerConnection original, SQLServerConnection control, String loginfo) { traceID = " XAResourceID:" + nextResourceID(); @@ -358,7 +359,7 @@ private String typeDisplay(int type) { } - /* L0 */ private XAReturnValue DTC_XA_Interface(int nType, + private XAReturnValue DTC_XA_Interface(int nType, Xid xid, int xaFlags) throws XAException { @@ -746,7 +747,8 @@ else if (-1 != version.indexOf('.')) { return returnStatus; } - /* L0 */ public void start(Xid xid, + @Override + public void start(Xid xid, int flags) throws XAException { /* * Transaction mgr will use this resource in the global transaction. After this call the app server will call getConnection() to get a @@ -771,7 +773,8 @@ else if (-1 != version.indexOf('.')) { DTC_XA_Interface(XA_START, xid, flags); } - /* L0 */ public void end(Xid xid, + @Override + public void end(Xid xid, int flags) throws XAException { // Called by the transaction mgr after the app closes the connection it was given from this physical // connection @@ -785,7 +788,8 @@ else if (-1 != version.indexOf('.')) { DTC_XA_Interface(XA_END, xid, flags | tightlyCoupled); } - /* L0 */ public int prepare(Xid xid) throws XAException { + @Override + public int prepare(Xid xid) throws XAException { /* * Ask the resource manager to prepare for a transaction commit of the transaction specified in xid. Parameters: xid - A global transaction * identifier Returns: A value indicating the resource manager's vote on the outcome of the transaction. The possible values are: XA_RDONLY or @@ -799,20 +803,24 @@ else if (-1 != version.indexOf('.')) { return nStatus; } - /* L0 */ public void commit(Xid xid, + @Override + public void commit(Xid xid, boolean onePhase) throws XAException { DTC_XA_Interface(XA_COMMIT, xid, ((onePhase) ? TMONEPHASE : TMNOFLAGS) | tightlyCoupled); } - /* L0 */ public void rollback(Xid xid) throws XAException { + @Override + public void rollback(Xid xid) throws XAException { DTC_XA_Interface(XA_ROLLBACK, xid, tightlyCoupled); } - /* L0 */ public void forget(Xid xid) throws XAException { + @Override + public void forget(Xid xid) throws XAException { DTC_XA_Interface(XA_FORGET, xid, tightlyCoupled); } - /* L0 */ public Xid[] recover(int flags) throws XAException { + @Override + public Xid[] recover(int flags) throws XAException { XAReturnValue r = DTC_XA_Interface(XA_RECOVER, null, flags | tightlyCoupled); int offset = 0; ArrayList al = new ArrayList<>(); @@ -859,7 +867,8 @@ else if (-1 != version.indexOf('.')) { return xids; } - /* L0 */ public boolean isSameRM(XAResource xares) throws XAException { + @Override + public boolean isSameRM(XAResource xares) throws XAException { // A Resource Manager (RM) is an instance of a connection to a DB if (xaLogger.isLoggable(Level.FINER)) @@ -872,7 +881,8 @@ else if (-1 != version.indexOf('.')) { return jxa.sResourceManagerId.equals(this.sResourceManagerId); } - /* L0 */ public boolean setTransactionTimeout(int seconds) throws XAException { + @Override + public boolean setTransactionTimeout(int seconds) throws XAException { isTransacrionTimeoutSet = 1; timeoutSeconds = seconds; @@ -881,7 +891,8 @@ else if (-1 != version.indexOf('.')) { return true; } - /* L0 */ public int getTransactionTimeout() throws XAException { + @Override + public int getTransactionTimeout() throws XAException { return timeoutSeconds; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java b/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java index 0f1287960..99cb4888a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java @@ -1,3 +1,11 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) Microsoft Corporation All rights reserved. + * + * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + package com.microsoft.sqlserver.jdbc; import java.util.Date; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamColumns.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamColumns.java index 3128fb318..e0f5342d9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamColumns.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamColumns.java @@ -8,6 +8,16 @@ package com.microsoft.sqlserver.jdbc; +import java.util.List; + +import com.microsoft.sqlserver.jdbc.dataclassification.ColumnSensitivity; +import com.microsoft.sqlserver.jdbc.dataclassification.InformationType; +import com.microsoft.sqlserver.jdbc.dataclassification.Label; +import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification; +import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityProperty; + +import java.util.ArrayList; + /** * StreamColumns stores the column meta data for a result set. StreamColumns parses the inbound TDS packet stream to determine column meta data. */ @@ -210,6 +220,95 @@ void setFromTDS(TDSReader tdsReader) throws SQLServerException { this.columns[numColumns] = new Column(typeInfo, columnName, tableName, null); } } + + // Data Classification + if (tdsReader.getServerSupportsDataClassification() && tdsReader.peekTokenType() == TDS.TDS_SQLDATACLASSIFICATION) { + // Read and parse + tdsReader.trySetSensitivityClassification(processDataClassification(tdsReader)); + } + } + + private String readByteString(TDSReader tdsReader) throws SQLServerException { + String value = ""; + int byteLen = (int) tdsReader.readUnsignedByte(); + value = tdsReader.readUnicodeString(byteLen); + return value; + } + + private Label readSensitivityLabel(TDSReader tdsReader) throws SQLServerException { + String name = readByteString(tdsReader); + String id = readByteString(tdsReader); + return new Label(name, id); + } + + private InformationType readSensitivityInformationType(TDSReader tdsReader) throws SQLServerException { + String name = readByteString(tdsReader); + String id = readByteString(tdsReader); + return new InformationType(name, id); + } + + private SensitivityClassification processDataClassification(TDSReader tdsReader) throws SQLServerException { + if (!tdsReader.getServerSupportsDataClassification()) { + tdsReader.throwInvalidTDS(); + } + + int dataClassificationToken = tdsReader.readUnsignedByte(); + assert dataClassificationToken == TDS.TDS_SQLDATACLASSIFICATION; + + SensitivityClassification sensitivityClassification = null; + + // get the label count + int numLabels = tdsReader.readUnsignedShort(); + List