Skip to content

Commit

Permalink
Backport 2379/2383 (#2419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeffery-Wasty authored May 22, 2024
1 parent 312092b commit e411e0b
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 15 deletions.
4 changes: 3 additions & 1 deletion src/main/java/com/microsoft/sqlserver/jdbc/DDC.java
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,14 @@ static final byte[] convertBigDecimalToBytes(BigDecimal bigDecimalVal, int scale
return valueBytes;
}

static final byte[] convertMoneyToBytes(BigDecimal bigDecimalVal, int bLength) {
static final byte[] convertMoneyToBytes(BigDecimal bigDecimalVal, int bLength) throws SQLServerException {
byte[] valueBytes = new byte[bLength];

BigInteger bi = bigDecimalVal.unscaledValue();

if (bLength == 8) {
// money
Util.validateMoneyRange(bigDecimalVal, JDBCType.MONEY);
byte[] longbArray = new byte[bLength];
Util.writeLong(bi.longValue(), longbArray, 0);
/*
Expand All @@ -362,6 +363,7 @@ static final byte[] convertMoneyToBytes(BigDecimal bigDecimalVal, int bLength) {
System.arraycopy(longbArray, 4, valueBytes, 0, 4);
} else {
// smallmoney
Util.validateMoneyRange(bigDecimalVal, JDBCType.SMALLMONEY);
Util.writeInt(bi.intValue(), valueBytes, 0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,33 @@
*/
package com.microsoft.sqlserver.jdbc.bulkCopy;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import javax.sql.RowSetMetaData;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetMetaDataImpl;
import javax.sql.rowset.RowSetProvider;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
Expand All @@ -20,8 +40,10 @@
import com.microsoft.sqlserver.jdbc.ComparisonUtil;
import com.microsoft.sqlserver.jdbc.RandomData;
import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCSVFileRecord;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions;
import com.microsoft.sqlserver.jdbc.TestResource;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;
Expand All @@ -31,20 +53,6 @@
import com.microsoft.sqlserver.testframework.DBTable;
import com.microsoft.sqlserver.testframework.PrepUtil;

import javax.sql.RowSetMetaData;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetMetaDataImpl;
import javax.sql.rowset.RowSetProvider;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


@RunWith(JUnitPlatform.class)
public class BulkCopyAllTypesTest extends AbstractTest {
Expand All @@ -55,12 +63,26 @@ public class BulkCopyAllTypesTest extends AbstractTest {
@BeforeAll
public static void setupTests() throws Exception {
setConnection();
setupMoneyTests();
}

public static void setupMoneyTests() throws SQLException {
try (Connection con = getConnection(); Statement stmt = con.createStatement()) {
TestUtils.dropTableIfExists(destTableName, stmt);
TestUtils.dropTableIfExists(destTableName2, stmt);

String table = "create table " + destTableName + " (c1 smallmoney, c2 money)";
stmt.execute(table);
table = "create table " + destTableName2 + " (c1 smallmoney, c2 money)";
stmt.execute(table);
}
}

/**
* Test TVP with result set
*
* @throws SQLException
* an exception
*/
@Test
@Tag(Constants.xAzureSQLDW)
Expand Down Expand Up @@ -185,4 +207,80 @@ public void testBulkCopyTimestamp() throws SQLException {
private static long getTime(Timestamp time) {
return (3 * time.getTime() + 5) / 10;
}

static String encoding = Constants.UTF8;
static String delimiter = Constants.COMMA;
static String destTableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("moneyBulkCopyDest"));
static String destTableName2 = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("moneyBulkCopyDest"));

/**
* Test money/smallmoney with BulkCopy
*
* @throws SQLException
* an exception
*/
@Test
public void testMoneyWithBulkCopy() throws Exception {
try (Connection conn = PrepUtil.getConnection(connectionString)) {
testMoneyLimits(Constants.MIN_VALUE_SMALLMONEY - 1, Constants.MAX_VALUE_MONEY - 1, conn); // 1 less than SMALLMONEY MIN
testMoneyLimits(Constants.MAX_VALUE_SMALLMONEY + 1, Constants.MAX_VALUE_MONEY - 1, conn); // 1 more than SMALLMONEY MAX
testMoneyLimits(Constants.MAX_VALUE_SMALLMONEY - 1, Constants.MIN_VALUE_MONEY - 1, conn); // 1 less than MONEY MIN
testMoneyLimits(Constants.MAX_VALUE_SMALLMONEY - 1, Constants.MAX_VALUE_MONEY + 1, conn); // 1 more than MONEY MAX
}
}

private void testMoneyLimits(double smallMoneyVal, double moneyVal, Connection conn) throws Exception {
SQLServerBulkCSVFileRecord fileRecord = constructFileRecord(smallMoneyVal, moneyVal);

try {
testMoneyWithBulkCopy(conn, fileRecord);
fail(TestResource.getResource("R_expectedExceptionNotThrown"));
} catch (SQLException e) {
assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_valueOutOfRange")), e.getMessage());
}
}

private SQLServerBulkCSVFileRecord constructFileRecord(double smallMoneyVal, double moneyVal) throws Exception {
Map<Object, Object> data = new HashMap();
data.put(smallMoneyVal, moneyVal);

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("smallmoneycol, moneycol\n");

for (Map.Entry entry : data.entrySet()) {
stringBuilder.append(String.format("%s,%s\n", entry.getKey(), entry.getValue()));
}

byte[] bytes = stringBuilder.toString().getBytes(StandardCharsets.UTF_8);
SQLServerBulkCSVFileRecord fileRecord;
try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
fileRecord = new SQLServerBulkCSVFileRecord(inputStream, encoding, delimiter, true);
}
return fileRecord;
}

private void testMoneyWithBulkCopy(Connection conn, SQLServerBulkCSVFileRecord fileRecord) throws SQLException {
try (SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(conn); Statement stmt = conn.createStatement()) {

fileRecord.addColumnMetadata(1, "c1", java.sql.Types.DECIMAL, 10, 4); // with smallmoney
fileRecord.addColumnMetadata(2, "c2", java.sql.Types.DECIMAL, 19, 4); // with money

bulkCopy.setDestinationTableName(destTableName);
bulkCopy.writeToServer(fileRecord);

try (ResultSet rs = stmt.executeQuery("select * FROM " + destTableName + " order by c1");
SQLServerBulkCopy bcOperation = new SQLServerBulkCopy(conn)) {
bcOperation.setDestinationTableName(destTableName2);
bcOperation.writeToServer(rs);
}
}
}

@AfterAll
public static void cleanUp() throws Exception {
try (Connection con = getConnection(); Statement stmt = con.createStatement()) {
TestUtils.dropTableIfExists(destTableName, stmt);
TestUtils.dropTableIfExists(destTableName2, stmt);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ private Constants() {}
public static final String SEND_TEMPORAL_DATATYPES_AS_STRING_FOR_BULK_COPY = "SENDTEMPORALDATATYPESASSTRINGFORBULKCOPY";
public static final String PREPARE_METHOD = "PREPAREMETHOD";
public static final String CONFIG_PROPERTIES_FILE = "config.properties";
public static final String UTF8 = "UTF-8";
public static final double MAX_VALUE_MONEY = 922337203685477.5807;
public static final double MIN_VALUE_MONEY = -922337203685477.5808;
public static final double MAX_VALUE_SMALLMONEY = 214748.3647;
public static final double MIN_VALUE_SMALLMONEY = -214748.3648;

public enum LOB {
CLOB,
Expand Down

0 comments on commit e411e0b

Please sign in to comment.