[Dbix-class] Get generated SQL
Matt Lawrence
matt.lawrence at ymogen.net
Wed Mar 12 12:30:14 GMT 2008
Mark Lawrence wrote:
> On Tue Mar 11, 2008 at 06:12:37PM +0000, Matt Lawrence wrote:
>
>
>> +=head2 as_static_sql
>> +
>> + $sql = $cursor->as_static_sql([ \%datatypes | \@datatypes ])
>> +
>> +Returns the SQL for the cursor as complete SQL, with placeholders replaced with
>> +relevant values, quoted by DBI's L<quote|DBI/quote> method.
>> +
>> +If a reference is passed as an argument it is used to ascertain the data type
>> +to pass to L<quote()|DBI/quote>. Array refs are passed in order for the
>> +positional parameters, hashrefs are mapped to columns by name.
>> +
>> +Warnings are issued if there is a mismatch between the number of placeholders
>> +and the number of bind values.
>> +
>> +Passing this SQL to a database is not recommended, certainly not
>> +programmatically. It should be used for informational or debugging purposes
>> +only.
>> +
>> +=cut
>> +
>> +sub as_static_sql {
>> + my ($self, $datatypes) = @_;
>> + my $storage = $self->{storage};
>> +
>> + my ($sql, $bind) = $self->_as_sql;
>> +
>> + if (ref $datatypes eq 'HASH') {
>> + $datatypes = [ map { $datatypes->{$_->[0]} } @$bind ];
>> + }
>> + elsif (ref $datatypes ne 'ARRAY') {
>> + $datatypes = [];
>> + }
>> +
>> + # Store quoted versions of the values
>> + my @bind_vals = map {
>> + $storage->dbh->quote($_->[1], shift @$datatypes)
>> + } @$bind;
>> +
>> + # Replace placeholders in the SQL string directly
>> + # Are there any other possible placeholders other than '?'
>> + $sql =~ s/(\?)/shift @bind_vals || $1/ge;
>> +
>> + # Check for a mismatch in the number of placeholders
>> + if (my $extra = $sql =~ y/\?/\?/) {
>> + warn "$extra extra placeholder", $extra==1?'':'s', " in SQL";
>> + }
>> + elsif (@bind_vals) {
>> + warn @bind_vals." extra bind parameter", @bind_vals==1?'':'s';
>> + }
>> +
>> + return $sql;
>> +}
>>
>
> You don't deal with binary (non-printable) data. Assuming this is method
> is for debugging purposes its usefulness is limited to pure text and
> won't work for mixed text/binary queries.
>
Specifying the data type for the bind columns should allow the driver to
properly escape binary data where appropriate, albeit non-automatically.
I guess I could add a failsafe to trap unprintable values still present
after quote() and replace them with dummy values as in your previous
example.
# Store quoted versions of the values
my @bind_vals = map {
$_ = $storage->dbh->quote($_->[1], shift @$datatypes);
$_ = $storage->dbh->quote('*BINARY DATA*') if /[^[:print:]\n\t]/;
$_;
} @$bind;
Are there any circumstances where unprintable values would be wanted anyway?
Matt
More information about the DBIx-Class
mailing list