diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index 6cf50d498..29511a822 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -395,6 +395,13 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_ stmt->params_container.insert_param(param_num, new_param); param_ptr = new_param; new_param.transferred(); + } else if (direction == SQL_PARAM_INPUT + && param_ptr->sql_data_type != SQL_SS_TABLE + && param_ptr->strlen_or_indptr == SQL_NULL_DATA) { + // reset the followings for regular input parameters if it was bound as a null param before + param_ptr->sql_data_type = sql_type; + param_ptr->column_size = column_size; + param_ptr->strlen_or_indptr = 0; } SQLSRV_ASSERT(param_ptr != NULL, "core_sqlsrv_bind_param: param_ptr is null. Something went wrong."); diff --git a/source/sqlsrv/stmt.cpp b/source/sqlsrv/stmt.cpp index 609209c32..100273fa3 100644 --- a/source/sqlsrv/stmt.cpp +++ b/source/sqlsrv/stmt.cpp @@ -1187,8 +1187,6 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt ) try { - stmt->free_param_data(); - stmt->executed = false; zval* params_z = stmt->params_z; @@ -1265,6 +1263,8 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt ) } ZEND_HASH_FOREACH_END(); } catch( core::CoreException& ) { + stmt->free_param_data(); + SQLFreeStmt( stmt->handle(), SQL_RESET_PARAMS ); zval_ptr_dtor( stmt->params_z ); sqlsrv_free( stmt->params_z ); diff --git a/test/functional/pdo_sqlsrv/pdo_1329_string_truncation.phpt b/test/functional/pdo_sqlsrv/pdo_1329_string_truncation.phpt new file mode 100644 index 000000000..7b1faf291 --- /dev/null +++ b/test/functional/pdo_sqlsrv/pdo_1329_string_truncation.phpt @@ -0,0 +1,118 @@ +--TEST-- +GitHub issue 1329 - string truncation error when binding some parameters as non-nulls the second time +--DESCRIPTION-- +The test shows the same parameters, though bound as nulls in the first insertion, can be bound as non-nulls 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, 'domains'); + +$tsql = <<exec($tsql); + +$tsql = <<prepare($tsql); + $authority = 'foo.com'; + $base = null; + $notFound = null; + $invalid = null; + $stmt->bindParam(1, $authority); + $stmt->bindParam(2, $base); + $stmt->bindParam(3, $notFound); + $stmt->bindParam(4, $invalid); + $stmt->execute(); + + $authority = 'detached-with-ředirects.com'; + $base = 'fŏő.com'; + $notFound = 'baŗ.com'; + $invalid = null; + $stmt->bindParam(1, $authority); + $stmt->bindParam(2, $base); + $stmt->bindParam(3, $notFound); + $stmt->bindParam(4, $invalid); + $stmt->execute(); + + $authority = 'Őther-redirects.com'; + $base = 'fooš.com'; + $notFound = null; + $invalid = 'ŷëå'; + $stmt->bindParam(1, $authority); + $stmt->bindParam(2, $base); + $stmt->bindParam(3, $notFound); + $stmt->bindParam(4, $invalid); + $stmt->execute(); + + // fetch the data + $stmt = $conn->prepare("SELECT * FROM domains"); + $stmt->execute(); + $row = $stmt->fetchAll(PDO::FETCH_NUM); + print_r($row); + + dropTable($conn, 'domains'); + + echo "Done\n"; +} catch (PdoException $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +Array +( + [0] => Array + ( + [0] => 1 + [1] => foo.com + [2] => + [3] => + [4] => + ) + + [1] => Array + ( + [0] => 2 + [1] => detached-with-ředirects.com + [2] => fŏő.com + [3] => baŗ.com + [4] => + ) + + [2] => Array + ( + [0] => 3 + [1] => Őther-redirects.com + [2] => fooš.com + [3] => + [4] => ŷëå + ) + +) +Done diff --git a/test/functional/sqlsrv/srv_1329_string_truncation.phpt b/test/functional/sqlsrv/srv_1329_string_truncation.phpt new file mode 100644 index 000000000..1395c92f8 --- /dev/null +++ b/test/functional/sqlsrv/srv_1329_string_truncation.phpt @@ -0,0 +1,112 @@ +--TEST-- +GitHub issue 1329 - string truncation error when binding some parameters as non-nulls the second time +--DESCRIPTION-- +The test shows the same parameters, though bound as nulls in the first insertion, can be bound as non-nulls in the subsequent insertions. +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- +'UTF-8'); +$conn = AE\connect($connectionInfo); + +dropTable($conn, 'srv_domains'); + +$tsql = << +--EXPECT-- +Array +( + [0] => 1 + [1] => foo.com + [2] => + [3] => + [4] => +) +Array +( + [0] => 2 + [1] => detached-with-ředirects.com + [2] => fŏő.com + [3] => baŗ.com + [4] => +) +Array +( + [0] => 3 + [1] => Őther-redirects.com + [2] => fooš.com + [3] => + [4] => ŷëå +) +Done