Permalink
Browse files

Refactor distill in prep for QueryParser::query_type().

git-svn-id: http://maatkit.googlecode.com/svn/trunk@4968 dfb901c2-3250-0410-b216-0b33211c9131
  • Loading branch information...
1 parent 309cf1b commit a46a96c9495ec07858eba60966f3c00760ebc8a1 daniel@percona.com committed Oct 29, 2009
Showing with 91 additions and 13 deletions.
  1. +7 −3 common/QueryParser.pm
  2. +30 −10 common/QueryRewriter.pm
  3. +54 −0 common/t/QueryParser.t
View
@@ -224,7 +224,7 @@ sub get_aliases {
sub split {
my ( $self, $query ) = @_;
return unless $query;
- $query = clean_query($query);
+ $query = $self->clean_query($query);
MKDEBUG && _d('Splitting', $query);
my $verbs = qr{SELECT|INSERT|UPDATE|DELETE|REPLACE|UNION|CREATE}i;
@@ -256,7 +256,7 @@ sub split {
}
sub clean_query {
- my ( $query ) = @_;
+ my ( $self, $query ) = @_;
return unless $query;
$query =~ s!/\*.*?\*/! !g; # Remove /* comment blocks */
$query =~ s/^\s+//; # Remove leading spaces
@@ -268,7 +268,7 @@ sub clean_query {
sub split_subquery {
my ( $self, $query ) = @_;
return unless $query;
- $query = clean_query($query);
+ $query = $self->clean_query($query);
$query =~ s/;$//;
my @subqueries;
@@ -332,6 +332,10 @@ sub split_subquery {
return $query, map { $_->{sql} } grep { defined $_ } @subqueries;
}
+sub query_type {
+ my ( $self, $query ) = @_;
+}
+
sub _d {
my ($package, undef, $line) = caller 0;
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
View
@@ -180,12 +180,8 @@ sub fingerprint {
return $query;
}
-# This is kind of like fingerprinting, but it super-fingerprints to something
-# that shows the query type and the tables/objects it accesses.
-sub distill {
- my ( $self, $query, %args ) = @_;
- my $qp = $args{qp} || $self->{QueryParser};
- die "I need a qp argument" unless $qp;
+sub _distill_verbs {
+ my ( $self, $query ) = @_;
# Special cases.
$query =~ m/\A\s*call\s+(\S+)\(/i
@@ -208,12 +204,11 @@ sub distill {
if ( $dds ) {
my ( $obj ) = $query =~ m/$dds.+(DATABASE|TABLE)\b/i;
$obj = uc $obj if $obj;
- MKDEBUG && _d('Data def statment:', $dds, $obj);
+ MKDEBUG && _d('Data def statment:', $dds, 'obj:', $obj);
my ($db_or_tbl)
= $query =~ m/(?:TABLE|DATABASE)\s+($QueryParser::tbl_ident)(\s+.*)?/i;
MKDEBUG && _d('Matches db or table:', $db_or_tbl);
- $obj .= ($db_or_tbl ? " $db_or_tbl" : '');
- return uc($dds) . ($obj ? " $obj" : '');
+ return uc($dds . ($obj ? " $obj" : '')), $db_or_tbl;
}
# First, get the query type -- just extract all the verbs and collapse them
@@ -226,20 +221,45 @@ sub distill {
my $verbs = join(q{ }, @verbs);
$verbs =~ s/( UNION SELECT)+/ UNION/g;
+ return $verbs;
+}
+
+sub _distill_tables {
+ my ( $self, $query, $table, %args ) = @_;
+ my $qp = $args{qp} || $self->{QueryParser};
+ die "I need a qp argument" unless $qp;
+
# "Fingerprint" the tables.
my @tables = map {
$_ =~ s/`//g;
$_ =~ s/(_?)[0-9]+/$1?/g;
$_;
} $qp->get_tables($query);
+ push @tables, $table if $table;
+
# Collapse the table list
@tables = do {
my $last = '';
grep { my $pass = $_ ne $last; $last = $_; $pass } @tables;
};
- $query = join(q{ }, $verbs, @tables);
+ return @tables;
+}
+
+# This is kind of like fingerprinting, but it super-fingerprints to something
+# that shows the query type and the tables/objects it accesses.
+sub distill {
+ my ( $self, $query, %args ) = @_;
+
+ # _distill_verbs() may return a table if it's a special statement
+ # like TRUNCATE TABLE foo. _distill_tables() handles some but not
+ # all special statements so we pass it this special table in case
+ # it's a statement it can't handle. If it can handle it, it will
+ # eliminate any duplicate tables.
+ my ($verbs, $table) = $self->_distill_verbs($query, %args);
+ my @tables = $self->_distill_tables($query, $table, %args);
+ $query = join(q{ }, $verbs, @tables);
return $query;
}
View
@@ -688,6 +688,60 @@ is_deeply(
);
# #############################################################################
+# Test query_type().
+# #############################################################################
+is(
+ 'select * from foo where id=1',
+ {
+ type => 'select',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+is(
+ 'insert into foo values (1, 2)',
+ {
+ type => 'insert',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+is(
+ 'select * from foo where id=1',
+ {
+ type => 'select',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+is(
+ 'select * from foo where id=1',
+ {
+ type => 'select',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+is(
+ 'select * from foo where id=1',
+ {
+ type => 'select',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+is(
+ 'select * from foo where id=1',
+ {
+ type => 'select',
+ rw => 'read',
+ },
+ 'query_type() select'
+);
+
+exit;
+
+# #############################################################################
# Issue 563: Lock tables is not distilled
# #############################################################################
is_deeply(

0 comments on commit a46a96c

Please sign in to comment.