Author: spadkins
Date: Tue Jun 20 12:37:48 2006
New Revision: 6553

Modified:
   p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm
   p5ee/trunk/App-Repository/lib/App/Repository/MySQL.pm

Log:
added automatic timings on all debug_sql. added explain_sql.

Modified: p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm Tue Jun 20 12:37:48 2006
@@ -12,6 +12,7 @@
 @ISA = ( "App::Repository" );
 
 use Data::Dumper;
+use Time::HiRes qw(gettimeofday);
 
 use strict;
 
@@ -382,8 +383,11 @@
         $dbh = $self->{dbh};
     }
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _get_row()\n";
         print $sql;
     }
@@ -410,12 +414,16 @@
         }
     }
     if ($debug_sql) {
-        print "DEBUG_SQL: nrows [", (defined $row ? 1 : 0), "] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: nrows [", (defined $row ? 1 : 0), "] ($elapsed_time 
sec) $DBI::errstr\n";
         if ($debug_sql >= 2) {
             print "DEBUG_SQL: [", ($row ? join("|",map { defined $_ ? $_ : 
"undef" } @$row) : ""), "]\n";
         }
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($row) if ($App::trace);
     return($row);
@@ -441,8 +449,11 @@
     $startrow = $options->{startrow} || 0;
     $endrow   = $options->{endrow} || 0;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _get_rows()\n";
         print $sql;
     }
@@ -468,7 +479,8 @@
         }
     }
     if ($debug_sql) {
-        print "DEBUG_SQL: nrows [", (defined $rows ? ($#$rows+1) : 0), "] 
$DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: nrows [", (defined $rows ? ($#$rows+1) : 0), "] 
($elapsed_time sec) $DBI::errstr\n";
         if ($debug_sql >= 2) {
             foreach my $row (@$rows) {
                 print "DEBUG_SQL: [", join("|",map { defined $_ ? $_ : 
"undef"} @$row), "]\n";
@@ -476,6 +488,9 @@
         }
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($rows) if ($App::trace);
     return($rows);
@@ -2096,17 +2111,24 @@
     my $dbh = $self->{dbh};
     my $retval = 0;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: insert()\n";
         print "DEBUG_SQL: bind vars [", join("|",map { defined $_ ? $_ : 
"undef" } @$row), "]\n";
         print $sql;
     }
     $retval = $dbh->do($sql, undef, @$row) if (defined $dbh);
     if ($debug_sql && $debug_sql >= 2) {
-        print "DEBUG_SQL: retval [$retval] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: retval [$retval] ($elapsed_time sec) $DBI::errstr\n";
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     $retval;
@@ -2125,7 +2147,12 @@
     my $nrows = 0;
     my $ok = 1;
     $sql = $self->_mk_insert_row_sql($table, $cols);
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
+    if ($debug_sql) {
+        $timer = $self->_get_timer();
+    }
     foreach my $row (@$rows) {
         if ($debug_sql) {
             print "DEBUG_SQL: _insert_rows()\n";
@@ -2147,6 +2174,13 @@
             last;
         }
     }
+    if ($debug_sql) {
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: nrows [$nrows] ($elapsed_time sec)\n";
+    }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
     $self->{sql} = $sql;
     $self->{numrows} = $nrows;
     &App::sub_exit($nrows) if ($App::trace);
@@ -2160,16 +2194,23 @@
     my $sql = $self->_mk_delete_sql($table, $params, $cols, $row, $options);
     $self->{sql} = $sql;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _delete()\n";
         print $sql;
     }
     my $retval = $self->{dbh}->do($sql);
     if ($debug_sql) {
-        print "DEBUG_SQL: retval [$retval] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: retval [$retval] ($elapsed_time sec) $DBI::errstr\n";
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     return($retval);
@@ -2187,17 +2228,24 @@
     my $sql = $self->_mk_update_sql($table, $params, $cols, $row, $options);
     $self->{sql} = $sql;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _update()\n";
         print $sql;
     }
     my $retval = $self->{dbh}->do($sql);
     $retval = 0 if ($retval == 0);
     if ($debug_sql) {
-        print "DEBUG_SQL: retval [$retval] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: retval [$retval] ($elapsed_time sec) $DBI::errstr\n";
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     return($retval);
@@ -2213,16 +2261,23 @@
     my $dbh = $self->{dbh};
     my $retval = 0;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _delete_row()\n";
         print $sql;
     }
     $retval = $dbh->do($sql) if (defined $dbh);
     if ($debug_sql) {
-        print "DEBUG_SQL: retval [$retval] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: retval [$retval] ($elapsed_time sec) $DBI::errstr\n";
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     $retval;
@@ -2238,16 +2293,23 @@
     my $dbh = $self->{dbh};
     my $retval = 0;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _delete_rows()\n";
         print $sql;
     }
     $retval = $dbh->do($sql) if (defined $dbh);
     if ($debug_sql) {
-        print "DEBUG_SQL: retval [$retval] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: retval [$retval] ($elapsed_time sec) $DBI::errstr\n";
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     $retval;
@@ -2261,8 +2323,11 @@
     my $dbh = $self->{dbh};
     my $retval = 0;
 
-    my $debug_sql = $self->{context}{options}{debug_sql};
+    my $context_options = $self->{context}{options};
+    my $debug_sql = $context_options->{debug_sql};
+    my ($timer, $elapsed_time);
     if ($debug_sql) {
+        $timer = $self->_get_timer();
         print "DEBUG_SQL: _do()\n";
         print $sql;
     }
@@ -2273,6 +2338,7 @@
         else {
             $retval = $dbh->do($sql);
         }
+        $self->{sql} = $sql;
     }
     if ($debug_sql) {
         my $nrows = 0;
@@ -2284,7 +2350,8 @@
                 $nrows = $retval;
             }
         }
-        print "DEBUG_SQL: nrows [$nrows] $DBI::errstr\n";
+        $elapsed_time = $self->_read_timer($timer);
+        print "DEBUG_SQL: nrows [$nrows] ($elapsed_time sec) $DBI::errstr\n";
         if ($debug_sql >= 2 && ref($retval)) {
             foreach my $row (@$retval) {
                 print "DEBUG_SQL: [", join("|",map { defined $_ ? $_ : 
"undef"} @$row), "]\n";
@@ -2292,11 +2359,53 @@
         }
         print "\n";
     }
+    if ($context_options->{explain_sql}) {
+        $self->explain_sql($sql);
+    }
 
     &App::sub_exit($retval) if ($App::trace);
     $retval;
 }
 
+sub explain_sql {
+    my ($self, $sql) = @_;
+    # to be overridden for each physical database
+}
+
+sub _get_timer {
+    my ($self) = @_;
+    my ($seconds_start, $microseconds_start) = gettimeofday;
+    my $timer = { seconds_start => $seconds_start, microseconds_start => 
$microseconds_start };
+    return($timer);
+}
+
+sub _read_timer {
+    my ($self, $timer, $reset) = @_;
+    my ($seconds_finish, $microseconds_finish) = gettimeofday;
+    my $seconds_elapsed           = $seconds_finish      - 
$timer->{seconds_start};
+    my $microseconds_elapsed      = $microseconds_finish - 
$timer->{microseconds_start};
+    if ($microseconds_elapsed < 0) {
+        $microseconds_elapsed += 1000000;
+        $seconds_elapsed      -= 1;
+    }
+    my $time_elapsed = sprintf("%d.%06d", $seconds_elapsed, 
$microseconds_elapsed);
+    if (defined $reset) {
+        # store values. don't reset the timer.
+        if ($reset == 0) {
+            $timer->{seconds_start}      = $seconds_finish;
+            $timer->{microseconds_start} = $microseconds_finish;
+            delete $timer->{time_elapsed};
+        }
+        # reset the timer to be ready for another reading.
+        elsif ($reset) {
+            $timer->{seconds_finish}      = $seconds_finish;
+            $timer->{microseconds_finish} = $microseconds_finish;
+            $timer->{time_elapsed}        = $time_elapsed;
+        }
+    }
+    return($time_elapsed);
+}
+
 ######################################################################
 # METADATA REPOSITORY METHODS (implements methods from App::Repository)
 ######################################################################

Modified: p5ee/trunk/App-Repository/lib/App/Repository/MySQL.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository/MySQL.pm       (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository/MySQL.pm       Tue Jun 20 
12:37:48 2006
@@ -66,6 +66,7 @@
     &App::sub_exit(defined $self->{dbh}) if ($App::trace);
     return(defined $self->{dbh});
 }
+
 sub _dsn {
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
@@ -380,5 +381,46 @@
     &App::sub_exit() if ($App::trace);
 }
 
+#+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+
+#| id | select_type | table | type  | possible_keys                       | 
key               | key_len | ref         | rows | Extra |
+#+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+
+#|  1 | SIMPLE      | t1    | const | hotel_prop_ds_ak1,hotel_prop_ds_ie1 | 
hotel_prop_ds_ak1 |       9 | const,const |    1 |       |
+#+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+
+sub explain_sql {
+    my ($self, $sql) = @_;
+    my $dbh = $self->{dbh};
+    # NOTE: MySQL "explain" only works for "select".
+    # We convert "update" and "delete" to "select" to explain them.
+    if (defined $dbh) {
+        if ($sql =~ s/^delete/select */is) {
+            # do nothing
+        }
+        elsif ($sql =~ s/^update\s+(.*)\sset\s+.*\swhere/select * from 
$1\nwhere/is) {
+            # do nothing
+        }
+        if ($sql =~ /^select/i) {
+            my ($rows);
+print $sql;
+            eval {
+                $rows = $dbh->selectall_arrayref("explain $sql");
+            };
+            print "EXPLAIN_SQL: $DBI::errstr\n";
+            if ($rows) {
+                print 
"+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+\n";
+                print "| id | select_type | table | type  | possible_keys      
                 | key               | key_len | ref         | rows | Extra 
|\n";
+                print 
"+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+\n";
+                foreach my $row (@$rows) {
+                    printf("|%3s | %-12s| %-6s| %-6s| %-36s| %-18s|%8d | 
%-12s|%5d | %-6s|\n", @$row);
+                }
+                print 
"+----+-------------+-------+-------+-------------------------------------+-------------------+---------+-------------+------+-------+\n";
+            }
+        }
+        else {
+            $sql =~ /^\s*(\S*)/;
+            print "EXPLAIN_SQL: Can't explain $1 statement.\n";
+        }
+    }
+}
+
 1;
 

Reply via email to