зеркало из https://github.com/microsoft/msphpsql.git
Fix right truncation issue and add unit test (#1408)
* Reset column size * Fix clientInfo related test cases (#1407) * Create pdo_1391_string_truncation_after_short_string.phpt Regresssion tests: Use the same Statement to insert a row with short strings first, and longer strings second. - Issue also happens with VARCHAR( >=4002 ). Not just Max or NVARCHAR - Issues 1391, 1393 (and possibly 1371 ?) might all have the same root cause. * fetchAll() -> fetch(), we only want 1 row. * Revert trigger Co-authored-by: Maarten S <42799774+talkinnl@users.noreply.github.com>
This commit is contained in:
Родитель
4974fe4334
Коммит
15d25ceb76
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once("MsSetup.inc");
|
||||
|
||||
function dropTable($conn, $tableName)
|
||||
{
|
||||
$drop = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $tableName . "') AND type in (N'U')) DROP TABLE $tableName";
|
||||
$conn->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 = <<<CREATESQL
|
||||
CREATE TABLE long_strings (
|
||||
id bigint IDENTITY(1,1) NOT NULL,
|
||||
four_thousand varchar(4002) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
var_max varchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
nvar_max varchar(max) NOT NULL,
|
||||
CONSTRAINT PK__long_strings__1391E83F512B1391 PRIMARY KEY (id))
|
||||
CREATESQL;
|
||||
|
||||
$conn->exec($tsql);
|
||||
|
||||
$tsql = <<<INSERTSQL
|
||||
INSERT INTO long_strings (four_thousand, var_max, nvar_max) VALUES (?, ?, ?)
|
||||
INSERTSQL;
|
||||
|
||||
$stmt = $conn->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
|
Загрузка…
Ссылка в новой задаче