NAME
DBIO::MySQL::Util - Shared MySQL/MariaDB-specific helper functions for DBIO
VERSION
version 0.900004
SYNOPSIS
use DBIO::MySQL::Util qw(mask_error_details);
my $message = mask_error_details(
q{Duplicate entry 'a@b.c' for key 'users.email'}
);
# Duplicate entry '***' for key 'users.email'
DESCRIPTION
Helpers of the MySQL and MariaDB 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);
MySQL and MariaDB write the offending value into their error text, also when the value was a bind: Incorrect integer value: 'x' for column 'i', Duplicate entry 'x' for key 'users.email'. Both DBDs put the bound values into the statement text themselves, so a syntax error quotes them in its near '...' excerpt. The family's rule is that a message names keys, columns and options, never values; the engine's text is the driver's to keep to it, and this is where the driver does.
Every value in the sentences of the engine that quote one is replaced by ***, and what the caller needs to find the cause stays: the type, the column, the constraint, the key, the position.
Incorrect integer value: '***' for column 'i' at row 1
Incorrect string value: '***' for column `db`.`t`.`c` at row 1
Truncated incorrect DOUBLE value: '***'
Duplicate entry '***' for key 't.PRIMARY'
Invalid utf8mb4 character string: '***'
Unknown or incorrect time zone: '***'
Variable 'sql_mode' can't be set to the value of '***'
The value is all that lies between the quotes of the sentence, up to the last quote that ends it, so a value with quotes, commas, newlines or the words of the sentence in it is masked whole. The key of Duplicate entry is one text: the values of a composite key cannot be told apart in it, and all of it is masked. A text that has the start of such a sentence but not its end loses all that follows the start.
A syntax error names the part of the statement it stopped at:
You have an error in your SQL syntax; ... use near 'fw_t where s = '***'' at line 1
The excerpt is the statement with the values written into it, and nothing in it tells a bound value from a literal of the statement. So each quoted literal (single or double quotes, backslash escapes and doubled quotes included) is replaced by ***, also the literal that the server cut off at the edge of the excerpt, and each bare number is, which is how a value of a numeric type is written. The rest of the excerpt stays: the words of the statement, quoted names, NULL.
... use near 'fw_t where s = *** and i = ***' at line 1
\@binds is optional: the values bound to the statement. Each one of four characters or more that is found elsewhere in the message (a name taken from a bind) is replaced as well, as it is, as DBD writes it into a literal (\', \n, ...) and as UTF-8 bytes. 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 the statement that was run. The excerpt of a syntax error is masked without it, so it is accepted for the signature of the hook that calls this function and is not consulted.
A message the sentences do not know is returned as it is, and so is one without a value: Data truncated for column 'e' at row 1, Data too long, Out of range value, Column 'i' cannot be null, a check or foreign key violation. The result of the function gives the same result when it is masked again.
SEE ALSO
DBIO::MySQL::Storage - the storage whose refused statements these texts come from
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.