Reverted the use of octet length and fixed tests (#1176)

This commit is contained in:
Jenny Tam 2020-08-11 17:09:26 -07:00 committed by GitHub
parent 284aca85ce
commit f02aefd6bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 22 deletions

View file

@ -750,25 +750,17 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
// For a parameter targeting a SmallDatetime column, the return values are SQL_TYPE_TIMESTAMP, 16, and 0. Inputting these values into SQLBindParameter() results in Operand type clash error.
// This is because SQL_TYPE_TIMESTAMP corresponds to Datetime2 by default, and conversion of Datetime2 to Datetime and conversion of Datetime2 to SmallDatatime is not allowed with encrypted columns.
// To fix the conversion problem, set the SQL_CA_SS_SERVER_TYPE field of the parameter to SQL_SS_TYPE_DATETIME and SQL_SS_TYPE_SMALLDATETIME respectively for a Datetime and Smalldatetime column.
// Check SQL_DESC_OCTET_LENGTH of the implementation parameter descriptor (IPD) to distinguish Smalldatetime or Datetime fields from Datetime2(0) or Datetime2(3) fields, as described in
// https://docs.microsoft.com/sql/relational-databases/native-client-odbc-date-time/metadata-parameter-and-result
// This has to be done before SQLBindParameter()
if (stmt->conn->ce_option.enabled && sql_type == SQL_TYPE_TIMESTAMP) {
if (decimal_digits == 0 || decimal_digits == 3) {
SQLHDESC hIpd = NULL;
SQLRETURN r = SQL_SUCCESS;
core::SQLGetStmtAttr(stmt, SQL_ATTR_IMP_PARAM_DESC, &hIpd, 0, 0);
if (hIpd != NULL) {
SQLULEN octetLength = 0;
SQLINTEGER dummy = 0;
SQLRETURN r = ::SQLGetDescField(hIpd, param_num + 1, SQL_DESC_OCTET_LENGTH, (SQLPOINTER)&octetLength, 0, &dummy);
if (SQL_SUCCEEDED(r)) {
// The octet length for datetime2 is 16 but no action required
if (octetLength == 8) {
r = ::SQLSetDescField(hIpd, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_DATETIME, SQL_IS_INTEGER);
} else if (octetLength == 4) {
r = ::SQLSetDescField(hIpd, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_SMALLDATETIME, SQL_IS_INTEGER);
}
if (decimal_digits == 0 && column_size == 16) {
r = ::SQLSetDescField(hIpd, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_SMALLDATETIME, SQL_IS_INTEGER);
} else if (decimal_digits == 3) {
r = ::SQLSetDescField(hIpd, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_DATETIME, SQL_IS_INTEGER);
}
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
throw core::CoreException();

View file

@ -63,7 +63,7 @@ try {
dropTable($conn, $tableName);
// Define the column definitions
$columns = array('c1' => 'smalldatetime', 'c2' => 'datetime', 'c3' => 'datetime2(0)', 'c4' => 'datetime2(3)');
$columns = array('c1' => 'smalldatetime', 'c2' => 'datetime', 'c3' => 'datetime2(0)', 'c4' => 'datetime2(4)');
if ($qualified) {
$tsql = createTableEncryptedQuery($conn, $tableName, $columns);
@ -76,7 +76,7 @@ try {
$val1 = '9999-12-31 23:59:59';
$val2 = null;
$val3 = null;
$val4 = '9999-12-31 23:59:59.999';
$val4 = '9999-12-31 23:59:59.9999';
$tsql = "INSERT INTO $tableName (c1, c2, c3, c4) VALUES (?,?,?,?)";
$stmt = $conn->prepare($tsql);
@ -89,7 +89,7 @@ try {
try {
$stmt->execute();
} catch (PDOException $e) {
$error = ($qualified)? '*Datetime field overflow' : '*The conversion of a nvarchar data type to a smalldatetime data type resulted in an out-of-range value.';
$error = ($qualified || isColEncrypted())? '*Datetime field overflow' : '*The conversion of a nvarchar data type to a smalldatetime data type resulted in an out-of-range value.';
if (!fnmatch($error, $e->getMessage())) {
echo "The error message is unexpected:\n";
var_dump($e->getMessage());
@ -139,6 +139,6 @@ array(4) {
[2]=>
string(19) "0001-01-01 01:01:01"
[3]=>
string(23) "9999-12-31 23:59:59.999"
string(24) "9999-12-31 23:59:59.9999"
}
Done

View file

@ -65,7 +65,7 @@ Verify that inserting into smalldatetime column might trigger "Datetime field ov
dropTable($conn, $tableName);
// Define the column definitions
$columns = array('c1' => 'smalldatetime', 'c2' => 'datetime', 'c3' => 'datetime2(0)', 'c4' => 'datetime2(3)');
$columns = array('c1' => 'smalldatetime', 'c2' => 'datetime', 'c3' => 'datetime2(0)', 'c4' => 'datetime2(4)');
if ($qualified) {
$tsql = createTableEncryptedQuery($conn, $tableName, $columns);
@ -82,7 +82,7 @@ Verify that inserting into smalldatetime column might trigger "Datetime field ov
$val1 = '9999-12-31 23:59:59';
$val2 = null;
$val3 = null;
$val4 = '9999-12-31 23:59:59.999';
$val4 = '9999-12-31 23:59:59.9999';
$tsql = "INSERT INTO $tableName (c1, c2, c3, c4) VALUES (?,?,?,?)";
$params = array($val1, $val2, $val3, $val4);
@ -95,7 +95,7 @@ Verify that inserting into smalldatetime column might trigger "Datetime field ov
if ($result) {
echo "Inserting invalid values should have failed!\n";
} else {
$error = ($qualified)? '*Datetime field overflow' : '*The conversion of a varchar data type to a smalldatetime data type resulted in an out-of-range value.';
$error = ($qualified || AE\isDataEncrypted())? '*Datetime field overflow' : '*The conversion of a varchar data type to a smalldatetime data type resulted in an out-of-range value.';
if (!fnmatch($error, sqlsrv_errors()[0]['message'])) {
var_dump(sqlsrv_errors());
}
@ -148,6 +148,6 @@ array(4) {
["c3"]=>
string(19) "0001-01-01 01:01:01"
["c4"]=>
string(23) "9999-12-31 23:59:59.999"
string(24) "9999-12-31 23:59:59.9999"
}
Done