msphpsql
msphpsql copied to clipboard
Binary stream returned from a statement becomes invalid if the statement gets implicitly closed
PHP version 8.2.3
PHP SQLSRV or PDO_SQLSRV version 5.10.1
Microsoft ODBC Driver version
2.3.11
SQL Server version
15.00.4236
Client operating system
macOS
Problem description
If a function prepares and executes a statement that returns an sqlsrv_stream
, then the stream becomes invalid outside of the function.
Expected behavior The stream is valid as long as it has at least one reference.
Actual behavior The stream is invalid. Passing it to any stream function results in the following error message:
TypeError: supplied resource is not a valid stream resource
Additionally, instead of "sqlsrv_stream", Xdebug displays the stream type as "Unknown".
Repro code or steps to reproduce
function get_stream($conn) {
$stmt = sqlsrv_query($conn, "SELECT CONVERT(VARBINARY, '0x41')");
sqlsrv_fetch($stmt);
return sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
}
$conn = sqlsrv_connect('127.0.0.1', [
'UID' => 'sa',
'PWD' => 'Passw0rd',
]);
$stream = get_stream($conn);
var_dump(stream_get_meta_data($stream));
Inlining the code of the get_stream
function mitigates the problem.
Hi, we're looking into it.
Seems the driver is designed to free the stream when the statement closes. But you could pass the $stmt to the function, and unset($stmt) when you're done.
<?php
function get_stream($stmt) {
sqlsrv_fetch($stmt);
return sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
}
$conn = sqlsrv_connect('127.0.0.1', [
'UID' => 'sa',
'PWD' => '',
]);
$stmt = sqlsrv_query($conn, "SELECT CONVERT(VARBINARY, '0x41')");
$stream = get_stream($stmt);
var_dump(stream_get_meta_data($stream));
unset($stmt);
?>
This is still a workaround. The intent is to have a function that accepts a connection and returns the stream. The statement is an implementation detail of the function, not an external dependency.
Seems the driver is designed to free the stream when the statement closes.
This doesn't look like a valid design. If the stream depends on the statement, then the statement should be automatically closed only when it's no longer referenced by the userland code and any internal resources (e.g. streams).