Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added getter for sensitivity rank and check for version which added sensitivity rank support #1373

Merged
merged 29 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c97b863
Fix AEv2 tests exclude for reqExternalSetup and cleanup (#1247)
lilgreenbird Feb 5, 2020
54b5a19
Fix | Add null check for getObject() with LocalTime and LocalDate (#1…
peterbae Feb 8, 2020
672b7d6
added all AKV tests to use reqExternalSetup tag so they will be skipp…
lilgreenbird Feb 10, 2020
3c3331b
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Mar 25, 2020
e2c5640
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Mar 26, 2020
aad6966
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Mar 28, 2020
92bf04c
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Mar 31, 2020
3ba5ab7
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Apr 4, 2020
d20823d
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Apr 7, 2020
4cc959f
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Apr 29, 2020
7b301f8
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird Apr 30, 2020
56bcf13
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird May 7, 2020
744e0ca
Merge remote-tracking branch 'upstream/dev' into dev
lilgreenbird May 12, 2020
8479062
dataclassification v2
lilgreenbird May 16, 2020
8dbcca6
fix
lilgreenbird May 18, 2020
c64011d
Merge remote-tracking branch 'upstream/dev' into dataclass
lilgreenbird May 19, 2020
234512b
fixed typo
lilgreenbird May 19, 2020
621bc2e
comment
lilgreenbird May 20, 2020
7712b19
resolved conflicts
lilgreenbird Jun 10, 2020
0599353
Merge branch 'dataclass' of https://github.com/lilgreenbird/mssql-jdb…
lilgreenbird Jun 10, 2020
23da8c2
Merge remote-tracking branch 'upstream/dev' into dataclass
lilgreenbird Jun 18, 2020
6461154
review updates
lilgreenbird Jun 18, 2020
104d4bb
updated rank
lilgreenbird Jun 26, 2020
804f181
merged
lilgreenbird Jun 26, 2020
20905a2
removed enum
lilgreenbird Jun 26, 2020
46910c6
fixed enums
lilgreenbird Jun 26, 2020
a3d6325
expected and actual order
lilgreenbird Jun 28, 2020
5735612
added xAzureSQLDW and TODO
lilgreenbird Jun 30, 2020
26bf42a
review updates
lilgreenbird Jul 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ final class TDS {
static final byte TDS_FEATURE_EXT_DATACLASSIFICATION = 0x09;
static final byte DATA_CLASSIFICATION_NOT_ENABLED = 0x00;
static final byte MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION = 0x02;
static final byte DATA_CLASSIFICATION_VERSION_ADDED_RANK_SUPPORT = 0x02;

static final int AES_256_CBC = 1;
static final int AEAD_AES_256_CBC_HMAC_SHA256 = 2;
Expand Down Expand Up @@ -3613,11 +3614,10 @@ void writeDateTimeOffset(Object value, int scale, SSType destSSType) throws SQLS
int minutesOffset;

/*
* Out of all the supported temporal datatypes, DateTimeOffset is the only datatype that doesn't
* allow direct casting from java.sql.timestamp (which was created from a String).
* DateTimeOffset was never required to be constructed from a String, but with the
* introduction of extended bulk copy support for Azure DW, we now need to support this scenario.
* Parse the DTO as string if it's coming from a CSV.
* Out of all the supported temporal datatypes, DateTimeOffset is the only datatype that doesn't allow direct
* casting from java.sql.timestamp (which was created from a String). DateTimeOffset was never required to be
* constructed from a String, but with the introduction of extended bulk copy support for Azure DW, we now need
* to support this scenario. Parse the DTO as string if it's coming from a CSV.
*/
if (value instanceof String) {
// expected format: YYYY-MM-DD hh:mm:ss[.nnnnnnn] [{+|-}hh:mm]
Expand All @@ -3628,8 +3628,8 @@ void writeDateTimeOffset(Object value, int scale, SSType destSSType) throws SQLS
String offsetString = stringValue.substring(lastColon - 3);

/*
* At this point, offsetString should look like +hh:mm or -hh:mm. Otherwise, the optional offset
* value has not been provided. Parse accordingly.
* At this point, offsetString should look like +hh:mm or -hh:mm. Otherwise, the optional offset value
* has not been provided. Parse accordingly.
*/
String timestampString;

Expand All @@ -3646,11 +3646,10 @@ void writeDateTimeOffset(Object value, int scale, SSType destSSType) throws SQLS
}

/*
* If the target data type is DATETIMEOFFSET, then use UTC for the calendar that
* will hold the value, since writeRPCDateTimeOffset expects a UTC calendar.
* Otherwise, when converting from DATETIMEOFFSET to other temporal data types,
* use a local time zone determined by the minutes offset of the value, since
* the writers for those types expect local calendars.
* If the target data type is DATETIMEOFFSET, then use UTC for the calendar that will hold the value,
* since writeRPCDateTimeOffset expects a UTC calendar. Otherwise, when converting from DATETIMEOFFSET
* to other temporal data types, use a local time zone determined by the minutes offset of the value,
* since the writers for those types expect local calendars.
*/
timeZone = (SSType.DATETIMEOFFSET == destSSType) ? UTC.timeZone
: new SimpleTimeZone(minutesOffset * 60 * 1000, "");
Expand Down Expand Up @@ -3689,11 +3688,10 @@ void writeDateTimeOffset(Object value, int scale, SSType destSSType) throws SQLS
minutesOffset = dtoValue.getMinutesOffset();

/*
* If the target data type is DATETIMEOFFSET, then use UTC for the calendar that
* will hold the value, since writeRPCDateTimeOffset expects a UTC calendar.
* Otherwise, when converting from DATETIMEOFFSET to other temporal data types,
* use a local time zone determined by the minutes offset of the value, since
* the writers for those types expect local calendars.
* If the target data type is DATETIMEOFFSET, then use UTC for the calendar that will hold the value, since
* writeRPCDateTimeOffset expects a UTC calendar. Otherwise, when converting from DATETIMEOFFSET to other
* temporal data types, use a local time zone determined by the minutes offset of the value, since the
* writers for those types expect local calendars.
*/
timeZone = (SSType.DATETIMEOFFSET == destSSType) ? UTC.timeZone
: new SimpleTimeZone(minutesOffset * 60 * 1000, "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,7 @@ public boolean locatorsUpdateCopy() throws SQLException {
*
* @return the database compatibility level value (from sys.databases table).
* @throws SQLException
* if error
*/
public int getDatabaseCompatibilityLevel() throws SQLException {
checkClosed();
Expand Down
30 changes: 0 additions & 30 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -455,36 +455,6 @@ public String toString() {
}


enum SensitivityRank {
NOT_DEFINED(-1),
NONE(0),
LOW(10),
MEDIUM(20),
HIGH(30),
CRITICAL(40);

private static final SensitivityRank[] VALUES = values();
private int rank;

private SensitivityRank(int rank) {
this.rank = rank;
}

public int getValue() {
return rank;
}

static boolean isValid(int rank) throws SQLServerException {
for (SensitivityRank r : VALUES) {
if (r.getValue() == rank) {
return true;
}
}
return false;
}
}


/**
* Provides methods to connect to a SQL Server database and to obtain information about the JDBC driver.
*/
Expand Down
34 changes: 23 additions & 11 deletions src/main/java/com/microsoft/sqlserver/jdbc/StreamColumns.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.microsoft.sqlserver.jdbc.dataclassification.InformationType;
import com.microsoft.sqlserver.jdbc.dataclassification.Label;
import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification;
import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification.SensitivityRank;
import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityProperty;


Expand All @@ -29,6 +30,8 @@ final class StreamColumns extends StreamPacket {

private boolean shouldHonorAEForRead = false;

private boolean sensitivityRankSupported = false;

/* Returns the CekTable */
CekTable getCekTable() {
return cekTable;
Expand Down Expand Up @@ -274,8 +277,12 @@ private SensitivityClassification processDataClassification(TDSReader tdsReader)
informationTypes.add(readSensitivityInformationType(tdsReader));
}

int sensitivityRank = SensitivityRank.NOT_DEFINED.getValue();
if (TDS.MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION <= tdsReader.getServerSupportedDataClassificationVersion()) {
sensitivityRankSupported = tdsReader
.getServerSupportedDataClassificationVersion() >= TDS.DATA_CLASSIFICATION_VERSION_ADDED_RANK_SUPPORT;

// get sensitivity rank if supported
int sensitivityRank = SensitivityRank.NOT_DEFINED.getValue();;
if (sensitivityRankSupported) {
sensitivityRank = tdsReader.readInt();
if (!SensitivityRank.isValid(sensitivityRank)) {
tdsReader.throwInvalidTDS();
Expand Down Expand Up @@ -311,21 +318,26 @@ private SensitivityClassification processDataClassification(TDSReader tdsReader)
informationType = informationTypes.get(informationTypeIndex);
}

if (TDS.MAX_SUPPORTED_DATA_CLASSIFICATION_VERSION <= tdsReader
.getServerSupportedDataClassificationVersion()) {
sensitivityRank = tdsReader.readInt();
if (!SensitivityRank.isValid(sensitivityRank)) {
int sensitivityRankProperty = SensitivityRank.NOT_DEFINED.getValue();
if (sensitivityRankSupported) {
sensitivityRankProperty = tdsReader.readInt();
if (!SensitivityRank.isValid(sensitivityRankProperty)) {
tdsReader.throwInvalidTDS();
}
// add sensitivity properties for the source
sensitivityProperties.add(new SensitivityProperty(label, informationType, sensitivityRankProperty));
}

// add sensitivity properties for the source
sensitivityProperties.add(new SensitivityProperty(label, informationType, sensitivityRank));
}
columnSensitivities.add(new ColumnSensitivity(sensitivityProperties));
}
sensitivityClassification = new SensitivityClassification(sensitivityLabels, informationTypes,
columnSensitivities);
if (sensitivityRankSupported) {
sensitivityClassification = new SensitivityClassification(sensitivityLabels, informationTypes,
columnSensitivities, sensitivityRank);
} else {
sensitivityClassification = new SensitivityClassification(sensitivityLabels, informationTypes,
columnSensitivities);
}

return sensitivityClassification;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,54 @@
import java.util.ArrayList;
import java.util.List;

import com.microsoft.sqlserver.jdbc.SQLServerException;


/**
* Provides the functionlity to retrieve Sensitivity Classification data as received from SQL Server for the active
* Provides the functionality to retrieve Sensitivity Classification data as received from SQL Server for the active
* resultSet
*/
public class SensitivityClassification {

public enum SensitivityRank {
NOT_DEFINED(-1),
NONE(0),
LOW(10),
MEDIUM(20),
HIGH(30),
CRITICAL(40);

private static final SensitivityRank[] VALUES = values();
private int rank;

private SensitivityRank(int rank) {
this.rank = rank;
}

public int getValue() {
return rank;
}

public static boolean isValid(int rank) throws SQLServerException {
for (SensitivityRank r : VALUES) {
if (r.getValue() == rank) {
return true;
}
}
return false;
}
}

private List<Label> labels;
private List<InformationType> informationTypes;
private List<ColumnSensitivity> columnSensitivities;
private int sensitivityRank;

/*
* Creating new ArrayList here assures that 'informationTypes' and 'labels' properties will not be null. The Count
* of the ColumnSensitivities property will be equal to the number of output columns for the query result set.
*/

// Creating new ArrayList here assures that 'informationTypes' and 'labels'
// properties will not be null.
// The Count of the ColumnSensitivities property will be equal to the number
// of output columns for the query result set.
/**
* Constructs a <code>SensitivityClassification</code> Object
*
Expand All @@ -39,6 +73,26 @@ public SensitivityClassification(List<Label> labels, List<InformationType> infor
this.columnSensitivities = new ArrayList<>(columnSensitivity);
}

/**
* Constructs a <code>SensitivityClassification</code> Object
*
* @param labels
* Labels as received from SQL Server
* @param informationTypes
* Information Types as received from SQL Server
* @param columnSensitivity
* Column Sensitivities as received from SQL Server
* @param sensitivityRank
* Sensitivity rank as received from SQL Server
*/
public SensitivityClassification(List<Label> labels, List<InformationType> informationTypes,
List<ColumnSensitivity> columnSensitivity, int sensitivityRank) {
this.labels = new ArrayList<>(labels);
this.informationTypes = new ArrayList<>(informationTypes);
this.columnSensitivities = new ArrayList<>(columnSensitivity);
this.sensitivityRank = sensitivityRank;
}

/**
* Returns the labels for this <code>SensitivityClassification</code> Object
*
Expand All @@ -65,4 +119,8 @@ public List<InformationType> getInformationTypes() {
public List<ColumnSensitivity> getColumnSensitivities() {
return columnSensitivities;
}

public int getSensitivityRank() {
return sensitivityRank;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.microsoft.sqlserver.jdbc.dataclassification.InformationType;
import com.microsoft.sqlserver.jdbc.dataclassification.Label;
import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityProperty;
import com.microsoft.sqlserver.jdbc.dataclassification.SensitivityClassification.SensitivityRank;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;
import com.microsoft.sqlserver.testframework.Constants;
Expand All @@ -39,31 +40,35 @@ public class DataClassificationTest extends AbstractTest {

private static final String addSensitivitySql = "ADD SENSITIVITY CLASSIFICATION TO %s.%s WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='%s', INFORMATION_TYPE_ID='%s'%s)";
private static final String sensitivityRankSql = ", RANK=%s";
private static String sensitivityRank[][] = {{"NONE", "0"}, {"LOW", "10"}, {"MEDIUM", "20"}, {"HIGH", "30"},
{"CRITICAL", "40"}};

/**
* Tests data classification metadata information from SQL Server
*
* TODO: remove xAzureSQLDW tag once issue on server is fixed
* (currently DW not returning rank info) VSO issue 12931
*
* @throws Exception
*/
@Tag(Constants.xSQLv12)
@Tag(Constants.xSQLv14)
@Tag(Constants.xAzureSQLDW)
@Test
public void testDataClassificationMetadata() throws Exception {
try (Statement stmt = connection.createStatement();) {
if (!TestUtils.serverSupportsDataClassification(stmt)) {
fail(TestResource.getResource("R_dataClassificationNotSupported"));
}

for (int i = 0; i < sensitivityRank.length; i++) {
createTable(connection, stmt);
addSensitivity(connection, stmt, sensitivityRank[i][0]);
insertData(connection, stmt);
try (SQLServerResultSet rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + tableName)) {
verifySensitivityClassification(rs, Integer.parseInt(sensitivityRank[i][1]));
for (SensitivityRank i : SensitivityRank.values()) {
if (SensitivityRank.NOT_DEFINED != i) {
createTable(connection, stmt);
addSensitivity(connection, stmt, i.toString());
insertData(connection, stmt);
try (SQLServerResultSet rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + tableName)) {
verifySensitivityClassification(rs, i.getValue());
}
dropTable();
}
dropTable();
}
}
}
Expand Down Expand Up @@ -173,7 +178,10 @@ private void verifySensitivityClassification(SQLServerResultSet rs, int rank) th

verifyLabel(sp.getLabel());
verifyInfoType(sp.getInformationType(), columnPos);
assertEquals(sp.getSensitivityRank(), rank, TestResource.getResource("R_valuesAreDifferent"));
assertEquals(rank, sp.getSensitivityRank(), TestResource.getResource("R_valuesAreDifferent"));

int sensitivityRank = rs.getSensitivityClassification().getSensitivityRank();
assertEquals(rank, sensitivityRank, TestResource.getResource("R_valuesAreDifferent"));
}
}
}
Expand Down