diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index 92c7cfc71..95161c465 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -414,10 +414,22 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_ } // If Always Encrypted is enabled, transfer the known param meta data if applicable, which might alter param_z for decimal types - if (stmt->conn->ce_option.enabled) { - if (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE) { + if (stmt->conn->ce_option.enabled + && (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE)) { // meta data parameters are always sorted based on parameter number param_ptr->copy_param_meta_ae(param_z, stmt->params_container.params_meta_ae[param_num]); + } + else { + if (Z_TYPE_P(param_z) == IS_STRING && column_size == SQLSRV_UNKNOWN_SIZE) { + size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char); + SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size; + + if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) { + param_ptr->column_size = SQL_SERVER_MAX_TYPE_SIZE; + } + else { + param_ptr->column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size; + } } } @@ -2272,18 +2284,6 @@ bool sqlsrv_param::derive_string_types_sizes(_In_ zval* param_z) break; } - // Derive the column size also only if it is unknown - if (column_size == SQLSRV_UNKNOWN_SIZE) { - size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char); - SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size; - - if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) { - column_size = SQL_SERVER_MAX_TYPE_SIZE; - } else { - column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size; - } - } - return is_numeric; } diff --git a/test/functional/pdo_sqlsrv/pdo_1391_string_truncation_after_short_string.phpt b/test/functional/pdo_sqlsrv/pdo_1391_string_truncation_after_short_string.phpt new file mode 100644 index 000000000..e11ffd488 --- /dev/null +++ b/test/functional/pdo_sqlsrv/pdo_1391_string_truncation_after_short_string.phpt @@ -0,0 +1,77 @@ +--TEST-- +GitHub issue 1391 - string truncation error when binding some parameters as longer strings the second time +--DESCRIPTION-- +The test shows the same parameters, though bound as short strings in the first insertion, can be bound as longer strings in the subsequent insertions. +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- +exec($drop); +} + +try { + $conn = new PDO("sqlsrv:server=$server; Database = $databaseName;", $uid, $pwd); + $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + dropTable($conn, 'long_strings'); + +$tsql = <<exec($tsql); + +$tsql = <<prepare($tsql); + + // Bind and execute short string values first + $fourThousand = '4'; + $varMax = 'v'; + $nvarMax = 'n'; + $stmt->bindParam(1, $fourThousand); + $stmt->bindParam(2, $varMax); + $stmt->bindParam(3, $nvarMax); + $stmt->execute(); + + // Bind and execute long string values second, on same $stmt + $fourThousand = str_repeat('4', 4001); + $varMax = str_repeat('v', 4001); + $nvarMax = str_repeat('n', 4001); + $stmt->bindParam(1, $fourThousand); + $stmt->bindParam(2, $varMax); + $stmt->bindParam(3, $nvarMax); + $stmt->execute(); + + // fetch the data + $stmt = $conn->prepare("SELECT COUNT(*) FROM long_strings"); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_NUM); + echo $row[0]."\n"; + + dropTable($conn, 'long_strings'); + + echo "Done\n"; +} catch (PdoException $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +2 +Done diff --git a/test/functional/pdo_sqlsrv/pdo_getAttribute_clientInfo.phpt b/test/functional/pdo_sqlsrv/pdo_getAttribute_clientInfo.phpt index 521940ba8..474697751 100644 --- a/test/functional/pdo_sqlsrv/pdo_getAttribute_clientInfo.phpt +++ b/test/functional/pdo_sqlsrv/pdo_getAttribute_clientInfo.phpt @@ -20,7 +20,7 @@ try { --EXPECTREGEX-- Array \( - \[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)) + \[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)) \[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2} \[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4} \[ExtensionVer\] => [0-9]\.[0-9]+\.[0-9](-(RC[1-9]?|beta[1-9]))?(\.[0-9]+)?(\+[0-9]+)? diff --git a/test/functional/pdo_sqlsrv/pdo_get_set_attr.phpt b/test/functional/pdo_sqlsrv/pdo_get_set_attr.phpt index 37178afe2..af121a685 100644 --- a/test/functional/pdo_sqlsrv/pdo_get_set_attr.phpt +++ b/test/functional/pdo_sqlsrv/pdo_get_set_attr.phpt @@ -125,7 +125,7 @@ SQLSTATE\[IMSSP\]: A read-only attribute was designated on the PDO object. Get Result PDO::ATTR_CLIENT_VERSION : array\(4\) { \[\"(DriverDllName|DriverName)\"\]=> - (string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\") + (string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\") \["DriverODBCVer"\]=> string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\" \["DriverVer"\]=> diff --git a/test/functional/sqlsrv/sqlsrv_client_info.phpt b/test/functional/sqlsrv/sqlsrv_client_info.phpt index d39819f9a..5b62871b7 100644 --- a/test/functional/sqlsrv/sqlsrv_client_info.phpt +++ b/test/functional/sqlsrv/sqlsrv_client_info.phpt @@ -15,7 +15,7 @@ var_dump( $client_info ); --EXPECTREGEX-- array\(4\) { \[\"(DriverDllName|DriverName)\"\]=> - (string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\") + (string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\") \[\"DriverODBCVer\"\]=> string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\" \[\"DriverVer\"\]=>