diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Tables.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Tables.java deleted file mode 100644 index 1783f0d2b..000000000 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Tables.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) 2016 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.bvt; -import static org.junit.Assert.fail; - -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; - -public class Tables { - static String query = ""; - static String name = ""; - private static String create_Table_sql = ""; - private static String drop_Table_Query = ""; - private static final String primary_key = "[c26_int]"; - - public static String createTable(String tableName) { - create_Table_sql = "CREATE TABLE " + tableName + "([c1_char(512)] char(512)," + " [c2_date] date, " - + "[c3_decimal(28,4)] decimal(28,4)," + " [c4_money] money," + " [c5_time] time, " - + "[c6_uniqueidentifier] uniqueidentifier," + " [c7_varchar(max)] varchar(max), " - + "[c8_nvarchar(max)] nvarchar(max)," + " [c9_smallint] smallint, " - + "[c10_numeric(28,4)] numeric(28,4), " + "[c11_ntext] ntext, " - + "[c12_varbinary(max)] varbinary(max), " + "[c13_nchar(512)] nchar(512), " - + "[c14_datetimeoffset(7)] datetimeoffset(7), " + "[c15_xml] xml," - + " [c16_smalldatetime] smalldatetime," + " [c17_varbinary(512)] varbinary(512), " + "[c18_bit] bit, " - + "[c19_varchar(512)] varchar(512), " + "[c20_real] real, " + "[c21_tinyint] tinyint," - + " [c22_float] float, " + "[c23_text] text, " + "[c24_binary(512)] binary(512)," - + " [c25_datetime2] datetime2," + " [c26_int] int NOT NULL PRIMARY KEY, " + "[c27_datetime] datetime," - + " [c28_bigint] bigint," + " [c29_nvarchar(512)] nvarchar(512), " + "[c30_smallmoney] smallmoney," - + "[c31_int] int" + ")"; - return create_Table_sql; - } - - public static String dropTable(String tableName) { - drop_Table_Query = "if object_id('" + tableName + "','U') is not null" + " drop table " + tableName; - return drop_Table_Query; - } - - public static String select(String tableName) { - return query = "SELECt * FROM " + tableName; - } - - public static String select_Orderby(String tableName, String column) { - return "SELECt * FROM " + tableName + " order by " + column; - } - - public static String orderby(String column) { - - if (query.contains("order")) - return query = query + ", " + column; - else - return query = query + " order by " + column; - - } - - public static String primaryKey() { - return primary_key; - } - - public static void populate(String tableName, Statement stmt) { - ArrayList valuesPerRow = null; - for (int i = 0; i < Values.getRowNumbers(); i++) { - valuesPerRow = Values.getTableValues(i); - String populate_query = createInsertSQL(tableName, valuesPerRow); - try { - stmt.executeUpdate(populate_query); - } catch (SQLException e) { - fail(e.toString()); - } - } - } - - private static String createInsertSQL(String tableName, ArrayList valuesPerRow) { - String sql = "INSERT into " + tableName + " values (" + "'" + valuesPerRow.get(0) + "', '" + valuesPerRow.get(1) - + "', " + valuesPerRow.get(2) + "," + valuesPerRow.get(3) + ", '" + valuesPerRow.get(4) + "','" - + valuesPerRow.get(5) + "','" + valuesPerRow.get(6) + "','" + valuesPerRow.get(7) + "', " - + valuesPerRow.get(8) + ", " + valuesPerRow.get(9) + ",N'" + valuesPerRow.get(10) + "', " - + valuesPerRow.get(11) + ", '" + valuesPerRow.get(12) + "',' " + valuesPerRow.get(13) + "',' " - + valuesPerRow.get(14) + "','" + valuesPerRow.get(15) + "'," + valuesPerRow.get(16) + ",'" - + valuesPerRow.get(17) + "','" + valuesPerRow.get(18) + "'," + valuesPerRow.get(19) + ", " - + valuesPerRow.get(20) + ", " + valuesPerRow.get(21) + ",'" + valuesPerRow.get(22) + "', " - + valuesPerRow.get(23) + ",' " + valuesPerRow.get(24) + "', " + valuesPerRow.get(25) + ",' " - + valuesPerRow.get(26) + "', " + valuesPerRow.get(27) + ", '" + valuesPerRow.get(28) + "', " - + valuesPerRow.get(29) + ", " + valuesPerRow.get(30) + " )"; - - return sql; - } -} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Values.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Values.java deleted file mode 100644 index 492a31ac9..000000000 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/Values.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) 2016 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.bvt; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Random; -import java.util.UUID; - -import microsoft.sql.DateTimeOffset; - -public class Values { - - private static ArrayList valuesPerRow; - private static ArrayList> tableValues; - private static String normalCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - private static int rowNumbers; - private static long max; - private static long min; - private static long avg; - private static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', - 'F' }; - private static Random r = new Random(); - - public static int getRowNumbers() { - return rowNumbers; - } - - public static void createData() { - - String[] char512 = { generateCharTypes("512", false), generateCharTypes("1", false), - generateCharTypes("225", false) }; - - Date[] date = { Date.valueOf("9999-12-31"), Date.valueOf("0001-01-01"), Date.valueOf("2011-01-11") }; - - BigDecimal[] decimal = { new BigDecimal("999999999999999999999999.9999"), - new BigDecimal("-999999999999999999999999.9999"), new BigDecimal("1234.1234") }; - - BigDecimal[] money = { new BigDecimal("922337203685477.5807"), new BigDecimal("-922337203685477.5808"), - new BigDecimal("-522337203685477.1234") }; - - max = Timestamp.valueOf("9999-12-31 23:59:59").getTime(); - min = Timestamp.valueOf("0001-01-01 00:00:00").getTime(); - avg = Timestamp.valueOf("2011-01-11 00:00:00").getTime(); - Time[] time = { Time.valueOf("23:59:59"), Time.valueOf("00:00:00"), Time.valueOf("05:23:00") }; - - String[] guid = { "" + UUID.randomUUID(), "" + UUID.randomUUID(), "" + UUID.randomUUID() }; - - String[] varcharMax = { generateCharTypes("max", false), generateCharTypes("1", false), - generateCharTypes("225", false) }; - - String[] nVarcharMax = { generateNCharTypes("max", false), generateNCharTypes("1", false), - generateNCharTypes("225", false) }; - - Short[] smallint = { new Short(Short.MAX_VALUE), new Short(Short.MIN_VALUE), 5 }; - - BigDecimal[] numeric = { new BigDecimal("999999999999999999999999.9999"), - new BigDecimal("-999999999999999999999999.9999"), new BigDecimal("1234.1234") }; - - String[] ntext = { "林ན་དགོས་ཏེ།ངག་ཕྱོαβγδεζη", "जंतुआपेड़पौधाकेमिलल太陽系の年齢もま", "放我放问역사적으" }; - - String[] varbinaryMax = { "0x" + toString(generateBinaryTypes("max", false)), - "0x" + toString(generateBinaryTypes("max", false)), - "0x" + toString(generateBinaryTypes("max", false)) }; - - String[] nchar512 = { generateNCharTypes("512", false), generateNCharTypes("0", false), - generateNCharTypes("225", false) }; - - DateTimeOffset maxDTS = calculateDateTimeOffsetMinMax("max", 7, "9999-12-31 23:59:59"); - DateTimeOffset minDTS = calculateDateTimeOffsetMinMax("min", 7, "0001-01-01 00:00:00"); - DateTimeOffset[] dto = { maxDTS, minDTS, minDTS }; - - String[] xml = { "1EMP", - "1EMP", - "1EMP" }; - - max = Timestamp.valueOf("2079-06-06 23:59:00").getTime(); - min = Timestamp.valueOf("1900-01-01 00:00:00").getTime(); - Timestamp[] smallDatetime = { new Timestamp(max), new Timestamp(min), new Timestamp(min) }; - - String[] varbinary512 = { "0x633234", "0x633234", "0x633234" }; - - max = Timestamp.valueOf("9999-12-31 23:59:59.997").getTime(); - min = Timestamp.valueOf("1753-01-01 00:00:00.000").getTime(); - Timestamp[] Datetime = { new Timestamp(max), new Timestamp(min), new Timestamp(min) }; - - max = Timestamp.valueOf("9999-12-31 23:59:59").getTime(); - min = Timestamp.valueOf("0001-01-01 00:00:00").getTime(); - Timestamp[] Datetime2 = { new Timestamp(max), new Timestamp(min), new Timestamp(min) }; - - Float[] real = { Float.valueOf("3.4E38"), Float.valueOf("-3.4E38"), Float.valueOf("10.0") }; - - Short[] tinyint = { Short.valueOf("255"), Short.valueOf("0"), Short.valueOf("125") }; - - Double[] floatVal = { new Double(+1.79E308), new Double(-1.79E308), new Double(10.0) }; - - String[] text = { "text", "text", "text" }; - - String[] binary512 = { "0x" + toString(generateBinaryTypes("512", false)), - "0x" + toString(generateBinaryTypes("512", false)), - "0x" + toString(generateBinaryTypes("512", false)) }; - - Integer[] intVal = { new Integer(Integer.MAX_VALUE), new Integer(Integer.MIN_VALUE), 10 }; - - Long[] bigInt = { new Long(Long.MAX_VALUE), new Long(Long.MIN_VALUE), (long) 10 }; - - String[] nvarchar512 = { generateNCharTypes("512", false), generateNCharTypes("0", false), - generateNCharTypes("225", false) }; - - BigDecimal[] smallmoney = { new BigDecimal("214748.3647"), new BigDecimal("-214748.3648"), - new BigDecimal("10.0000") }; - - String[] bit = { "true", "false", "true" }; - - String[] varchar512 = { generateCharTypes("512", false), generateCharTypes("1", false), - generateCharTypes("225", false) }; - - tableValues = new ArrayList>(); - rowNumbers = 0; - - for (int i = 0; i < 3; i++) { - valuesPerRow = new ArrayList(); - - valuesPerRow.add(char512[i]); - valuesPerRow.add(date[i]); - valuesPerRow.add(decimal[i]); - valuesPerRow.add(money[i]); - valuesPerRow.add(time[i]); - valuesPerRow.add(guid[i]); - valuesPerRow.add(varcharMax[i]); - valuesPerRow.add(nVarcharMax[i]); - valuesPerRow.add(smallint[i]); - valuesPerRow.add(numeric[i]); - valuesPerRow.add(ntext[i]); - valuesPerRow.add(varbinaryMax[i]); - valuesPerRow.add(nchar512[i]); - valuesPerRow.add(dto[i]); - valuesPerRow.add(xml[i]); - valuesPerRow.add(smallDatetime[i]); - valuesPerRow.add(varbinary512[i]); - valuesPerRow.add(bit[i]); - valuesPerRow.add(varchar512[i]); - valuesPerRow.add(real[i]); - valuesPerRow.add(tinyint[i]); - valuesPerRow.add(floatVal[i]); - valuesPerRow.add(text[i]); - valuesPerRow.add(binary512[i]); - valuesPerRow.add(Datetime2[i]); - valuesPerRow.add((i + 1)); - valuesPerRow.add(Datetime[i]); - valuesPerRow.add(bigInt[i]); - valuesPerRow.add(nvarchar512[i]); - valuesPerRow.add(smallmoney[i]); - valuesPerRow.add(intVal[i]); - - tableValues.add(valuesPerRow); - rowNumbers++; - } - } - - public static ArrayList getTableValues(int index) { - return tableValues.get(index); - } - - private static String generateCharTypes(String columnLength, boolean nullable) { - String charSet = normalCharSet; - return buildCharOrNChar(columnLength, nullable, charSet, 8001); - } - - private static String generateNCharTypes(String columnLength, boolean nullable) { - String charSet = normalCharSet; - - return buildCharOrNChar(columnLength, nullable, charSet, 4001); - } - - private static String buildCharOrNChar(String columnLength, boolean nullable, String charSet, int maxBound) { - if (nullable) { - return null; - } - - int minimumLength = 0; - int length; - if (columnLength.toLowerCase().equals("max")) { - // 50% chance of return value longer than 8000/4000 - if (r.nextBoolean()) { - length = r.nextInt(100000) + maxBound; - return buildRandomString(length, charSet); - } else { - length = r.nextInt(maxBound - minimumLength) + minimumLength; - ; - return buildRandomString(length, charSet); - } - } else { - int columnLengthInt = Integer.parseInt(columnLength); - length = columnLengthInt; - return buildRandomString(length, charSet); - } - } - - private static String buildRandomString(int length, String charSet) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; i++) { - char c = pickRandomChar(charSet); - sb.append(c); - } - return sb.toString(); - } - - private static char pickRandomChar(String charSet) { - int charSetLength = charSet.length(); - int randomIndex = r.nextInt(charSetLength); - return charSet.charAt(randomIndex); - } - - public static byte[] generateBinaryTypes(String columnLength, boolean nullable) { - int maxBound = 8001; - - if (nullable) { - return null; - } - - int minimumLength = 0; - int length; - if (columnLength.toLowerCase().equals("max")) { - // 50% chance of return value longer than 8000/4000 - if (r.nextBoolean()) { - length = r.nextInt(100000) + maxBound; - byte[] bytes = new byte[length]; - r.nextBytes(bytes); - return bytes; - } else { - length = r.nextInt(maxBound - minimumLength) + minimumLength; - byte[] bytes = new byte[length]; - r.nextBytes(bytes); - return bytes; - } - } else { - int columnLengthInt = Integer.parseInt(columnLength); - length = columnLengthInt; - byte[] bytes = new byte[length]; - r.nextBytes(bytes); - return bytes; - } - } - - public static String toString(byte[] bytes) { - if (null == bytes) - return null; - - StringBuffer buffer = new StringBuffer(); - - // 0xFF => "FF" (it takes two characters to represent one byte) - for (int i = 0; i < bytes.length; i++) - toString(buffer, bytes[i]); - - return buffer.toString(); - } - - public static void toString(StringBuffer buffer, byte b) { - // 0xFF => "FF" (it takes two characters to represent one byte) - int i = b; - if (i < 0) - i = 256 + i; // Bytes are 'signed' in Java - - buffer.append(hexdigits[(i >> 4)]); - buffer.append(hexdigits[(i & 0xF)]); - } - - private static DateTimeOffset calculateDateTimeOffsetMinMax(String maxOrMin, Integer precision, String tsMinMax){ - int providedTimeZoneInMinutes; - if(maxOrMin.toLowerCase().equals("max")){ - providedTimeZoneInMinutes = 840; - } - else{ - providedTimeZoneInMinutes = -840; - } - - Timestamp tsMax = Timestamp.valueOf(tsMinMax); - - Calendar cal = Calendar.getInstance(); - long offset = cal.get(Calendar.ZONE_OFFSET); //in milliseconds - - //max Timestamp + difference of current time zone and GMT - provided time zone in milliseconds - tsMax = new Timestamp(tsMax.getTime() + offset - (providedTimeZoneInMinutes * 60 * 1000)); - - if(maxOrMin.toLowerCase().equals("max")){ - int precisionDigits = buildPrecision(precision, "9"); - tsMax.setNanos(precisionDigits); - } - - return microsoft.sql.DateTimeOffset.valueOf(tsMax, providedTimeZoneInMinutes); - } - - private static int buildPrecision(int precision, String charSet){ - String stringValue = calculatePrecisionDigits(precision, charSet); - return Integer.parseInt(stringValue); - } - - //setNanos(999999900) gives 00:00:00.9999999 - //so, this value has to be 9 digits - private static String calculatePrecisionDigits(int precision, String charSet){ - StringBuffer sb = new StringBuffer(); - for(int i = 0; i < precision; i++){ - char c = pickRandomChar(charSet); - sb.append(c); - } - - for(int i = sb.length(); i < 9; i++){ - sb.append("0"); - } - - return sb.toString(); - } - -} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTest.java index 321f4f230..42f99478e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTest.java @@ -1,678 +1,614 @@ /* * Microsoft JDBC Driver for SQL Server * - * Copyright(c) 2016 Microsoft Corporation - * All rights reserved. + * 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. + * 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.bvt; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.math.BigDecimal; -import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; - -public class bvtTest { - private static boolean cursor = false; - private static boolean querytimeout = false; - private static String connectionUrl = ""; - private static Connection con; - private static String driverNamePattern = "Microsoft JDBC Driver \\d.\\d for SQL Server"; - private static String table1 = "stmt_test_bvt"; - private static String table2 = "rs_test_bvt"; - private static Statement stmt = null; - private static ResultSet rs = null; - private static SQLServerPreparedStatement pstmt = null; - private static bvt_ResultSet bvt_rs = null; - - @BeforeClass - public static void init() throws SQLException { - try { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - - Statement stmt = null; - try { - stmt = conn().createStatement(); - - // CREATE the table - stmt.executeUpdate(Tables.dropTable(table1)); - stmt.executeUpdate(Tables.createTable(table1)); - // CREATE the data to populate the table with - Values.createData(); - Tables.populate(table1, stmt); - - stmt.executeUpdate(Tables.dropTable(table2)); - stmt.executeUpdate(Tables.createTable(table2)); - Tables.populate(table2, stmt); - } finally { - if (null != stmt) { - stmt.close(); - } - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - //// Connect to specified server and close the connection - ///////////////////////////////////////////////////////////////////// - @Test - public void testConnection() throws SQLException { - try { - conn().close(); - } finally { - terminateVariation(); - } - } - - ///////////////////////////////////////////////////////////////////// - //// Verify isClosed() - ///////////////////////////////////////////////////////////////////// - @Test - public void testConnectionIsClosed() throws SQLException { - try { - Connection conn = conn(); - assertTrue("BVT connection should not be closed", !conn.isClosed()); - conn.close(); - assertTrue("BVT connection should not be open", conn.isClosed()); - } finally { - terminateVariation(); - } - } - - ///////////////////////////////////////////////////////////////////// - //// Verify Driver Name and Version from MetaData - ///////////////////////////////////////////////////////////////////// - @Test - public void testDriverNameAndDriverVersion() throws SQLException { - try { - DatabaseMetaData metaData = conn().getMetaData(); - Pattern p = Pattern.compile(driverNamePattern); - Matcher m = p.matcher(metaData.getDriverName()); - assertTrue("Driver name is not a correct format! ", m.find()); - String[] parts = metaData.getDriverVersion().split("\\."); - if (parts.length != 4) - assertTrue("Driver version number should be four parts! ", true); - } finally { - terminateVariation(); - } - } - - @Test - public void testCreateStatement() throws SQLException { - - try { - stmt = conn().createStatement(); - // SELECT * FROM - String query = Tables.select(table1); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // close and verify - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement with a query timeout - // ResultSet.Type_forward_only, - // ResultSet.CONCUR_READ_ONLY, executeQuery - // verify cursor by using next and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testCreateStatementWithQueryTimeout() throws SQLException { - - querytimeout = true; - - try { - stmt = conn().createStatement(); - assertEquals(10, stmt.getQueryTimeout()); - } finally { - terminateVariation(); - querytimeout = false; - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // ResultSet.Type_forward_only, - // ResultSet.CONCUR_READ_ONLY, executeQuery - // verify cursor by using next and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtForwardOnlyReadOnly() throws SQLException, ClassNotFoundException { - - try { - stmt = conn().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table1, pk); - rs = stmt.executeQuery(query); - - bvt_rs = new bvt_ResultSet(rs); - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - try { - bvt_rs.previous(); - assertTrue("Previous should have thrown an exception", false); - } catch (SQLException ex) { - // expected exception - } - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // ResultSet.SCROLL_INSENSITIVE, - // ResultSet.CONCUR_READ_ONLY, executeQuery - // verify cursor by using next, afterlast and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtScrollInsensitiveReadOnly() throws SQLException, ClassNotFoundException { - try { - stmt = conn().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - - // SELECT * FROM ORDER BY , - String c1 = Tables.primaryKey(); - String c2 = "[c1_char(512)]"; - - Tables.select(table1); - Tables.orderby(c1); - Tables.orderby(c2); - - rs = stmt.executeQuery(Tables.query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - bvt_rs.afterLast(); - bvt_rs.previous(); - bvt_rs.verifyCurrentRow(); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - ///////////////////////////////////////////////////////////////// - // Create a statement - // ResultSet.SCROLL_SENSITIVE, - // ResultSet.CONCUR_READ_ONLY, executeQuery - // verify cursor by using next and absolute and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtScrollSensitiveReadOnly() throws SQLException { - - try { - stmt = conn().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table1, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - bvt_rs.absolute(3); - bvt_rs.verifyCurrentRow(); - bvt_rs.absolute(1); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // ResultSet.Type_forward_only, - // ResultSet.CONCUR_UPDATABLE, executeQuery - // verify cursor by using next and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtForwardOnlyUpdateable() throws SQLException { - - try { - stmt = conn().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table1, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - try { - bvt_rs.previous(); - assertTrue("Previous should have thrown an exception", false); - } catch (SQLException ex) { - // expected exception - } - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // ResultSet.SCROLL_SENSITIVE, - // ResultSet.CONCUR_UPDATABLE, executeQuery - // verify cursor by using next and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtScrollSensitiveUpdatable() throws SQLException { - - try { - stmt = conn().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table1, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.next(); - bvt_rs.verifyCurrentRow(); - bvt_rs.absolute(3); - bvt_rs.verifyCurrentRow(); - bvt_rs.absolute(1); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // TYPE_SS_SCROLL_DYNAMIC, - // CONCUR_SS_OPTIMISTIC_CC, executeQuery - // verify cursor by using next and previous and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtSS_ScrollDynamicOptimistic_CC() throws SQLException { - - try { - int TYPE_SS_SCROLL_DYNAMIC = 1006; - int CONCUR_SS_OPTIMISTIC_CC = 1008; - stmt = conn().createStatement(TYPE_SS_SCROLL_DYNAMIC, CONCUR_SS_OPTIMISTIC_CC); - - // SELECT * FROM ORDER BY , ASC|DESC - String c1 = Tables.primaryKey(); - String c2 = "[c1_char(512)]"; - - Tables.select(table1); - Tables.orderby(c1); - Tables.orderby(c2); - - rs = stmt.executeQuery(Tables.query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.afterLast(); - bvt_rs.previous(); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Create a statement - // TYPE_SS_SEVER_CURSOR_FORWARD_ONLY, - // CONCUR_READ_ONLY, executeQuery - // verify cursor by using next and verify data - /////////////////////////////////////////////////////////////////// - @Test - public void testStmtSS_SEVER_CURSOR_FORWARD_ONLY() throws SQLException { - - try { - int TYPE_SS_SEVER_CURSOR_FORWARD_ONLY = 2004; - int CONCUR_READ_ONLY = 1008; - stmt = conn().createStatement(TYPE_SS_SEVER_CURSOR_FORWARD_ONLY, CONCUR_READ_ONLY); - - String c1 = Tables.primaryKey(); - String c2 = "[c1_char(512)]"; - - Tables.select(table1); - Tables.orderby(c1); - Tables.orderby(c2); - - rs = stmt.executeQuery(Tables.query); - bvt_rs = new bvt_ResultSet(rs); - - // Verify resultset behavior - bvt_rs.next(); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - - } - - /////////////////////////////////////////////////////////////////// - // Create a preparedstatement, call close - /////////////////////////////////////////////////////////////////// - @Test - public void testCreatepreparedStatement() throws SQLException { - - try { - String pk = Tables.primaryKey(); - String query = "SELECT * from " + table1 + " where c30_smallmoney = ? order by " + pk; - - pstmt = (SQLServerPreparedStatement) conn().prepareStatement(query); - pstmt.setSmallMoney(1, new BigDecimal("214748.3647")); - - rs = pstmt.executeQuery(); - bvt_rs = new bvt_ResultSet(rs); - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify resultset using ResultSetMetaData - /////////////////////////////////////////////////////////////////// - @Test - public void testResultSet() throws SQLException { - - try { - stmt = conn().createStatement(); - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // verify resultSet - bvt_rs.verify(); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify resultset and close resultSet - /////////////////////////////////////////////////////////////////// - @Test - public void testResultSetAndClose() throws SQLException { - - try { - stmt = conn().createStatement(); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs = stmt.executeQuery(query); - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify two concurrent resultsets from same connection, - // separate statements - /////////////////////////////////////////////////////////////////// - @Test - public void testTwoResultsetsDifferentStmt() throws SQLException { - - Statement stmt1 = null; - Statement stmt2 = null; - ResultSet rs1 = null; - ResultSet rs2 = null; - bvt_ResultSet bvt_rs1 = null; - bvt_ResultSet bvt_rs2 = null; - try { - stmt1 = conn().createStatement(); - stmt2 = conn().createStatement(); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs1 = stmt1.executeQuery(query); - - String query2 = Tables.select_Orderby(table1, pk); - rs2 = stmt2.executeQuery(query2); - bvt_rs1 = new bvt_ResultSet(rs1); - bvt_rs2 = new bvt_ResultSet(rs2); - - // Interleave resultset calls - bvt_rs1.next(); - bvt_rs1.verifyCurrentRow(); - bvt_rs2.next(); - bvt_rs2.verifyCurrentRow(); - bvt_rs1.next(); - bvt_rs1.verifyCurrentRow(); - bvt_rs1.verify(); - bvt_rs1.close(); - bvt_rs2.next(); - bvt_rs2.verify(); - } finally { - if (null != bvt_rs2) { - bvt_rs2.close(); - } - if (null != rs1) { - rs1.close(); - } - if (null != rs2) { - rs2.close(); - } - if (null != stmt1) { - stmt1.close(); - } - if (null != stmt2) { - stmt2.close(); - } - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify two concurrent resultsets from same connection, - // same statement - /////////////////////////////////////////////////////////////////// - @Test - public void testTwoResultsetsSameStmt() throws SQLException { - - ResultSet rs1 = null; - ResultSet rs2 = null; - try { - stmt = conn().createStatement(); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs1 = stmt.executeQuery(query); - - // SELECT * FROM ORDER BY - String query2 = Tables.select_Orderby(table1, pk); - rs2 = stmt.executeQuery(query2); - - bvt_ResultSet bvt_rs1 = new bvt_ResultSet(rs1); - bvt_ResultSet bvt_rs2 = new bvt_ResultSet(rs2); - - // Interleave resultset calls. rs is expected to be closed - try { - bvt_rs1.next(); - } catch (SQLException e) { - assertEquals(e.toString(), - "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); - } - bvt_rs2.next(); - bvt_rs2.verifyCurrentRow(); - try { - bvt_rs1.next(); - } catch (SQLException e) { - assertEquals(e.toString(), - "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); - } - bvt_rs1.close(); - bvt_rs2.next(); - bvt_rs2.verify(); - } finally { - if (null != rs1) { - rs1.close(); - } - if (null != rs2) { - rs2.close(); - } - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify resultset closed after statement is closed - /////////////////////////////////////////////////////////////////// - @Test - public void testResultSetAndCloseStmt() throws SQLException { - try { - stmt = conn().createStatement(); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // close statement and verify resultSet - stmt.close(); // this should close the resultSet - try { - bvt_rs.next(); - } catch (SQLException e) { - assertEquals(e.toString(), - "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); - } - } finally { - terminateVariation(); - } - } - - /////////////////////////////////////////////////////////////////// - // Verify resultset using SelectMethod - /////////////////////////////////////////////////////////////////// - @Test - public void testResultSetSelectMethod() throws SQLException { - - // guarantees selectMethod=cursor - cursor = true; - try { - stmt = conn().createStatement(); - - // SELECT * FROM ORDER BY - String pk = Tables.primaryKey(); - String query = Tables.select_Orderby(table2, pk); - rs = stmt.executeQuery(query); - bvt_rs = new bvt_ResultSet(rs); - - // verify resultSet - bvt_rs.verify(); - cursor = false; - } finally { - terminateVariation(); - } - } - - @AfterClass - public static void terminate() throws SQLException { - - try { - stmt = conn().createStatement(); - stmt.executeUpdate(Tables.dropTable(table2)); - stmt.executeUpdate(Tables.dropTable(table1)); - } finally { - terminateVariation(); - } - } - - public static String getConnectionURL() { - connectionUrl = System.getenv("mssql_jdbc_test_connection_properties"); - - if(null == connectionUrl){ - fail("Please setup environment variable mssql_jdbc_test_connection_properties"); - } - - if (cursor){ - connectionUrl += ";selectMethod=cursor;"; - } - - if (querytimeout){ - connectionUrl += ";queryTimeout=10"; - } - - return connectionUrl; - } - - public static Connection conn() { - - connectionUrl = getConnectionURL(); - // Establish the connection. - try { - - Connection con = DriverManager.getConnection(connectionUrl); - return con; - // Handle any errors that may have occurred. - } catch (SQLException e) { - fail("Please make sure the environment variable mssql_jdbc_test_connection_properties is set with correct connection properties.\n" - + e.toString()); - } - return null; - } - - public static void terminateVariation() throws SQLException { - if (con != null && !con.isClosed()) { - try { - con.close(); - } catch (SQLException e) { - fail("Connection close threw : " + e.toString()); - } finally { - if (null != bvt_rs) - bvt_rs.close(); - if (null != rs) - rs.close(); - if (null != stmt) - stmt.close(); - if (null != pstmt) - pstmt.close(); - } - } - } +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.microsoft.sqlserver.testframework.DBConnection; +import com.microsoft.sqlserver.testframework.DBPreparedStatement; +import com.microsoft.sqlserver.testframework.DBResultSet; +import com.microsoft.sqlserver.testframework.DBResultSetTypes; +import com.microsoft.sqlserver.testframework.DBStatement; + +@RunWith(JUnitPlatform.class) +@DisplayName("BVT Test") +public class bvtTest extends bvtTestSetup { + private static String driverNamePattern = "Microsoft JDBC Driver \\d.\\d for SQL Server"; + private static DBResultSet rs = null; + private static DBPreparedStatement pstmt = null; + private static DBConnection conn = null; + private static DBStatement stmt = null; + + /** + * Connect to specified server and close the connection + * + * @throws SQLException + */ + @Test + @DisplayName("test connection") + public void testConnection() throws SQLException { + try { + conn = new DBConnection(connectionString); + conn.close(); + } + finally { + terminateVariation(); + } + } + + /** + * Verify isClosed() + * + * @throws SQLException + */ + @Test + public void testConnectionIsClosed() throws SQLException { + try { + conn = new DBConnection(connectionString); + assertTrue(!conn.isClosed(), "BVT connection should not be closed"); + conn.close(); + assertTrue(conn.isClosed(), "BVT connection should not be open"); + } + finally { + terminateVariation(); + } + } + + /** + * Verify Driver Name and Version from MetaData + * + * @throws SQLException + */ + @Test + public void testDriverNameAndDriverVersion() throws SQLException { + try { + conn = new DBConnection(connectionString); + DatabaseMetaData metaData = conn.getMetaData(); + Pattern p = Pattern.compile(driverNamePattern); + Matcher m = p.matcher(metaData.getDriverName()); + assertTrue(m.find(), "Driver name is not a correct format! "); + String[] parts = metaData.getDriverVersion().split("\\."); + if (parts.length != 4) + assertTrue(true, "Driver version number should be four parts! "); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement, call close + * + * @throws SQLException + */ + @Test + public void testCreateStatement() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + String query = "SELECT * FROM " + table1.getEscapedTableName() + ";"; + rs = stmt.executeQuery(query); + rs.verify(table1); + rs.close(); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement with a query timeout + * + * @throws SQLException + */ + @Test + public void testCreateStatementWithQueryTimeout() throws SQLException { + + try { + conn = new DBConnection(connectionString + ";querytimeout=10"); + stmt = conn.createStatement(); + assertEquals(10, stmt.getQueryTimeout()); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement ResultSet.Type_forward_only, ResultSet.CONCUR_READ_ONLY, executeQuery verify cursor by using next and previous and verify + * data + * + * @throws SQLException + * @throws ClassNotFoundException + */ + @Test + public void testStmtForwardOnlyReadOnly() throws SQLException, ClassNotFoundException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_FORWARD_ONLY_CONCUR_READ_ONLY); + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + rs.next(); + rs.verifyCurrentRow(table1); + rs.next(); + rs.verifyCurrentRow(table1); + + try { + rs.previous(); + assertTrue(false, "Previous should have thrown an exception"); + } + catch (SQLException ex) { + // expected exception + } + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement, ResultSet.SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, executeQuery verify cursor by using next, afterlast and previous + * and verify data + * + * @throws SQLException + * @throws ClassNotFoundException + */ + @Test + public void testStmtScrollInsensitiveReadOnly() throws SQLException, ClassNotFoundException { + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY); + + String query = "SELECT * FROM" + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + rs.next(); + rs.verifyCurrentRow(table1); + rs.afterLast(); + rs.previous(); + rs.verifyCurrentRow(table1); + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement ResultSet.SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, executeQuery verify cursor by using next and absolute and verify + * data + * + * @throws SQLException + */ + @Test + public void testStmtScrollSensitiveReadOnly() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_SCROLL_SENSITIVE_CONCUR_READ_ONLY); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + rs.next(); + rs.next(); + rs.verifyCurrentRow(table1); + rs.absolute(3); + rs.verifyCurrentRow(table1); + rs.absolute(1); + rs.verify(table1); + + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement ResultSet.Type_forward_only, ResultSet.CONCUR_UPDATABLE, executeQuery verify cursor by using next and previous and verify + * data + * + * @throws SQLException + */ + @Test + public void testStmtForwardOnlyUpdateable() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_FORWARD_ONLY_CONCUR_UPDATABLE); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + rs.next(); + + // Verify resultset behavior + rs.next(); + rs.verifyCurrentRow(table1); + rs.next(); + rs.verifyCurrentRow(table1); + try { + rs.previous(); + assertTrue(false, "Previous should have thrown an exception"); + } + catch (SQLException ex) { + // expected exception + } + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement ResultSet.SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, executeQuery verify cursor by using next and previous and verify + * data + * + * @throws SQLException + */ + @Test + public void testStmtScrollSensitiveUpdatable() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_SCROLL_SENSITIVE_CONCUR_UPDATABLE); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + // Verify resultset behavior + rs.next(); + rs.next(); + rs.verifyCurrentRow(table1); + rs.absolute(3); + rs.verifyCurrentRow(table1); + rs.absolute(1); + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement TYPE_SS_SCROLL_DYNAMIC, CONCUR_SS_OPTIMISTIC_CC, executeQuery verify cursor by using next and previous and verify data + * + * @throws SQLException + */ + @Test + public void testStmtSS_ScrollDynamicOptimistic_CC() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(DBResultSetTypes.TYPE_DYNAMIC_CONCUR_OPTIMISTIC); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + // Verify resultset behavior + rs.next(); + rs.afterLast(); + rs.previous(); + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Create a statement TYPE_SS_SEVER_CURSOR_FORWARD_ONLY, CONCUR_READ_ONLY, executeQuery verify cursor by using next and verify data + * + * @throws SQLException + */ + @Test + public void testStmtSS_SEVER_CURSOR_FORWARD_ONLY() throws SQLException { + + try { + conn = new DBConnection(connectionString); + DBResultSetTypes rsType = DBResultSetTypes.TYPE_FORWARD_ONLY_CONCUR_READ_ONLY; + stmt = conn.createStatement(rsType.resultsetCursor, rsType.resultSetConcurrency); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + + rs = stmt.executeQuery(query); + + // Verify resultset behavior + rs.next(); + rs.verify(table1); + } + finally { + terminateVariation(); + } + + } + + /** + * Create a preparedStatement, call close + * + * @throws SQLException + */ + @Test + public void testCreatepreparedStatement() throws SQLException { + + try { + conn = new DBConnection(connectionString); + String colName = table1.getColumnName(7); + String value = table1.getRowData(7, 0).toString(); + + String query = "SELECT * from " + table1.getEscapedTableName() + " where [" + colName + "] = ? "; + + pstmt = conn.prepareStatement(query); + pstmt.setObject(1, new BigDecimal(value)); + + rs = pstmt.executeQuery(); + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Verify resultset using ResultSetMetaData + * + * @throws SQLException + */ + @Test + public void testResultSet() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + // verify resultSet + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * Verify resultset and close resultSet + * + * @throws SQLException + */ + @Test + public void testResultSetAndClose() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + try { + if (null != rs) + rs.close(); + } + catch (SQLException e) { + fail(e.toString()); + } + } + finally { + terminateVariation(); + } + } + + /** + * Verify two concurrent resultsets from same connection, separate statements + * + * @throws SQLException + */ + @Test + public void testTwoResultsetsDifferentStmt() throws SQLException { + + DBStatement stmt1 = null; + DBStatement stmt2 = null; + DBResultSet rs1 = null; + DBResultSet rs2 = null; + try { + conn = new DBConnection(connectionString); + stmt1 = conn.createStatement(); + stmt2 = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs1 = stmt1.executeQuery(query); + + String query2 = "SELECT * FROM " + table2.getEscapedTableName(); + rs2 = stmt2.executeQuery(query2); + + // Interleave resultset calls + rs1.next(); + rs1.verifyCurrentRow(table1); + rs2.next(); + rs2.verifyCurrentRow(table2); + rs1.next(); + rs1.verifyCurrentRow(table1); + rs1.verify(table1); + rs1.close(); + rs2.next(); + rs2.verify(table2); + } + finally { + if (null != rs1) { + rs1.close(); + } + if (null != rs2) { + rs2.close(); + } + if (null != stmt1) { + stmt1.close(); + } + if (null != stmt2) { + stmt2.close(); + } + terminateVariation(); + } + } + + /** + * Verify two concurrent resultsets from same connection, same statement + * + * @throws SQLException + */ + @Test + public void testTwoResultsetsSameStmt() throws SQLException { + + DBResultSet rs1 = null; + DBResultSet rs2 = null; + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs1 = stmt.executeQuery(query); + + String query2 = "SELECT * FROM " + table2.getEscapedTableName(); + rs2 = stmt.executeQuery(query2); + + // Interleave resultset calls. rs is expected to be closed + try { + rs1.next(); + } + catch (SQLException e) { + assertEquals(e.toString(), "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); + } + rs2.next(); + rs2.verifyCurrentRow(table2); + try { + rs1.next(); + } + catch (SQLException e) { + assertEquals(e.toString(), "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); + } + rs1.close(); + rs2.next(); + rs2.verify(table2); + } + finally { + if (null != rs1) { + rs1.close(); + } + if (null != rs2) { + rs2.close(); + } + terminateVariation(); + } + } + + /** + * Verify resultset closed after statement is closed + * + * @throws SQLException + */ + @Test + public void testResultSetAndCloseStmt() throws SQLException { + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + stmt.close(); // this should close the resultSet + try { + rs.next(); + } + catch (SQLException e) { + assertEquals(e.toString(), "com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed."); + } + assertTrue(true, "Previouse one should have thrown exception!"); + } + finally { + terminateVariation(); + } + } + + /** + * Verify resultset using SelectMethod + * + * @throws SQLException + */ + @Test + public void testResultSetSelectMethod() throws SQLException { + + try { + conn = new DBConnection(connectionString + ";selectMethod=cursor;"); + stmt = conn.createStatement(); + + String query = "SELECT * FROM " + table1.getEscapedTableName(); + rs = stmt.executeQuery(query); + + rs.verify(table1); + } + finally { + terminateVariation(); + } + } + + /** + * drops tables + * + * @throws SQLException + */ + @AfterAll + public static void terminate() throws SQLException { + + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + stmt.execute("if object_id('" + table1.getEscapedTableName() + "','U') is not null" + " drop table " + table1.getEscapedTableName()); + stmt.execute("if object_id('" + table2.getEscapedTableName() + "','U') is not null" + " drop table " + table2.getEscapedTableName()); + } + finally { + terminateVariation(); + } + } + + /** + * cleanup after tests + * + * @throws SQLException + */ + public static void terminateVariation() throws SQLException { + if (conn != null && !conn.isClosed()) { + try { + conn.close(); + } + finally { + if (null != rs) + rs.close(); + if (null != stmt) + stmt.close(); + } + } + } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTestSetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTestSetup.java new file mode 100644 index 000000000..52f71d509 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvtTestSetup.java @@ -0,0 +1,57 @@ +/* + * Microsoft JDBC Driver for SQL Server + * + * Copyright(c) 2016 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.bvt; + +import java.sql.SQLException; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.DBConnection; +import com.microsoft.sqlserver.testframework.DBStatement; +import com.microsoft.sqlserver.testframework.DBTable; + +/** + * + * Setting up the test + */ +@RunWith(JUnitPlatform.class) +public class bvtTestSetup extends AbstractTest { + private static DBConnection conn = null; + private static DBStatement stmt = null; + + static DBTable table1; + static DBTable table2; + + @BeforeAll + public static void init() throws SQLException { + try { + conn = new DBConnection(connectionString); + stmt = conn.createStatement(); + + // create tables + table1 = new DBTable(true); + stmt.createTable(table1); + stmt.populateTable(table1); + table2 = new DBTable(true); + stmt.createTable(table2); + stmt.populateTable(table2); + } + finally { + if (null != stmt) { + stmt.close(); + } + if (null != conn && !conn.isClosed()) { + conn.close(); + } + } + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvt_ResultSet.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvt_ResultSet.java deleted file mode 100644 index 9b6ce9588..000000000 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/bvt_ResultSet.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server - * - * Copyright(c) 2016 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.bvt; -import static org.junit.Assert.fail; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.ArrayList; - -public class bvt_ResultSet { - - private ResultSet rs; - private ResultSetMetaData metadata = null; - private int index; - - public bvt_ResultSet(ResultSet rs) { - this.rs = rs; - index = 0; - } - - public void setIndex(int index) { - this.index = index; - } - - public boolean next() throws SQLException { - boolean validrow = rs.next(); - if (validrow) - index++; - return (validrow); - } - - public boolean previous() throws SQLException { - boolean validrow = rs.previous(); - if (validrow) - index--; - return (validrow); - } - - public void afterLast() throws SQLException { - rs.afterLast(); - index = Values.getRowNumbers() + 1; - } - - public void close() throws SQLException { - rs.close(); - } - - public void absolute(int x) throws SQLException { - rs.absolute(x); - index = x; - } - - public void verify() throws SQLException { - - metadata = rs.getMetaData(); - metaData_Verify(); - - // Verify the data - while (next()) { - verifyCurrentRow(); - } - } - - private void metaData_Verify() { - - // getColumnCount - int columns; - try { - columns = metadata.getColumnCount(); - - // Loop through the columns - for (int i = 1; i <= columns; i++) { - // Note: Just calling these performs the verification, in each - // method - metadata.getColumnName(i); - metadata.getColumnType(i); - metadata.getColumnTypeName(i); - - // MetaData - metadata.getScale(i); - metadata.isCaseSensitive(i); - metadata.isAutoIncrement(i); - metadata.isCurrency(i); - metadata.isNullable(i); - metadata.isSigned(i); - - } - } catch (SQLException e) { - fail(e.toString()); - } - - } - - public void verifyCurrentRow() { - Class coercion = Object.class; - - ArrayList currentRow = Values.getTableValues(index - 1); - Object backendData = null; - - for (int i = 1; i <= currentRow.size(); i++) { - backendData = currentRow.get(i - 1); // currentRow is zero based - verifyData(i, coercion, backendData); - } - - } - - private void verifyData(int idx, Class coercion, Object backendData) { - - try { - // getXXX - default mapping - Object actual = getXXX(idx, coercion); - - // Verify - verifydata(backendData, actual, idx); - - } catch (SQLException e) { - fail(e.toString()); - } - - } - - private Object getXXX(int idx, Class coercion) throws SQLException { - if (coercion == Object.class) { - return rs.getObject(idx); - } - return null; - } - - private static void verifydata(Object backendData, Object actual, int idx) { - if (backendData != null) { - if (actual instanceof BigDecimal) { - if (((BigDecimal) actual).compareTo(new BigDecimal("" + backendData)) != 0) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual - + " , inserted value is " + backendData); - } else if (actual instanceof Float) { - if (Float.compare(new Float("" + backendData), (float) actual) != 0) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual - + " ,inserted value is " + backendData); - } else if (actual instanceof Double) { - if (Double.compare(new Double("" + backendData), (double) actual) != 0) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual - + " , inserted value is " + backendData); - } else if (actual instanceof byte[]) { - if (!parseByte((byte[]) actual).contains("" + backendData)) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual - + " , inserted value is " + backendData); - } else if (actual instanceof String) { - if (!(((String) actual).trim()).equalsIgnoreCase(((String) backendData).trim())) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual - + " , inserted value is " + backendData); - } else if (!(("" + actual).equalsIgnoreCase("" + backendData))) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual + " , inserted value is " - + backendData); - } - // if data is null - else { - if (actual != backendData) - fail(" Verification failed at index: " + idx + " , retrieved value: " + actual + " , inserted value is " - + backendData); - } - } - - private static String parseByte(byte[] bytes) { - StringBuffer parsedByte = new StringBuffer(); - parsedByte.append("0x"); - for (byte b : bytes) { - parsedByte.append(String.format("%02X", b)); - } - return parsedByte.toString(); - } - -} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java index 0e4efb814..796a72208 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java @@ -32,8 +32,7 @@ import com.microsoft.sqlserver.testframework.sqlType.SqlType; /** - * This class holds data for Column. Think about encrypted columns. createCMK - * code should not add here. + * This class holds data for Column. Think about encrypted columns. createCMK code should not add here. */ class DBColumn { @@ -79,7 +78,7 @@ SqlType getSqlType() { JDBCType getJdbctype() { return sqlType.getJdbctype(); } - + /** * * @param sqlType @@ -105,7 +104,7 @@ void populateValues(int rows) { * @param row * @return the value populated for the column */ - Object getRowValue(int row) { + Object getRowValue(int row) { // handle exceptions return columnValues.get(row); } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java.orig b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java.orig new file mode 100644 index 000000000..54326b4ca --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java.orig @@ -0,0 +1,116 @@ +// --------------------------------------------------------------------------------------------------------------------------------- +// File: DBColumn.java +// +// +// Microsoft JDBC Driver for SQL Server +// Copyright(c) Microsoft Corporation +// All rights reserved. +// MIT License +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, +// and / or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions : +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// --------------------------------------------------------------------------------------------------------------------------------- + +package com.microsoft.sqlserver.testframework; + +import java.sql.JDBCType; +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.sqlserver.testframework.sqlType.SqlType; + +/** + * This class holds data for Column. Think about encrypted columns. createCMK code should not add here. + */ +class DBColumn { + + /* + * TODO: add nullable, defaultValue, alwaysEncrypted + */ + private String columnName; + private SqlType sqlType; + private List columnValues; + + DBColumn(String columnName, SqlType sqlType) { + this.columnName = columnName; + this.sqlType = sqlType; + } + + /** + * @return the columnName + */ + String getColumnName() { + return columnName; + } + + /** + * @param columnName + * the columnName to set + */ + void setColumnName(String columnName) { + this.columnName = columnName; + } + + /** + * + * @return SqlType for the column + */ + SqlType getSqlType() { + return sqlType; + } + + /** + * + * @return JDBCType for the column + */ + JDBCType getJdbctype() { + return sqlType.getJdbctype(); + } +<<<<<<< HEAD + +======= + +>>>>>>> 85dd53d41a6d634a76d0a4872b4eaf0a2d2ccf4f + /** + * + * @param sqlType + */ + void setSqlType(SqlType sqlType) { + this.sqlType = sqlType; + } + + /** + * generate value for the column + * + * @param rows + * number of rows + */ + void populateValues(int rows) { + columnValues = new ArrayList(); + for (int i = 0; i < rows; i++) + columnValues.add(sqlType.createdata()); + } + + /** + * + * @param row + * @return the value populated for the column + */ + public Object getRowValue(int row) { + // handle exceptions + return columnValues.get(row); + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBConnection.java b/src/test/java/com/microsoft/sqlserver/testframework/DBConnection.java index 35b4a4d2a..25a116126 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBConnection.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBConnection.java @@ -28,71 +28,110 @@ import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import com.microsoft.sqlserver.jdbc.SQLServerConnection; +import com.microsoft.sqlserver.jdbc.SQLServerException; /* * Wrapper class for SQLServerConnection */ public class DBConnection extends AbstractParentWrapper { - // TODO: add Isolation Level - // TODO: add auto commit - // TODO: add connection Savepoint and rollback - // TODO: add additional connection properties - // TODO: add DataSource support - private SQLServerConnection connection = null; - - /** - * establishes connection using the input - * - * @param connectionString - */ - public DBConnection(String connectionString) { - super(null, null, "connection"); - getConnection(connectionString); - } - - /** - * establish connection - * - * @param connectionString - */ - void getConnection(String connectionString) { - try { - connection = PrepUtil.getConnection(connectionString); - setInternal(connection); - } catch (SQLException ex) { - fail(ex.getMessage()); - } catch (ClassNotFoundException ex) { - fail(ex.getMessage()); - } - } - - @Override - void setInternal(Object internal) { - this.internal = internal; - } - - /** - * - * @return Statement wrapper - */ - public DBStatement createStatement() { - try { - DBStatement dbstatement = new DBStatement(this); - return dbstatement.createStatement(); - } catch (SQLException ex) { - fail(ex.getMessage()); - } - return null; - } + // TODO: add Isolation Level + // TODO: add auto commit + // TODO: add connection Savepoint and rollback + // TODO: add additional connection properties + // TODO: add DataSource support + private SQLServerConnection connection = null; + /** + * establishes connection using the input + * + * @param connectionString + */ + public DBConnection(String connectionString) { + super(null, null, "connection"); + getConnection(connectionString); + } /** - * clsoe connection + * establish connection + * + * @param connectionString + */ + void getConnection(String connectionString) { + try { + connection = PrepUtil.getConnection(connectionString); + setInternal(connection); + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + catch (ClassNotFoundException ex) { + fail(ex.getMessage()); + } + } + + @Override + void setInternal(Object internal) { + this.internal = internal; + } + + /** + * + * @return Statement wrapper + */ + public DBStatement createStatement() { + try { + DBStatement dbstatement = new DBStatement(this); + return dbstatement.createStatement(); + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + return null; + } + + /** + * + * @param type + * @param concurrency + * @return + * @throws SQLException + */ + public DBStatement createStatement(int type, int concurrency) throws SQLException { + DBStatement dbstatement = new DBStatement(this); + return dbstatement.createStatement(type, concurrency); + + } + + /** + * + * @param rsType + * @return + * @throws SQLServerException + */ + public DBStatement createStatement(DBResultSetTypes rsType) throws SQLServerException { + DBStatement dbstatement = new DBStatement(this); + return dbstatement.createStatement(rsType.resultsetCursor, rsType.resultSetConcurrency); + } + + /** + * + * @param query + * @return + * @throws SQLException + */ + public DBPreparedStatement prepareStatement(String query) throws SQLException { + DBPreparedStatement dbpstmt = new DBPreparedStatement(this); + return dbpstmt.prepareStatement(query); + } + + /** + * close connection */ public void close() { try { @@ -103,19 +142,52 @@ public void close() { } } + /** + * checks if the connection is closed. + * + * @return true if connection is closed. + * @throws SQLException + */ + public boolean isClosed() { + boolean current = false; + try { + current = connection.isClosed(); + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + return current; + } - public static boolean isSqlAzure(Connection con) throws SQLException { - boolean isSqlAzure = false; + /** + * Retrieves metaData + * + * @return + * @throws SQLException + */ + public DatabaseMetaData getMetaData() throws SQLException { + DatabaseMetaData product = connection.getMetaData(); + return product; + } - ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)"); - rs.next(); - int engineEdition = rs.getInt(1); - rs.close(); - if (ENGINE_EDITION_FOR_SQL_AZURE == engineEdition) { - isSqlAzure = true; - } + /** + * + * @param con + * @return + * @throws SQLException + */ + public static boolean isSqlAzure(Connection con) throws SQLException { + boolean isSqlAzure = false; + + ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)"); + rs.next(); + int engineEdition = rs.getInt(1); + rs.close(); + if (ENGINE_EDITION_FOR_SQL_AZURE == engineEdition) { + isSqlAzure = true; + } - return isSqlAzure; - } + return isSqlAzure; + } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBPreparedStatement.java b/src/test/java/com/microsoft/sqlserver/testframework/DBPreparedStatement.java new file mode 100644 index 000000000..ba8d230cb --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBPreparedStatement.java @@ -0,0 +1,78 @@ +/** + * 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.testframework; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * + * Wrapper class PreparedStatement + */ +public class DBPreparedStatement extends AbstractParentWrapper { + + PreparedStatement pstmt = null; + DBResultSet dbresultSet = null; + + /** + * + */ + public DBPreparedStatement(DBConnection dbconnection) { + super(dbconnection, null, "preparedStatement"); + } + + /** + * @param parent + * @param internal + * @param name + */ + DBPreparedStatement(AbstractParentWrapper parent, Object internal, String name) { + super(parent, internal, name); + } + + /** + * @throws SQLException + * + */ + DBPreparedStatement prepareStatement(String query) throws SQLException { + pstmt = ((Connection) parent().product()).prepareStatement(query); + setInternal(pstmt); + return this; + } + + @Override + void setInternal(Object internal) { + this.internal = internal; + } + + /** + * + * @param parameterIndex + * @param targetObject + * @throws SQLException + */ + public void setObject(int parameterIndex, Object targetObject) throws SQLException { + + ((PreparedStatement) product()).setObject(parameterIndex, targetObject); + } + + /** + * + * @return + * @throws SQLException + */ + public DBResultSet executeQuery() throws SQLException { + ResultSet rs = null; + rs = pstmt.executeQuery(); + dbresultSet = new DBResultSet(this, rs); + return dbresultSet; + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBResultSet.java b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSet.java index 04b069b04..f7230822b 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBResultSet.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSet.java @@ -1,32 +1,27 @@ -// --------------------------------------------------------------------------------------------------------------------------------- -// File: DBResultSet.java -// -// -// Microsoft JDBC Driver for SQL Server -// Copyright(c) Microsoft Corporation -// All rights reserved. -// MIT License -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), -// to deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, -// and / or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions : -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// --------------------------------------------------------------------------------------------------------------------------------- - +/** + * 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.testframework; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.math.BigDecimal; +import java.sql.JDBCType; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Arrays; +import java.util.Calendar; +import java.util.logging.Level; +import java.util.logging.Logger; /** * wrapper class for ResultSet @@ -34,18 +29,39 @@ * @author Microsoft * */ + public class DBResultSet extends AbstractParentWrapper { // TODO: add cursors // TODO: add resultSet level holdability // TODO: add concurrency control + public static final Logger log = Logger.getLogger("DBResultSet"); + + public static final int TYPE_DYNAMIC = ResultSet.TYPE_SCROLL_SENSITIVE + 1; + public static final int CONCUR_OPTIMISTIC = ResultSet.CONCUR_UPDATABLE + 2; + public static final int TYPE_CURSOR_FORWARDONLY = ResultSet.TYPE_FORWARD_ONLY + 1001; + public static final int TYPE_FORWARD_ONLY = ResultSet.TYPE_FORWARD_ONLY; + public static final int CONCUR_READ_ONLY = ResultSet.CONCUR_READ_ONLY; + public static final int TYPE_SCROLL_INSENSITIVE = ResultSet.TYPE_SCROLL_INSENSITIVE; + public static final int TYPE_SCROLL_SENSITIVE = ResultSet.TYPE_SCROLL_SENSITIVE; + public static final int CONCUR_UPDATABLE = ResultSet.CONCUR_UPDATABLE; + + protected DBTable currentTable; + public int _currentrow = -1; // The row this rowset is currently pointing to + ResultSet resultSet = null; + DBResultSetMetaData metaData; DBResultSet(DBStatement dbstatement, ResultSet internal) { super(dbstatement, internal, "resultSet"); resultSet = internal; } + DBResultSet(DBPreparedStatement dbpstmt, ResultSet internal) { + super(dbpstmt, internal, "resultSet"); + resultSet = internal; + } + /** * Close the ResultSet object * @@ -63,6 +79,7 @@ public void close() throws SQLException { * @throws SQLException */ public boolean next() throws SQLException { + _currentrow++; return resultSet.next(); } @@ -85,4 +102,331 @@ public Object getObject(int index) throws SQLException { public void updateObject(int index) throws SQLException { // TODO: update object based on cursor type } + + /** + * + * @throws SQLException + */ + public void verify(DBTable table) throws SQLException { + currentTable = table; + metaData = this.getMetaData(); + metaData.verify(); + + while (this.next()) + this.verifyCurrentRow(table); + } + + /** + * @throws SQLException + * + */ + public void verifyCurrentRow(DBTable table) throws SQLException { + currentTable = table; + int totalColumns = ((ResultSet) product()).getMetaData().getColumnCount(); + + Class _class = Object.class; + for (int i = 0; i < totalColumns; i++) + verifydata(i, _class); + } + + /** + * + * @param ordinal + * @param coercion + * @throws SQLException + */ + public void verifydata(int ordinal, Class coercion) throws SQLException { + Object expectedData = currentTable.columns.get(ordinal).getRowValue(_currentrow); + + // getXXX - default mapping + Object retrieved = this.getXXX(ordinal + 1, coercion); + + // Verify + verifydata(ordinal, coercion, expectedData, retrieved); + } + + /** + * verifies data + * + * @param ordinal + * @param coercion + * @param expectedData + * @param retrieved + * @throws SQLException + */ + public void verifydata(int ordinal, Class coercion, Object expectedData, Object retrieved) throws SQLException { + metaData = this.getMetaData(); + switch (metaData.getColumnType(ordinal + 1)) { + case java.sql.Types.BIGINT: + assertTrue((((Long) expectedData).longValue() == ((Long) retrieved).longValue()), + "Unexpected bigint value, expected: " + ((Long) expectedData).longValue() + " .Retrieved: " + ((Long) retrieved).longValue()); + break; + + case java.sql.Types.INTEGER: + assertTrue((((Integer) expectedData).intValue() == ((Integer) retrieved).intValue()), "Unexpected int value, expected : " + + ((Integer) expectedData).intValue() + " ,received: " + ((Integer) retrieved).intValue()); + break; + + case java.sql.Types.SMALLINT: + case java.sql.Types.TINYINT: + assertTrue((((Short) expectedData).shortValue() == ((Short) retrieved).shortValue()), "Unexpected smallint/tinyint value, expected: " + + " " + ((Short) expectedData).shortValue() + " received: " + ((Short) retrieved).shortValue()); + break; + + case java.sql.Types.BIT: + if (expectedData.equals(1)) + expectedData = true; + else + expectedData = false; + assertTrue((((Boolean) expectedData).booleanValue() == ((Boolean) retrieved).booleanValue()), "Unexpected bit value, expected: " + + ((Boolean) expectedData).booleanValue() + " ,received: " + ((Boolean) retrieved).booleanValue()); + break; + + case java.sql.Types.DECIMAL: + case java.sql.Types.NUMERIC: + assertTrue(0 == (((BigDecimal) expectedData).compareTo((BigDecimal) retrieved)), "Unexpected decimal/numeric/money/smallmoney value " + + ",expected: " + (BigDecimal) expectedData + " received: " + (BigDecimal) retrieved); + break; + + case java.sql.Types.DOUBLE: + assertTrue((((Double) expectedData).doubleValue() == ((Double) retrieved).doubleValue()), "Unexpected float value, expected: " + + ((Double) expectedData).doubleValue() + " received: " + ((Double) retrieved).doubleValue()); + break; + + case java.sql.Types.REAL: + assertTrue((((Float) expectedData).floatValue() == ((Float) retrieved).floatValue()), + "Unexpected real value, expected: " + ((Float) expectedData).floatValue() + " received: " + ((Float) retrieved).floatValue()); + break; + + case java.sql.Types.VARCHAR: + case java.sql.Types.NVARCHAR: + assertTrue((((String) expectedData).trim().equalsIgnoreCase(((String) retrieved).trim())), "Unexpected varchar/nvarchar value, " + + "expected: " + ((String) expectedData).trim() + " ,received: " + ((String) retrieved).trim()); + break; + case java.sql.Types.CHAR: + case java.sql.Types.NCHAR: + + assertTrue((((String) expectedData).trim().equalsIgnoreCase(((String) retrieved).trim())), "Unexpected char/nchar value, " + + "expected: " + ((String) expectedData).trim() + " ,received: " + ((String) retrieved).trim()); + break; + + case java.sql.Types.TIMESTAMP: + if (metaData.getColumnTypeName(ordinal + 1).equalsIgnoreCase("datetime")) { + assertTrue((((Timestamp) roundDatetimeValue(expectedData)).getTime() == (((Timestamp) retrieved).getTime())), + "Unexpected datetime value, expected: " + ((Timestamp) roundDatetimeValue(expectedData)).getTime() + " , received: " + + (((Timestamp) retrieved).getTime())); + break; + } + else if (metaData.getColumnTypeName(ordinal + 1).equalsIgnoreCase("smalldatetime")) { + assertTrue((((Timestamp) roundSmallDateTimeValue(expectedData)).getTime() == (((Timestamp) retrieved).getTime())), + "Unexpected smalldatetime value, expected: " + ((Timestamp) roundSmallDateTimeValue(expectedData)).getTime() + + " ,received: " + (((Timestamp) retrieved).getTime())); + break; + } + else + assertTrue(("" + Timestamp.valueOf((LocalDateTime) expectedData)).equalsIgnoreCase("" + retrieved), "Unexpected datetime2 value, " + + "expected: " + Timestamp.valueOf((LocalDateTime) expectedData) + " ,received: " + retrieved); + break; + + case java.sql.Types.DATE: + assertTrue((("" + expectedData).equalsIgnoreCase("" + retrieved)), + "Unexpected date value, expected: " + expectedData + " ,received: " + retrieved); + break; + + case java.sql.Types.TIME: + assertTrue(("" + Time.valueOf((LocalTime) expectedData)).equalsIgnoreCase("" + retrieved), + "Unexpected time value, exptected: " + Time.valueOf((LocalTime) expectedData) + " ,received: " + retrieved); + break; + + case microsoft.sql.Types.DATETIMEOFFSET: + assertTrue(("" + expectedData).equals("" + retrieved), + " unexpected DATETIMEOFFSET value, expected: " + expectedData + " ,received: " + retrieved); + break; + + case java.sql.Types.BINARY: + assertTrue(parseByte((byte[]) expectedData, (byte[]) retrieved), + " unexpected BINARY value, expected: " + expectedData + " ,received: " + retrieved); + break; + + case java.sql.Types.VARBINARY: + assertTrue(Arrays.equals((byte[]) expectedData, (byte[]) retrieved), + " unexpected BINARY value, expected: " + expectedData + " ,received: " + retrieved); + break; + default: + fail("Unhandled JDBCType " + JDBCType.valueOf(metaData.getColumnType(ordinal + 1))); + break; + } + } + + private boolean parseByte(byte[] expectedData, byte[] retrieved) { + assertTrue(Arrays.equals(expectedData, Arrays.copyOf(retrieved, expectedData.length)), " unexpected BINARY value, expected"); + for (int i = expectedData.length; i < retrieved.length; i++) { + assertTrue(0 == retrieved[i], "unexpected data BINARY"); + } + return true; + } + + private Object getXXX(int idx, Class coercion) throws SQLException { + if (coercion == Object.class) { + return this.getObject(idx); + } + else { + if (log.isLoggable(Level.FINE)) { + log.fine("coercion not supported! "); + } + else { + log.fine("coercion + " + coercion.toString() + " is not supported!"); + } + } + return null; + } + + /** + * + * @return + * @throws SQLException + */ + public DBResultSetMetaData getMetaData() throws SQLException { + DBResultSetMetaData metaData = new DBResultSetMetaData(this); + return metaData.getMetaData(); + } + + /** + * + * @return + * @throws SQLException + */ + public int getRow() throws SQLException { + int product = ((ResultSet) product()).getRow(); + return product; + } + + /** + * + * @return + * @throws SQLException + */ + public boolean previous() throws SQLException { + + boolean validrow = ((ResultSet) product()).previous(); + + if (_currentrow > 0) { + _currentrow--; + } + return (validrow); + } + + /** + * + * @throws SQLException + */ + public void afterLast() throws SQLException { + ((ResultSet) product()).afterLast(); + _currentrow = DBTable.getTotalRows(); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public boolean absolute(int x) throws SQLException { + boolean validrow = ((ResultSet) product()).absolute(x); + _currentrow = x - 1; + return validrow; + } + + private static Object roundSmallDateTimeValue(Object value) { + if (value == null) { + return null; + } + + Calendar cal; + java.sql.Timestamp ts = null; + int nanos = -1; + + if (value instanceof Calendar) { + cal = (Calendar) value; + } + else { + ts = (java.sql.Timestamp) value; + cal = Calendar.getInstance(); + cal.setTimeInMillis(ts.getTime()); + nanos = ts.getNanos(); + } + + // round to the nearest minute + double seconds = cal.get(Calendar.SECOND) + (nanos == -1 ? ((double) cal.get(Calendar.MILLISECOND) / 1000) : ((double) nanos / 1000000000)); + if (seconds > 29.998) { + cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + 1); + } + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + nanos = 0; + + // required to force computation + cal.getTimeInMillis(); + + // return appropriate value + if (value instanceof Calendar) { + return cal; + } + else { + ts.setTime(cal.getTimeInMillis()); + ts.setNanos(nanos); + return ts; + } + } + + private static Object roundDatetimeValue(Object value) { + if (value == null) + return null; + Timestamp ts = value instanceof Timestamp ? (Timestamp) value : new Timestamp(((Calendar) value).getTimeInMillis()); + int millis = ts.getNanos() / 1000000; + int lastDigit = (int) (millis % 10); + switch (lastDigit) { + // 0, 1 -> 0 + case 1: + ts.setNanos((millis - 1) * 1000000); + break; + + // 2, 3, 4 -> 3 + case 2: + ts.setNanos((millis + 1) * 1000000); + break; + case 4: + ts.setNanos((millis - 1) * 1000000); + break; + + // 5, 6, 7, 8 -> 7 + case 5: + ts.setNanos((millis + 2) * 1000000); + break; + case 6: + ts.setNanos((millis + 1) * 1000000); + break; + case 8: + ts.setNanos((millis - 1) * 1000000); + break; + + // 9 -> 0 with overflow + case 9: + ts.setNanos(0); + ts.setTime(ts.getTime() + millis + 1); + break; + + // default, i.e. 0, 3, 7 -> 0, 3, 7 + // don't change the millis but make sure that any + // sub-millisecond digits are zeroed out + default: + ts.setNanos((millis) * 1000000); + } + if (value instanceof Calendar) { + ((Calendar) value).setTimeInMillis(ts.getTime()); + ((Calendar) value).getTimeInMillis(); + return value; + } + return ts; + } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetMetaData.java b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetMetaData.java new file mode 100644 index 000000000..11ddf8bc6 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetMetaData.java @@ -0,0 +1,191 @@ +/* + * 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.testframework; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +import com.microsoft.sqlserver.jdbc.SQLServerResultSetMetaData; + +/** + * + * Wrapper class for ResultSetMetaData + */ +public class DBResultSetMetaData extends AbstractParentWrapper { + + DBResultSetMetaData dbresultSetMetaData = null; + ResultSetMetaData resultSetMetaData = null; + + /** + * @param parent + * @param internal + * @param name + */ + DBResultSetMetaData(AbstractParentWrapper parent, Object internal, String name) { + super(parent, internal, name); + // TODO Auto-generated constructor stub + } + + /** + * + */ + public DBResultSetMetaData(DBResultSet dbresultset) { + super(dbresultset, null, "dbresultset"); + } + + DBResultSetMetaData resultSetMetaData() { + return this; + } + + /** + * + * @return + * @throws SQLException + */ + public DBResultSetMetaData getMetaData() throws SQLException { + resultSetMetaData = ((ResultSet) parent().product()).getMetaData(); + setInternal(resultSetMetaData); + return this; + } + + /** + * + * @throws SQLException + */ + public void verify() throws SQLException { + // getColumnCount + int columns = this.getColumnCount(); + + // Loop through the columns + for (int i = 1; i <= columns; i++) { + // Note: Just calling these performs the verification, in each method + this.getColumnName(i); + this.getColumnType(i); + this.getColumnTypeName(i); + this.getScale(i); + this.isCaseSensitive(i); + this.isAutoIncrement(i); + this.isCurrency(i); + this.isNullable(i); + this.isSigned(i); + } + } + + /** + * + * @return + * @throws SQLException + */ + public int getColumnCount() throws SQLException { + return ((SQLServerResultSetMetaData) product()).getColumnCount(); + } + + /** + * + * @param index + * @return + * @throws SQLException + */ + public String getColumnName(int index) throws SQLException { + return ((SQLServerResultSetMetaData) product()).getColumnName(index); + } + + /** + * + * @param index + * @return + * @throws SQLException + */ + public int getColumnType(int index) throws SQLException { + return ((SQLServerResultSetMetaData) product()).getColumnType(index); + } + + /** + * + * @param index + * @return + * @throws SQLException + */ + public String getColumnTypeName(int index) throws SQLException { + return ((SQLServerResultSetMetaData) product()).getColumnTypeName(index); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public int getPrecision(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).getPrecision(x); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public int getScale(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).getScale(x); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public boolean isCaseSensitive(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).isCaseSensitive(x); + + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public boolean isCurrency(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).isCurrency(x); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public boolean isAutoIncrement(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).isAutoIncrement(x); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public int isNullable(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).isNullable(x); + } + + /** + * + * @param x + * @return + * @throws SQLException + */ + public boolean isSigned(int x) throws SQLException { + return ((SQLServerResultSetMetaData) product()).isSigned(x); + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetTypes.java b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetTypes.java new file mode 100644 index 000000000..d1af9baf7 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBResultSetTypes.java @@ -0,0 +1,33 @@ +/* + * 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.testframework; + +/** + * @author Microsoft + * + */ + +public enum DBResultSetTypes { + + TYPE_FORWARD_ONLY_CONCUR_READ_ONLY(DBResultSet.TYPE_FORWARD_ONLY, DBResultSet.CONCUR_READ_ONLY), + TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY(DBResultSet.TYPE_SCROLL_INSENSITIVE, DBResultSet.CONCUR_READ_ONLY), + TYPE_SCROLL_SENSITIVE_CONCUR_READ_ONLY(DBResultSet.TYPE_SCROLL_SENSITIVE, DBResultSet.CONCUR_READ_ONLY), + TYPE_FORWARD_ONLY_CONCUR_UPDATABLE(DBResultSet.TYPE_FORWARD_ONLY, DBResultSet.CONCUR_UPDATABLE), + TYPE_SCROLL_SENSITIVE_CONCUR_UPDATABLE(DBResultSet.TYPE_SCROLL_SENSITIVE, DBResultSet.CONCUR_UPDATABLE), + TYPE_DYNAMIC_CONCUR_OPTIMISTIC( DBResultSet.TYPE_DYNAMIC, DBResultSet.CONCUR_OPTIMISTIC), + TYPE_CURSOR_FORWARDONLY_CONCUR_UPDATABLE(DBResultSet.TYPE_CURSOR_FORWARDONLY, DBResultSet.CONCUR_READ_ONLY),; + + public int resultsetCursor; + public int resultSetConcurrency; + + DBResultSetTypes(int resultSetCursor, int resultSetConcurrency) { + this.resultsetCursor = resultSetCursor; + this.resultSetConcurrency = resultSetConcurrency; + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBStatement.java b/src/test/java/com/microsoft/sqlserver/testframework/DBStatement.java index 199ddd8f2..82309fe99 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBStatement.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBStatement.java @@ -62,6 +62,13 @@ DBStatement createStatement() throws SQLServerException { return this; } + DBStatement createStatement(int type, int concurrency) throws SQLServerException { + // TODO: add cursor and holdability + statement = ((SQLServerConnection) parent().product()).createStatement(type, concurrency); + setInternal(statement); + return this; + } + /** * * @param sql @@ -88,8 +95,7 @@ public boolean execute(String sql) throws SQLException { } /** - * Close the Statement and ResultSet associated - * with it + * Close the Statement and ResultSet associated with it * * @throws SQLException */ @@ -134,4 +140,14 @@ public boolean dropTable(DBTable table) { void setInternal(Object internal) { this.internal = internal; } + + /** + * + * @return + * @throws SQLException + */ + public int getQueryTimeout() throws SQLException { + int current = ((Statement) product()).getQueryTimeout(); + return current; + } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java index 9a293280c..7e2802939 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java @@ -1,27 +1,10 @@ -// --------------------------------------------------------------------------------------------------------------------------------- -// File: DBTable.java -// -// -// Microsoft JDBC Driver for SQL Server -// Copyright(c) Microsoft Corporation -// All rights reserved. -// MIT License -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), -// to deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, -// and / or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions : -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// --------------------------------------------------------------------------------------------------------------------------------- +/* + * 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.testframework; @@ -51,15 +34,14 @@ public class DBTable extends AbstractSQLGenerator { String escapedTableName; List columns; int totalColumns; - int totalRows = 2; // default row count set to 2 + static int totalRows = 3; // default row count set to 3 DBSchema schema; /** * Initializes {@link DBTable} with tableName, schema, and {@link DBColumns} * * @param autoGenerateSchema - * true : generates schema with all available - * dataTypes in SqlType class + * true : generates schema with all available dataTypes in SqlType class */ public DBTable(boolean autoGenerateSchema) { @@ -76,8 +58,7 @@ public DBTable(boolean autoGenerateSchema) { } /** - * Similar to {@link DBTable#DBTable(boolean)}, but uses existing list of - * columns Used internally to clone schema + * Similar to {@link DBTable#DBTable(boolean)}, but uses existing list of columns Used internally to clone schema * * @param DBTable */ @@ -125,14 +106,14 @@ public String getEscapedTableName() { * * @return total rows in the table */ - public int getTotalRows() { + public static int getTotalRows() { return totalRows; } /** * * @param totalRows - * set the number of rows in table, default value is 2 + * set the number of rows in table, default value is 3 */ public void setTotalRows(int totalRows) { this.totalRows = totalRows; @@ -334,29 +315,36 @@ public void addColumn(SqlType sqlType) { DBColumn getColumn(int index) { return columns.get(index); } - + + /** + * + * @param colIndex + * @param rowIndex + * @return + */ + public Object getRowData(int colIndex, int rowIndex) { + return columns.get(colIndex).getRowValue(rowIndex); + } + /** * * @param colNum * @return true if value can be passed as String for the column */ - boolean passDataAsString(int colNum){ - return (JDBCType.CHAR == getColumn(colNum).getJdbctype() - || JDBCType.VARCHAR == getColumn(colNum).getJdbctype() - || JDBCType.NCHAR == getColumn(colNum).getJdbctype() - || JDBCType.NVARCHAR == getColumn(colNum).getJdbctype() - || JDBCType.TIMESTAMP == getColumn(colNum).getJdbctype() - || JDBCType.DATE == getColumn(colNum).getJdbctype() + boolean passDataAsString(int colNum) { + return (JDBCType.CHAR == getColumn(colNum).getJdbctype() || JDBCType.VARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.NCHAR == getColumn(colNum).getJdbctype() || JDBCType.NVARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.TIMESTAMP == getColumn(colNum).getJdbctype() || JDBCType.DATE == getColumn(colNum).getJdbctype() || JDBCType.TIME == getColumn(colNum).getJdbctype()); } - + /** * * @param colNum * @return true if value can be passed as Hex for the column */ - boolean passDataAsHex(int colNum){ - return (JDBCType.BINARY == getColumn(colNum).getJdbctype() - || JDBCType.VARBINARY == getColumn(colNum).getJdbctype()); + + boolean passDataAsHex(int colNum) { + return (JDBCType.BINARY == getColumn(colNum).getJdbctype() || JDBCType.VARBINARY == getColumn(colNum).getJdbctype()); } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java.orig b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java.orig new file mode 100644 index 000000000..3594c2583 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java.orig @@ -0,0 +1,389 @@ +// --------------------------------------------------------------------------------------------------------------------------------- +// File: DBTable.java +// +// +// Microsoft JDBC Driver for SQL Server +// Copyright(c) Microsoft Corporation +// All rights reserved. +// MIT License +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, +// and / or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions : +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// --------------------------------------------------------------------------------------------------------------------------------- + +package com.microsoft.sqlserver.testframework; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.sql.JDBCType; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.codec.binary.Hex; + +import com.microsoft.sqlserver.testframework.sqlType.SqlType; +import com.microsoft.sqlserver.testframework.sqlType.VariableLengthType; +import com.microsoft.sqlserver.testframework.util.RandomUtil; + +/** + * This class holds data for Table. + */ +public class DBTable extends AbstractSQLGenerator { + + public static final Logger log = Logger.getLogger("DBTable"); + String tableName; + String escapedTableName; + List columns; + int totalColumns; + static int totalRows = 3; // default row count set to 3 + DBSchema schema; + ArrayList> rows; + ArrayList currentrow; + + /** + * Initializes {@link DBTable} with tableName, schema, and {@link DBColumns} + * + * @param autoGenerateSchema + * true : generates schema with all available dataTypes in SqlType class + */ + public DBTable(boolean autoGenerateSchema) { + + this.tableName = RandomUtil.getIdentifier("table"); + this.escapedTableName = escapeIdentifier(tableName); + this.schema = new DBSchema(autoGenerateSchema); + if (autoGenerateSchema) { + addColumns(); + } + else { + this.columns = new ArrayList(); + } + this.totalColumns = columns.size(); + } + + /** + * Similar to {@link DBTable#DBTable(boolean)}, but uses existing list of columns Used internally to clone schema + * + * @param DBTable + */ + private DBTable(DBTable sourceTable) { + this.tableName = RandomUtil.getIdentifier("table"); + this.escapedTableName = escapeIdentifier(tableName); + this.columns = sourceTable.columns; + this.totalColumns = columns.size(); + this.schema = sourceTable.schema; + } + + /** + * adds a columns for each SQL type in DBSchema + */ + private void addColumns() { + totalColumns = schema.getNumberOfSqlTypes(); + columns = new ArrayList(totalColumns); + + for (int i = 0; i < totalColumns; i++) { + SqlType sqlType = schema.getSqlType(i); + DBColumn column = new DBColumn(RandomUtil.getIdentifier(sqlType.getName()), sqlType); + columns.add(column); + } + } + + /** + * gets table name of the {@link DBTable} object + * + * @return {@link String} table name + */ + public String getTableName() { + return tableName; + } + + /** + * gets escaped table name of the {@link DBTable} object + * + * @return {@link String} escaped table name + */ + public String getEscapedTableName() { + return escapedTableName; + } + + /** + * + * @return total rows in the table + */ + public static int getTotalRows() { + return totalRows; + } + + /** + * + * @param totalRows + * set the number of rows in table, default value is 3 + */ + public void setTotalRows(int totalRows) { + this.totalRows = totalRows; + } + + /** + * create table + * + * @param dbstatement + */ + boolean createTable(DBStatement dbstatement) { + try { + dropTable(dbstatement); + String sql = createTableSql(); + return dbstatement.execute(sql); + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + return false; + } + + String createTableSql() { + StringJoiner sb = new StringJoiner(SPACE_CHAR); + + sb.add(CREATE_TABLE); + sb.add(escapedTableName); + sb.add(OPEN_BRACKET); + for (int i = 0; i < totalColumns; i++) { + DBColumn column = getColumn(i); + sb.add(escapeIdentifier(column.getColumnName())); + sb.add(column.getSqlType().getName()); + // add precision and scale + if (VariableLengthType.Precision == column.getSqlType().getVariableLengthType()) { + sb.add(OPEN_BRACKET); + sb.add("" + column.getSqlType().getPrecision()); + sb.add(CLOSE_BRACKET); + } + else if (VariableLengthType.Scale == column.getSqlType().getVariableLengthType()) { + sb.add(OPEN_BRACKET); + sb.add("" + column.getSqlType().getPrecision()); + sb.add(COMMA); + sb.add("" + column.getSqlType().getScale()); + sb.add(CLOSE_BRACKET); + } + + sb.add(COMMA); + } + sb.add(CLOSE_BRACKET); + return sb.toString(); + } + + /** + * populate table with values + * + * @param dbstatement + * @return + */ + boolean populateTable(DBStatement dbstatement) { + try { + populateValues(); + String sql = populateTableSql(); + return dbstatement.execute(sql); + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + return false; + } + + private void populateValues() { + // generate values for all columns + for (int i = 0; i < totalColumns; i++) { + DBColumn column = getColumn(i); + column.populateValues(totalRows); + } + } + + public SqlType getSqlType(int columnIndex) { + return getColumn(columnIndex).getSqlType(); + } + + public String getColumnName(int columnIndex) { + return getColumn(columnIndex).getColumnName(); + } + + public int totalColumns() { + return totalColumns; + } + + /** + * + * @return new DBTable object with same schema + */ + public DBTable cloneSchema() { + + DBTable clonedTable = new DBTable(this); + return clonedTable; + } + + /** + * + * @return query to create table + */ + String populateTableSql() { + StringJoiner sb = new StringJoiner(SPACE_CHAR); + + sb.add("INSERT"); + sb.add("INTO"); + sb.add(escapedTableName); + sb.add("VALUES"); + + for (int i = 0; i < totalRows; i++) { + if (i != 0) { + sb.add(COMMA); + } + sb.add(OPEN_BRACKET); + for (int colNum = 0; colNum < totalColumns; colNum++) { + + // TODO: consider how to enclose data in case of preparedStatemets + if (passDataAsString(colNum)) { + sb.add("'" + String.valueOf(getColumn(colNum).getRowValue(i)) + "'"); + } + else if (passDataAsHex(colNum)) { + sb.add("0X" + Hex.encodeHexString((byte[]) (getColumn(colNum).getRowValue(i)))); + } + else { + sb.add(String.valueOf(getColumn(colNum).getRowValue(i))); + } + + if (colNum < totalColumns - 1) { + sb.add(COMMA); + } + } + sb.add(CLOSE_BRACKET); + } + + return (sb.toString()); + } + + /** + * Drop table from Database + * + * @param dbstatement + * @return true if table dropped + */ + boolean dropTable(DBStatement dbstatement) { + boolean result = false; + try { + String sql = dropTableSql(); + result = dbstatement.execute(sql); + if (log.isLoggable(Level.FINE)) { + log.fine("Table Deleted " + tableName); + } + else { + log.fine("Table did not exist : " + tableName); + } + } + catch (SQLException ex) { + fail(ex.getMessage()); + } + return result; + } + + /** + * This will give you query for Drop Table. + */ + String dropTableSql() { + StringJoiner sb = new StringJoiner(SPACE_CHAR); + sb.add("IF OBJECT_ID"); + sb.add(OPEN_BRACKET); + sb.add(wrapName(tableName)); + sb.add(","); + sb.add(wrapName("U")); + sb.add(CLOSE_BRACKET); + sb.add("IS NOT NULL"); + sb.add("DROP TABLE"); + sb.add(escapedTableName); // for drop table no need to wrap. + return sb.toString(); + } + + /** + * new column to add to DBTable based on the SqlType + * + * @param sqlType + */ + public void addColumn(SqlType sqlType) { + schema.addSqlTpe(sqlType); + DBColumn column = new DBColumn(RandomUtil.getIdentifier(sqlType.getName()), sqlType); + columns.add(column); + ++totalColumns; + } + + /** + * + * @param index + * @return DBColumn + */ + DBColumn getColumn(int index) { + return columns.get(index); + } +<<<<<<< HEAD + + public List getColumns() { + return columns; + } + + public Object getRowData(int colIndex, int rowIndex) { + return columns.get(colIndex).getRowValue(rowIndex); + } + +======= + +>>>>>>> 85dd53d41a6d634a76d0a4872b4eaf0a2d2ccf4f + /** + * + * @param colNum + * @return true if value can be passed as String for the column + */ +<<<<<<< HEAD + boolean passDataAsString(int colNum) { + return (JDBCType.CHAR == getColumn(colNum).getJdbctype() || JDBCType.VARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.NCHAR == getColumn(colNum).getJdbctype() || JDBCType.NVARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.TIMESTAMP == getColumn(colNum).getJdbctype() || JDBCType.DATE == getColumn(colNum).getJdbctype() + || JDBCType.TIME == getColumn(colNum).getJdbctype()); + } + +======= + boolean passDataAsString(int colNum){ + return (JDBCType.CHAR == getColumn(colNum).getJdbctype() + || JDBCType.VARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.NCHAR == getColumn(colNum).getJdbctype() + || JDBCType.NVARCHAR == getColumn(colNum).getJdbctype() + || JDBCType.TIMESTAMP == getColumn(colNum).getJdbctype() + || JDBCType.DATE == getColumn(colNum).getJdbctype() + || JDBCType.TIME == getColumn(colNum).getJdbctype()); + } + +>>>>>>> 85dd53d41a6d634a76d0a4872b4eaf0a2d2ccf4f + /** + * + * @param colNum + * @return true if value can be passed as Hex for the column + */ +<<<<<<< HEAD + boolean passDataAsHex(int colNum) { + return (JDBCType.BINARY == getColumn(colNum).getJdbctype() || JDBCType.VARBINARY == getColumn(colNum).getJdbctype()); +======= + boolean passDataAsHex(int colNum){ + return (JDBCType.BINARY == getColumn(colNum).getJdbctype() + || JDBCType.VARBINARY == getColumn(colNum).getJdbctype()); +>>>>>>> 85dd53d41a6d634a76d0a4872b4eaf0a2d2ccf4f + } +} diff --git a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlChar.java b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlChar.java index 19181556e..ef4c66ba4 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlChar.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlChar.java @@ -28,27 +28,58 @@ import java.sql.JDBCType; import java.util.concurrent.ThreadLocalRandom; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang3.RandomStringUtils; - /* - * Restricting the size of char/binary to 2000 and nchar to 1000 to accommodate SQL Sever limitation of having of having maximum allowable - * table row size to 8060 + * Restricting the size of char/binary to 2000 and nchar to 1000 to accommodate SQL Sever limitation of having of having maximum allowable table row + * size to 8060 */ public class SqlChar extends SqlType { + private static String normalCharSet = "1234567890-=!@#$%^&*()_+qwertyuiop[]\\asdfghjkl;zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?"; + public SqlChar() { this("char", JDBCType.CHAR, 2000); } SqlChar(String name, JDBCType jdbctype, int precision) { - super(name, jdbctype, precision, 0, SqlTypeValue.CHAR.minValue, SqlTypeValue.CHAR.maxValue, - SqlTypeValue.CHAR.nullValue, VariableLengthType.Precision); + super(name, jdbctype, precision, 0, SqlTypeValue.CHAR.minValue, SqlTypeValue.CHAR.maxValue, SqlTypeValue.CHAR.nullValue, + VariableLengthType.Precision); generatePrecision(); } public Object createdata() { int dataLength = ThreadLocalRandom.current().nextInt(precision); - return StringEscapeUtils.escapeSql(RandomStringUtils.randomAscii(dataLength)); + return generateCharTypes(dataLength); + } + + private static String generateCharTypes(int columnLength) { + String charSet = normalCharSet; + return buildCharOrNChar(columnLength, charSet); + } + + /** + * generate char or nchar values + * + * @param columnLength + * @param charSet + * @return + */ + protected static String buildCharOrNChar(int columnLength, String charSet) { + int columnLengthInt = columnLength; + return buildRandomString(columnLengthInt, charSet); + } + + private static String buildRandomString(int length, String charSet) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + char c = pickRandomChar(charSet); + sb.append(c); + } + return sb.toString(); + } + + private static char pickRandomChar(String charSet) { + int charSetLength = charSet.length(); + int randomIndex = ThreadLocalRandom.current().nextInt(charSetLength); + return charSet.charAt(randomIndex); } } \ No newline at end of file diff --git a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlDateTimeOffset.java b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlDateTimeOffset.java index c5f3a85e6..c04aefa01 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlDateTimeOffset.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlDateTimeOffset.java @@ -1,98 +1,153 @@ -// --------------------------------------------------------------------------------------------------------------------------------- -// File: SqlDateTimeOffset.java -// -// -// Microsoft JDBC Driver for SQL Server -// Copyright(c) Microsoft Corporation -// All rights reserved. -// MIT License -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), -// to deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, -// and / or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions : -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// --------------------------------------------------------------------------------------------------------------------------------- - +/* + * 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.testframework.sqlType; -import static org.junit.jupiter.api.Assertions.fail; - import java.sql.JDBCType; import java.sql.Timestamp; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; +import java.util.Calendar; import java.util.concurrent.ThreadLocalRandom; -import org.apache.commons.lang3.RandomStringUtils; +import microsoft.sql.DateTimeOffset; public class SqlDateTimeOffset extends SqlDateTime { + public static boolean returnMinMax = (0 == ThreadLocalRandom.current().nextInt(5)); // 20% chance of return Min/Max value + private static String numberCharSet2 = "123456789"; + DateTimeOffset maxDTS; + DateTimeOffset minDTS; + long max; + long min; + // TODO: datetiemoffset can extend SqlDateTime2 // timezone is not supported in Timestamp so its useless to initialize // min/max with offset - static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss.SSSSSSSZ"); - static String basePattern = "yyyy-MM-dd HH:mm:ss"; - static ZoneOffset min = ZoneOffset.of("-1400"); - static ZoneOffset max = ZoneOffset.of("+1400"); - - static DateTimeFormatter formatter; - public SqlDateTimeOffset() { - super("datetimeoffset", - JDBCType.TIMESTAMP /* microsoft.sql.Types.DATETIMEOFFSET */, null, null); - try { - minvalue = new Timestamp( - dateFormat.parse((String) SqlTypeValue.DATETIMEOFFSET.minValue).getTime()); - maxvalue = new Timestamp( - dateFormat.parse((String) SqlTypeValue.DATETIMEOFFSET.maxValue).getTime()); - } - catch (ParseException ex) { - fail(ex.getMessage()); - } + super("datetimeoffset", JDBCType.TIMESTAMP /* microsoft.sql.Types.DATETIMEOFFSET */, null, null); + minvalue = Timestamp.valueOf((String) SqlTypeValue.DATETIMEOFFSET.minValue); + maxvalue = Timestamp.valueOf((String) SqlTypeValue.DATETIMEOFFSET.maxValue); this.precision = 7; this.variableLengthType = VariableLengthType.Precision; generatePrecision(); - formatter = new DateTimeFormatterBuilder().appendPattern(basePattern) - .appendFraction(ChronoField.NANO_OF_SECOND, 0, this.precision, true) - .appendOffset("+HH:mm", "Z").toFormatter(); + maxDTS = calculateDateTimeOffsetMinMax("max", precision, (String) SqlTypeValue.DATETIMEOFFSET.maxValue); + minDTS = calculateDateTimeOffsetMinMax("min", precision, (String) SqlTypeValue.DATETIMEOFFSET.minValue); + + max = maxDTS.getTimestamp().getTime(); + min = minDTS.getTimestamp().getTime(); } + /** + * create data + */ public Object createdata() { - Timestamp temp = new Timestamp(ThreadLocalRandom.current() - .nextLong(((Timestamp) minvalue).getTime(), ((Timestamp) maxvalue).getTime())); - temp.setNanos(0); - String timeNano = temp.toString().substring(0, temp.toString().length() - 1) - + RandomStringUtils.randomNumeric(this.precision); - - // generate random offset values - int offsetSeconds = ThreadLocalRandom.current().nextInt(min.getTotalSeconds(), - max.getTotalSeconds() + 1); - - // trim the seconds from +HH:mm:ss - if (0 != offsetSeconds % 60) { - timeNano = timeNano - + ZoneOffset.ofTotalSeconds(offsetSeconds).toString().substring(0, 6); + return generateDatetimeoffset(this.precision); + } + + /** + * + * @param precision + * @return + */ + public Object generateDatetimeoffset(Integer precision) { + if (null == precision) { + precision = 7; + } + + Timestamp ts = generateTimestamp(max, min); + + if (null == ts) { + return null; + } + + if (returnMinMax) { + if (ThreadLocalRandom.current().nextBoolean()) { + return maxDTS; + } + else { + return minDTS; + } + } + + int precisionDigits = buildPrecision(precision, numberCharSet2); + ts.setNanos(precisionDigits); + + int randomTimeZoneInMinutes = ThreadLocalRandom.current().nextInt(1681) - 840; + + return microsoft.sql.DateTimeOffset.valueOf(ts, randomTimeZoneInMinutes); + } + + private static DateTimeOffset calculateDateTimeOffsetMinMax(String maxOrMin, Integer precision, String tsMinMax) { + int providedTimeZoneInMinutes; + if (maxOrMin.toLowerCase().equals("max")) { + providedTimeZoneInMinutes = 840; } else { - timeNano = timeNano + ZoneOffset.ofTotalSeconds(offsetSeconds).toString(); + providedTimeZoneInMinutes = -840; } - // can pass string rather than converting to LocalDateTime, but leaving - // it unchanged for now to handle prepared statements - OffsetDateTime of = OffsetDateTime.parse(timeNano, formatter); - return of; + + Timestamp tsMax = Timestamp.valueOf(tsMinMax); + + Calendar cal = Calendar.getInstance(); + long offset = cal.get(Calendar.ZONE_OFFSET); // in milliseconds + + // max Timestamp + difference of current time zone and GMT - provided time zone in milliseconds + tsMax = new Timestamp(tsMax.getTime() + offset - (providedTimeZoneInMinutes * 60 * 1000)); + + if (maxOrMin.toLowerCase().equals("max")) { + int precisionDigits = buildPrecision(precision, "9"); + tsMax.setNanos(precisionDigits); + } + + return microsoft.sql.DateTimeOffset.valueOf(tsMax, providedTimeZoneInMinutes); + } + + private static int buildPrecision(int precision, String charSet) { + String stringValue = calculatePrecisionDigits(precision, charSet); + return Integer.parseInt(stringValue); + } + + // setNanos(999999900) gives 00:00:00.9999999 + // so, this value has to be 9 digits + private static String calculatePrecisionDigits(int precision, String charSet) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < precision; i++) { + char c = pickRandomChar(charSet); + sb.append(c); + } + + for (int i = sb.length(); i < 9; i++) { + sb.append("0"); + } + + return sb.toString(); + } + + private static Timestamp generateTimestamp(long max, long min) { + + if (returnMinMax) { + if (ThreadLocalRandom.current().nextBoolean()) { + return new Timestamp(max); + } + else { + return new Timestamp(min); + } + } + + while (true) { + long longValue = ThreadLocalRandom.current().nextLong(); + + if (longValue >= min && longValue <= max) { + return new Timestamp(longValue); + } + } + } + + private static char pickRandomChar(String charSet) { + int charSetLength = charSet.length(); + int randomIndex = ThreadLocalRandom.current().nextInt(charSetLength); + return charSet.charAt(randomIndex); } } \ No newline at end of file diff --git a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlNChar.java b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlNChar.java index 45fed3f75..ed1ee1232 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlNChar.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlNChar.java @@ -28,9 +28,8 @@ import java.sql.JDBCType; import java.util.concurrent.ThreadLocalRandom; -import org.apache.commons.lang.StringEscapeUtils; - public class SqlNChar extends SqlChar { + private static String normalCharSet = "1234567890-=!@#$%^&*()_+qwertyuiop[]\\asdfghjkl;zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?"; SqlNChar(String name, JDBCType jdbctype, int precision) { super(name, jdbctype, precision); @@ -42,23 +41,11 @@ public SqlNChar() { public Object createdata() { int dataLength = ThreadLocalRandom.current().nextInt(precision); - /* - * Just supporting Latin character sets for now, as the entire valid - * code point Character.MIN_CODE_POINT to Character.MAX_CODE_POINT has - * many unassigned code points. - * - * CodePoints Used: Basic Latin, Latin-1 Supplement, Latin Extended-A, - * Latin Extended-B - */ - int minCodePoint = 0x000; - int maxCodePoint = 0x24F; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < dataLength; i++) { - // TODO: need to remove uassigned - int rand = ThreadLocalRandom.current().nextInt(minCodePoint, maxCodePoint); - char c = (char) rand; - sb.append(c); - } - return StringEscapeUtils.escapeSql(sb.toString()); + return generateCharTypes(dataLength); + } + + private static String generateCharTypes(int columnLength) { + String charSet = normalCharSet; + return buildCharOrNChar(columnLength, charSet); } } \ No newline at end of file diff --git a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlType.java b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlType.java index 153bea24f..6ac548e84 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlType.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlType.java @@ -39,6 +39,7 @@ public abstract class SqlType { protected Object maxvalue = null; protected Object nullvalue = null; // Primitives have non-null defaults protected VariableLengthType variableLengthType; +// protected ThreadLocalRandom r; /** * @@ -55,8 +56,8 @@ public abstract class SqlType { * @param variableLengthType * {@link VariableLengthType} */ - SqlType(String name, JDBCType jdbctype, int precision, int scale, Object min, Object max, - Object nullvalue, VariableLengthType variableLengthType) { + SqlType(String name, JDBCType jdbctype, int precision, int scale, Object min, Object max, Object nullvalue, + VariableLengthType variableLengthType) { this.name = name; this.jdbctype = jdbctype; this.precision = precision; @@ -180,4 +181,5 @@ void generatePrecision() { int maxPrecision = this.precision; this.precision = ThreadLocalRandom.current().nextInt(minPrecision, maxPrecision + 1); } + } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlTypeValue.java b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlTypeValue.java index 57fcf2a98..a4309aee6 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlTypeValue.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/sqlType/SqlTypeValue.java @@ -51,9 +51,9 @@ enum SqlTypeValue { TIME ("00:00:00.0000000", "23:59:59.9999999", null), SMALLDATETIME ("19000101T00:00:00", "20790606T23:59:59", null), DATETIME2 ("00010101T00:00:00.0000000", "99991231T23:59:59.9999999", null), - DATETIMEOFFSET ("00010101T00:00:00.0000000-1400", "99991231T23:59:59.9999999+1400", null), + DATETIMEOFFSET ("0001-01-01 00:00:00", "9999-12-31 23:59:59", null), ; - + Object minValue; Object maxValue; Object nullValue;