NAME
DBIO::MSSQL::Util - Shared MSSQL-specific helper functions for DBIO
VERSION
version 0.900004
SYNOPSIS
use DBIO::MSSQL::Util qw(mask_error_details);
my $message = mask_error_details(
q{Conversion failed when converting the varchar value 'x@y.z' to data type int.}
);
# Conversion failed when converting the varchar value '***' to data type int.
DESCRIPTION
Helpers of the MSSQL driver that do not belong to one class.
METHODS
mask_error_details
my $message = mask_error_details($message);
my $message = mask_error_details($message, \@binds);
my $message = mask_error_details($message, \@binds, $statement);
SQL Server writes the offending value into its error text, also when the value was a bind: Conversion failed when converting the varchar value 'x' to data type int., The duplicate key value is (x).. The family's rule is that a message names keys, columns and options, never values; the server's text is the driver's to keep to it, and this is where the driver does.
Every value in the sentences of the server that quote one is replaced by ***, and what the caller needs to find the cause stays: the type, the table, the column, the constraint.
Conversion failed when converting the varchar value '***' to data type int.
The conversion of the varchar value '***' overflowed an INT2 column. Use a larger integer column.
Violation of PRIMARY KEY constraint 'pk_x'. Cannot insert duplicate key in object 'dbo.t'. The duplicate key value is (***).
String or binary data would be truncated in table 'tempdb.dbo.t', column 's'. Truncated value: '***'.
Incorrect syntax near '***'.
JSON text is not properly formatted. Unexpected character '***' is found at position 1.
An apostrophe in a value is written twice in the server's text and is read that way. The duplicate key value has no column names and may hold , and ), so all of it up to the last ). of the text is masked (the text after it, if there is any, is not).
The server cuts a message at about 2000 characters; a long value then runs to the end of the message and has no closing quote. Such a value is masked to the end of the message (the end of the text, the (SQL-nnnnn) of DBD::ODBC, the next message of DBD::Sybase), and the cut text gets the closing quote.
The rules look at the text of a server message wherever it stands: after the Server message number=... text= of DBD::Sybase, between the [FreeTDS][SQL Server] and the (SQL-22018) of DBD::ODBC, in the second of several messages.
\@binds is optional: the values bound to the statement. Each one of four characters or more (as it is, and written for a string literal, with an apostrophe doubled) that is found elsewhere in the message is replaced as well, longest first. Shorter values, undef and references are not looked for, since a letter or a number is part of any text; the sentences above hold those.
$statement is accepted for the family's signature and not used: SQL Server does not append an excerpt of the statement to its messages.
The limit is deliberate. A message the rules do not know is returned as it is, and so is one without a value (Violation of FOREIGN KEY constraint ... The conflict occurred in database "d", table "dbo.p"., Cannot insert the value NULL into column 'b', ..., Incorrect syntax near the keyword 'FROM'., the conversion errors that name no value). Names of tables, columns and constraints are never masked. The text of a RAISERROR or THROW the application's own SQL raises is the application's and is not looked at beyond the bound values; and $dbh->errstr stays as the DBD has it.
SEE ALSO
DBIO::MSSQL::Storage - the storage whose refused statements these texts belong to
AUTHOR
DBIO & DBIx::Class Authors
COPYRIGHT AND LICENSE
Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.