Skip to content

Commit

Permalink
Use mysql_exec_statement API whenever possible
Browse files Browse the repository at this point in the history
The list of statements supported by the prepared statement API includes most things:
https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html#prepared-statements-permitted

Consistently using this API when possible provides consistency with NULL handling and potentially other divergences which we've not yet discovered.

A few, such as LOCK TABLE or LOAD TABLE or SHOW WARNINGS, are yet supported so fallback to the older query mechanism when required. If performance with this type of query is an issue, peaking at the first word might be possible rather than relying strictly on the try/catch.
  • Loading branch information
rbt committed Apr 8, 2022
1 parent 2694344 commit 0778fc5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
22 changes: 16 additions & 6 deletions lib/DBDish/mysql/Connection.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,25 @@ method prepare(Str $statement, *%args) {

# Override DBIish::Connection.execute as statements such as LOCK TABLE cannot
# be prepared in MySQL.
# Avoid looking into the query string by using a simple parameter count
# and skipping the prepare step for queries without parameters.
method execute(Str $statement, **@params, *%args) {
if @params.elems == 0 {
return DBDish::mysql::StatementHandle.new(
:$!mysql-client, :parent(self), :$statement, :$!RaiseError, |%args).execute;
} else {
try {
# Copied from the DBIish::Connection.execute
return self.prepare($statement, |%args).execute(|@params);

# A small number of statements cannot be executed using prepare/execute. Handle these
# by calling the older protocol. We try very hard to use the newer protocol first as
# it has several bug and minor behaviour fixes such as the handling of NULLs.
CATCH {
when X::DBDish::DBError::mysql {
when $_.code == 1 and $_.sqlstate eq 'HY000' and $_.native-message eq 'This command is not supported in the prepared statement protocol yet' {
return DBDish::mysql::StatementHandle.new(
:$!mysql-client, :parent(self), :$statement, :$!RaiseError, |%args).execute;
}
default {
.rethrow;
}
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/DBDish/mysql/StatementHandle.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ method execute(*@params --> DBDish::StatementHandle) {
}
without self!handle-errors { .fail }
}
else { # Unprepared path
else { # Unprepared path, seldome used.
$!parent.protect-connection: {
my $status = $!mysql-client.mysql_query($!statement)
and self!set-err($status, $!mysql-client.mysql_error).fail;
Expand Down

0 comments on commit 0778fc5

Please sign in to comment.