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

Data Classification sensitivity metadata retrieval #979

Merged
merged 11 commits into from
May 1, 2019
133 changes: 71 additions & 62 deletions source/pdo_sqlsrv/pdo_dbh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ enum PDO_STMT_OPTIONS {
PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE,
PDO_STMT_OPTION_FETCHES_DATETIME_TYPE,
PDO_STMT_OPTION_FORMAT_DECIMALS,
PDO_STMT_OPTION_DECIMAL_PLACES
PDO_STMT_OPTION_DECIMAL_PLACES,
PDO_STMT_OPTION_DATA_CLASSIFICATION
};

// List of all the statement options supported by this driver.
Expand All @@ -104,6 +105,7 @@ const stmt_option PDO_STMT_OPTS[] = {
{ NULL, 0, PDO_STMT_OPTION_FETCHES_DATETIME_TYPE, std::unique_ptr<stmt_option_fetch_datetime>( new stmt_option_fetch_datetime ) },
{ NULL, 0, PDO_STMT_OPTION_FORMAT_DECIMALS, std::unique_ptr<stmt_option_format_decimals>( new stmt_option_format_decimals ) },
{ NULL, 0, PDO_STMT_OPTION_DECIMAL_PLACES, std::unique_ptr<stmt_option_decimal_places>( new stmt_option_decimal_places ) },
{ NULL, 0, PDO_STMT_OPTION_DATA_CLASSIFICATION, std::unique_ptr<stmt_option_data_classification>( new stmt_option_data_classification ) },

{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
};
Expand Down Expand Up @@ -1136,6 +1138,7 @@ int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR:
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
case SQLSRV_ATTR_DATA_CLASSIFICATION:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
}
Expand Down Expand Up @@ -1193,7 +1196,8 @@ int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
// Statement level only
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR:
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
case SQLSRV_ATTR_DATA_CLASSIFICATION:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
}
Expand Down Expand Up @@ -1594,70 +1598,75 @@ namespace {

// Maps the PDO driver specific statement option/attribute constants to the core layer
// statement option/attribute constants.
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
_Inout_ zval* data TSRMLS_DC )
void add_stmt_option_key(_Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
_Inout_ zval* data TSRMLS_DC)
{
zend_ulong option_key = -1;
switch( key ) {

case PDO_ATTR_CURSOR:
option_key = SQLSRV_STMT_OPTION_SCROLLABLE;
break;

case SQLSRV_ATTR_ENCODING:
option_key = PDO_STMT_OPTION_ENCODING;
break;

case SQLSRV_ATTR_QUERY_TIMEOUT:
option_key = SQLSRV_STMT_OPTION_QUERY_TIMEOUT;
break;

case PDO_ATTR_STATEMENT_CLASS:
break;

case SQLSRV_ATTR_DIRECT_QUERY:
option_key = PDO_STMT_OPTION_DIRECT_QUERY;
break;

case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
option_key = PDO_STMT_OPTION_CURSOR_SCROLL_TYPE;
break;

case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
option_key = PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE;
break;

case PDO_ATTR_EMULATE_PREPARES:
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
break;

case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
option_key = PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE;
break;

case SQLSRV_ATTR_FETCHES_DATETIME_TYPE:
option_key = PDO_STMT_OPTION_FETCHES_DATETIME_TYPE;
break;

case SQLSRV_ATTR_FORMAT_DECIMALS:
option_key = PDO_STMT_OPTION_FORMAT_DECIMALS;
break;

case SQLSRV_ATTR_DECIMAL_PLACES:
option_key = PDO_STMT_OPTION_DECIMAL_PLACES;
break;

default:
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
throw core::CoreException();
}
break;
zend_ulong option_key = -1;
switch (key) {

case PDO_ATTR_CURSOR:
option_key = SQLSRV_STMT_OPTION_SCROLLABLE;
break;

case SQLSRV_ATTR_ENCODING:
option_key = PDO_STMT_OPTION_ENCODING;
break;

case SQLSRV_ATTR_QUERY_TIMEOUT:
option_key = SQLSRV_STMT_OPTION_QUERY_TIMEOUT;
break;

case PDO_ATTR_STATEMENT_CLASS:
break;

case SQLSRV_ATTR_DIRECT_QUERY:
option_key = PDO_STMT_OPTION_DIRECT_QUERY;
break;

case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
option_key = PDO_STMT_OPTION_CURSOR_SCROLL_TYPE;
break;

case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
option_key = PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE;
break;

case PDO_ATTR_EMULATE_PREPARES:
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
break;

case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
option_key = PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE;
break;

case SQLSRV_ATTR_FETCHES_DATETIME_TYPE:
option_key = PDO_STMT_OPTION_FETCHES_DATETIME_TYPE;
break;

case SQLSRV_ATTR_FORMAT_DECIMALS:
option_key = PDO_STMT_OPTION_FORMAT_DECIMALS;
break;

case SQLSRV_ATTR_DECIMAL_PLACES:
option_key = PDO_STMT_OPTION_DECIMAL_PLACES;
break;

case SQLSRV_ATTR_DATA_CLASSIFICATION:
option_key = PDO_STMT_OPTION_DATA_CLASSIFICATION;
break;

default:
CHECK_CUSTOM_ERROR(true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION)
{
throw core::CoreException();
}
break;
}

// if a PDO handled option makes it through (such as PDO_ATTR_STATEMENT_CLASS, just skip it
if( option_key != -1 ) {
zval_add_ref( data );
core::sqlsrv_zend_hash_index_update(ctx, options_ht, option_key, data TSRMLS_CC );
if (option_key != -1) {
zval_add_ref(data);
core::sqlsrv_zend_hash_index_update(ctx, options_ht, option_key, data TSRMLS_CC);
}
}

Expand Down
1 change: 1 addition & 0 deletions source/pdo_sqlsrv/pdo_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ namespace {
{ "SQLSRV_ATTR_FETCHES_DATETIME_TYPE", SQLSRV_ATTR_FETCHES_DATETIME_TYPE },
{ "SQLSRV_ATTR_FORMAT_DECIMALS" , SQLSRV_ATTR_FORMAT_DECIMALS },
{ "SQLSRV_ATTR_DECIMAL_PLACES" , SQLSRV_ATTR_DECIMAL_PLACES },
{ "SQLSRV_ATTR_DATA_CLASSIFICATION" , SQLSRV_ATTR_DATA_CLASSIFICATION },

// used for the size for output parameters: PDO::PARAM_INT and PDO::PARAM_BOOL use the default size of int,
// PDO::PARAM_STR uses the size of the string in the variable
Expand Down
26 changes: 25 additions & 1 deletion source/pdo_sqlsrv/pdo_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,10 @@ int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
core_sqlsrv_set_decimal_places(driver_stmt, val TSRMLS_CC);
break;

case SQLSRV_ATTR_DATA_CLASSIFICATION:
driver_stmt->data_classification = (zend_is_true(val)) ? true : false;
break;

default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
break;
Expand Down Expand Up @@ -1012,6 +1016,12 @@ int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
break;
}

case SQLSRV_ATTR_DATA_CLASSIFICATION:
{
ZVAL_BOOL(return_value, driver_stmt->data_classification);
break;
}

default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
break;
Expand Down Expand Up @@ -1071,7 +1081,21 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
core_meta_data = core_sqlsrv_field_metadata( driver_stmt, (SQLSMALLINT) colno TSRMLS_CC );

// add the following fields: flags, native_type, driver:decl_type, table
add_assoc_long( return_value, "flags", 0 );
if (driver_stmt->data_classification) {
core_sqlsrv_sensitivity_metadata(driver_stmt);

// initialize the column data classification array
zval data_classification;
ZVAL_UNDEF(&data_classification);
core::sqlsrv_array_init(*driver_stmt, &data_classification TSRMLS_CC );

data_classification::fill_column_sensitivity_array(driver_stmt, (SQLSMALLINT)colno, &data_classification);

add_assoc_zval(return_value, "flags", &data_classification);
}
else {
add_assoc_long(return_value, "flags", 0);
}

// get the name of the data type
char field_type_name[SQL_SERVER_IDENT_SIZE_MAX] = {'\0'};
Expand Down
12 changes: 12 additions & 0 deletions source/pdo_sqlsrv/pdo_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,18 @@ pdo_error PDO_ERRORS[] = {
SQLSRV_ERROR_AAD_MSI_UID_PWD_NOT_NULL,
{ IMSSP, (SQLCHAR*) "When using ActiveDirectoryMsi Authentication, PWD must be NULL. UID can be NULL, but if not, an empty string is not accepted.", -93, false}
},
{
SQLSRV_ERROR_DATA_CLASSIFICATION_PRE_EXECUTION,
{ IMSSP, (SQLCHAR*) "The statement must be executed to retrieve Data Classification Sensitivity Metadata.", -94, false}
},
{
SQLSRV_ERROR_DATA_CLASSIFICATION_NOT_AVAILABLE,
{ IMSSP, (SQLCHAR*) "Failed to retrieve Data Classification Sensitivity Metadata. If the driver and the server both support the Data Classification feature, check whether the query returns columns with classification information.", -95, false}
},
{
SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED,
{ IMSSP, (SQLCHAR*) "Failed to retrieve Data Classification Sensitivity Metadata: %1!s!", -96, true}
},

{ UINT_MAX, {} }
};
Expand Down
3 changes: 2 additions & 1 deletion source/pdo_sqlsrv/php_pdo_sqlsrv_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ enum PDO_SQLSRV_ATTR {
SQLSRV_ATTR_FETCHES_NUMERIC_TYPE,
SQLSRV_ATTR_FETCHES_DATETIME_TYPE,
SQLSRV_ATTR_FORMAT_DECIMALS,
SQLSRV_ATTR_DECIMAL_PLACES
SQLSRV_ATTR_DECIMAL_PLACES,
SQLSRV_ATTR_DATA_CLASSIFICATION
};

// valid set of values for TransactionIsolation connection option
Expand Down
Loading