-
Notifications
You must be signed in to change notification settings - Fork 374
Description
PHP Driver version or file name
5.10.0beta1
SQL Server version
I'm using docker image mcr.microsoft.com/mssql/server:2019-latest
.
Client operating system
Alpine.
PHP version
8.1 RC6
Microsoft ODBC Driver version
17.5.2.2
Table schema
Included in repo with reproducible sandbox: ddl.sql
CREATE TABLE shlink_test.dbo.domains (
id bigint IDENTITY(1,1) NOT NULL,
authority nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
base_url_redirect nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
regular_not_found_redirect nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
invalid_short_url_redirect nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT PK__domains__3213E83F512B36BA PRIMARY KEY (id)
);
Problem description
It took me some time to reproduce this on a small env, and I'm still not completely sure if the error is on the driver itself, or on how the DBAL library I use (doctrine) is handling prepared statements internally, but this is reproducible only with PHP 8.1 and pdo_sqlsrv 5.10. With PHP 8.0 and pdo_sqlsrv 5.9 everything works as expected.
Expected behavior and actual behavior
Expected behavior: Reusing the same prepared statement with new bind params, allows for the same query to be run again.
Actual behavior: The second time the same prepared statement is used, the error [Microsoft][ODBC Driver 17 for SQL Server]String data, right truncation
is thrown.
Repro code or steps to reproduce
I have prepared a small repository with everything needed to reproduce the steps. The README file explains how to start 3 docker containers, one with MS SQL server, one with PHP 8.0, and one with PHP 8.1, and then how to create the database, and run a simple PHP script in both PHP containers.
But in short, this is the script:
<?php
declare(strict_types=1);
var_dump(PHP_VERSION);
$pdo = new PDO('sqlsrv:server=mssql,1433;Database=shlink_test', 'sa', 'Passw0rd!');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$st = $pdo->prepare(
'INSERT INTO domains (authority, base_url_redirect, regular_not_found_redirect, invalid_short_url_redirect) VALUES (?, ?, ?, ?)'
);
$authority = 'foo.com';
$base = null;
$notFound = null;
$invalid = null;
$st->bindParam(1, $authority);
$st->bindParam(2, $base);
$st->bindParam(3, $notFound);
$st->bindParam(4, $invalid);
$st->execute();
$authority = 'detached-with-redirects.com';
$base = 'foo.com';
$notFound = 'bar.com';
$invalid = null;
$st->bindParam(1, $authority);
$st->bindParam(2, $base);
$st->bindParam(3, $notFound);
$st->bindParam(4, $invalid);
$st->execute();