Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)

## [7.1.1] Preview Release
### Fixed Issues
- Fixed a bug where calling length() after obtaining a stream would close the stream for Clobs/NClobs [#799](https://github.com/Microsoft/mssql-jdbc/pull/799)
- Fixed issues in Bulk Copy exception handling [#801](https://github.com/Microsoft/mssql-jdbc/pull/801)
- Fixed closeable resource leaks in Junit tests [#797](https://github.com/Microsoft/mssql-jdbc/pull/797)
- Fixed issues with apostrophe being passed in table name [#780](https://github.com/Microsoft/mssql-jdbc/pull/780)
- Fixed statement leaks and improved exception handling in SQLServerParameterMetadata [#780](https://github.com/Microsoft/mssql-jdbc/pull/780)

### Changed
- Changed error message to be thrown when data out of range for DECIMAL/NUMERIC types [#796](https://github.com/Microsoft/mssql-jdbc/pull/796)

## [7.1.0] Preview Release
### Added
- Added support for LocalDate, LocalTime and LocalDateTime to be passed as 'type' in ResultSet.getObject() [#749](https://github.com/Microsoft/mssql-jdbc/pull/749)
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ For some features (e.g. Integrated Authentication and Distributed Transactions),
Don't want to compile anything?

We're now on the Maven Central Repository. Add the following to your POM file to get the most stable release:

```xml
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
Expand All @@ -84,13 +85,15 @@ We're now on the Maven Central Repository. Add the following to your POM file to
The driver can be downloaded from the [Microsoft Download Center](https://go.microsoft.com/fwlink/?linkid=868287).

To get the latest preview version of the driver, add the following to your POM file:

```xml
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.1.0.jre10-preview</version>
<version>7.1.1.jre10-preview</version>
</dependency>
```

### Using driver as Java Module
Starting from version 7.0.0, the driver Jars (jre10 and above) will expose 'Automatic-Module' as **'com.microsoft.sqlserver.jdbc'**. The supporting Jar can now be added to ModulePath to access this module.

Expand All @@ -115,11 +118,12 @@ mvn dependency:tree
Projects that require either of the two features need to explicitly declare the dependency in their pom file.

***For Example:*** If you are using *Azure Active Directory Authentication feature* then you need to redeclare *adal4j* dependency in your project's pom file. Please see the following snippet:

```xml
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.1.0.jre10-preview</version>
<version>7.1.1.jre10-preview</version>
<scope>compile</scope>
</dependency>

Expand All @@ -131,11 +135,12 @@ Projects that require either of the two features need to explicitly declare the
```

***For Example:*** If you are using *Azure Key Vault feature* then you need to redeclare *azure-keyvault* dependency and *adal4j* dependency in your project's pom file. Please see the following snippet:

```xml
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.1.0.jre10-preview</version>
<version>7.1.1.jre10-preview</version>
<scope>compile</scope>
</dependency>

Expand All @@ -151,6 +156,7 @@ Projects that require either of the two features need to explicitly declare the
<version>1.0.0</version>
</dependency>
```

***Please note*** as of the v6.2.2, the way to construct a `SQLServerColumnEncryptionAzureKeyVaultProvider` object has changed. Please refer to this [Wiki](https://github.com/Microsoft/mssql-jdbc/wiki/New-Constructor-Definition-for-SQLServerColumnEncryptionAzureKeyVaultProvider-after-6.2.2-Release) page for more information.

## Guidelines for Creating Pull Requests
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

apply plugin: 'java'

version = '7.1.0'
version = '7.1.1'
def jreVersion = ""
def testOutputDir = file("build/classes/java/test")
def archivesBaseName = 'mssql-jdbc'
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.1.0</version>
<version>7.1.1</version>
<packaging>jar</packaging>

<name>Microsoft JDBC Driver for SQL Server</name>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3132,7 +3132,7 @@ final void endMessage() throws SQLServerException {
// the client MUST send the next packet with both ignore bit (0x02) and EOM bit (0x01)
// set in the status to cancel the request.
final boolean ignoreMessage() throws SQLServerException {
if (packetNum > 0) {
if (packetNum > 0 || TDS.PKT_BULK == this.tdsMessageType) {
assert !isEOMSent;

if (logger.isLoggable(Level.FINER))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ class PLPInputStream extends BaseInputStream {
static final int PLP_TERMINATOR = 0x00000000;
private final static byte[] EMPTY_PLP_BYTES = new byte[0];

// Stated length of the PLP stream payload; -1 if unknown length.
int payloadLength;

private static final int PLP_EOS = -1;
private int currentChunkRemain;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
final class SQLJdbcVersion {
static final int major = 7;
static final int minor = 1;
static final int patch = 0;
static final int patch = 1;
static final int build = 0;
}
28 changes: 6 additions & 22 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java
Original file line number Diff line number Diff line change
Expand Up @@ -1559,22 +1559,6 @@ private boolean doInsertBulk(TDSCommand command) throws SQLServerException {
} finally {
tdsWriter = command.getTDSWriter();
}
} catch (SQLServerException ex) {
if (null == tdsWriter) {
tdsWriter = command.getTDSWriter();
}

// Close the TDS packet before handling the exception
writePacketDataDone(tdsWriter);

// Send Attention packet to interrupt a complete request that was already sent to the server
command.startRequest(TDS.PKT_CANCEL_REQ);

TDSParser.parse(command.startResponse(), command.getLogContext());
command.interrupt(ex.getMessage());
command.onRequestComplete();

throw ex;
} finally {
if (null == tdsWriter) {
tdsWriter = command.getTDSWriter();
Expand Down Expand Up @@ -1728,8 +1712,8 @@ private void getDestinationMetadata() throws SQLServerException {
ResultSet.CONCUR_READ_ONLY, connection.getHoldability(), stmtColumnEncriptionSetting);

// Get destination metadata
rs = stmt.executeQueryInternal(
"sp_executesql N'SET FMTONLY ON SELECT * FROM " + destinationTableName + " '");
rs = stmt.executeQueryInternal("sp_executesql N'SET FMTONLY ON SELECT * FROM "
+ Util.escapeSingleQuotes(destinationTableName) + " '");
}

destColumnCount = rs.getMetaData().getColumnCount();
Expand All @@ -1740,11 +1724,11 @@ private void getDestinationMetadata() throws SQLServerException {
// SQL server prior to 2016 does not support encryption_type
rsMoreMetaData = ((SQLServerStatement) connection.createStatement())
.executeQueryInternal("select collation_name from sys.columns where " + "object_id=OBJECT_ID('"
+ destinationTableName + "') " + "order by column_id ASC");
+ Util.escapeSingleQuotes(destinationTableName) + "') " + "order by column_id ASC");
} else {
rsMoreMetaData = ((SQLServerStatement) connection.createStatement())
.executeQueryInternal("select collation_name, encryption_type from sys.columns where "
+ "object_id=OBJECT_ID('" + destinationTableName + "') " + "order by column_id ASC");
rsMoreMetaData = ((SQLServerStatement) connection.createStatement()).executeQueryInternal(
"select collation_name, encryption_type from sys.columns where " + "object_id=OBJECT_ID('"
+ Util.escapeSingleQuotes(destinationTableName) + "') " + "order by column_id ASC");
}
for (int i = 1; i <= destColumnCount; ++i) {
if (rsMoreMetaData.next()) {
Expand Down
50 changes: 35 additions & 15 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

package com.microsoft.sqlserver.jdbc;

import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_16LE;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -20,6 +18,7 @@
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.MessageFormat;
Expand Down Expand Up @@ -152,7 +151,7 @@ abstract class SQLServerClobBase extends SQLServerLob implements Serializable {

// The value of the CLOB that this Clob object represents.
// This value is never null unless/until the free() method is called.
private String value;
protected String value;

private final SQLCollation sqlCollation;

Expand Down Expand Up @@ -181,8 +180,9 @@ final public String toString() {
// Unique id generator for each instance (used for logging).
static private final AtomicInteger baseID = new AtomicInteger(0);

private Charset defaultCharset = null;

// Returns unique id for each instance.

private static int nextInstanceID() {
return baseID.incrementAndGet();
}
Expand Down Expand Up @@ -281,9 +281,19 @@ public InputStream getAsciiStream() throws SQLException {
if (null != sqlCollation && !sqlCollation.supportsAsciiConversion())
DataTypes.throwConversionError(getDisplayClassName(), "AsciiStream");

getStringFromStream();
InputStream getterStream = new BufferedInputStream(
new ReaderInputStream(new StringReader(value), US_ASCII, value.length()));
// Need to use a BufferedInputStream since the stream returned by this method is assumed to support mark/reset
InputStream getterStream = null;
if (null == value && !activeStreams.isEmpty()) {
InputStream inputStream = (InputStream) activeStreams.get(0);
try {
inputStream.reset();
} catch (IOException e) {
SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false);
}
getterStream = new BufferedInputStream(inputStream);
} else {
getterStream = new ByteArrayInputStream(value.getBytes(java.nio.charset.StandardCharsets.US_ASCII));
}
activeStreams.add(getterStream);
return getterStream;
}
Expand All @@ -301,11 +311,17 @@ public Reader getCharacterStream() throws SQLException {
Reader getterStream = null;
if (null == value && !activeStreams.isEmpty()) {
InputStream inputStream = (InputStream) activeStreams.get(0);
getterStream = new BufferedReader(new InputStreamReader(inputStream, UTF_16LE));
try {
inputStream.reset();
} catch (IOException e) {
SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false);
}
Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset;
getterStream = new BufferedReader(new InputStreamReader(inputStream, cs));
} else {
getterStream = new StringReader(value);
activeStreams.add(getterStream);
}
activeStreams.add(getterStream);
return getterStream;
}

Expand Down Expand Up @@ -381,9 +397,8 @@ public String getSubString(long pos, int length) throws SQLException {
*/
public long length() throws SQLException {
checkClosed();

if (value == null && activeStreams.get(0) instanceof PLPInputStream) {
return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2;
if (null == value && activeStreams.get(0) instanceof BaseInputStream) {
return (long) ((BaseInputStream) activeStreams.get(0)).payloadLength;
}
return value.length();
}
Expand All @@ -410,9 +425,10 @@ private void getStringFromStream() throws SQLServerException {
try {
stream.reset();
} catch (IOException e) {
throw new SQLServerException(e.getMessage(), null, 0, e);
SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false);
}
value = new String((stream).getBytes(), typeInfo.getCharset());
Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset;
value = new String(stream.getBytes(), cs);
}
}

Expand Down Expand Up @@ -661,6 +677,10 @@ public int setString(long pos, String str, int offset, int len) throws SQLExcept

return len;
}

protected void setDefaultCharset(Charset c) {
this.defaultCharset = c;
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum SQLState {
STATEMENT_CANCELED("HY008"),
DATA_EXCEPTION_NOT_SPECIFIC("22000"),
DATA_EXCEPTION_DATETIME_FIELD_OVERFLOW("22008"),
NUMERIC_DATA_OUT_OF_RANGE("22003"),
DATA_EXCEPTION_LENGTH_MISMATCH("22026"),
COL_NOT_FOUND("42S22");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ public final class SQLServerNClob extends SQLServerClobBase implements NClob {

SQLServerNClob(SQLServerConnection connection) {
super(connection, "", connection.getDatabaseCollation(), logger, null);
this.setDefaultCharset(java.nio.charset.StandardCharsets.UTF_16LE);
}

SQLServerNClob(BaseInputStream stream, TypeInfo typeInfo) throws SQLServerException, UnsupportedEncodingException {
super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo);
this.setDefaultCharset(java.nio.charset.StandardCharsets.UTF_16LE);
}

@Override
Expand All @@ -45,6 +47,9 @@ public void free() throws SQLException {

@Override
public InputStream getAsciiStream() throws SQLException {
// NClobs are mapped to Nvarchar(max), and are always UTF-16 encoded. This API expects a US_ASCII stream.
// It's not possible to modify the stream without loading it into memory. Users should use getCharacterStream.
this.fillFromStream();
return super.getAsciiStream();
}

Expand All @@ -65,7 +70,9 @@ public String getSubString(long pos, int length) throws SQLException {

@Override
public long length() throws SQLException {
return super.length();
// If streaming, every 2 bytes represents 1 character. If not, length() just returns string length
long length = super.length();
return (null == value) ? length / 2 : length;
}

@Override
Expand Down
Loading