~ubuntu-branches/ubuntu/vivid/drizzle/vivid-proposed

« back to all changes in this revision

Viewing changes to tests/kewpie/randgen/lib/GenTest/Transform/DisableChosenPlan.pm

  • Committer: Package Import Robot
  • Author(s): Tobias Frost
  • Date: 2013-08-22 20:18:31 UTC
  • mto: (20.1.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20130822201831-gn3ozsh7o7wmc5tk
Tags: upstream-7.2.3
ImportĀ upstreamĀ versionĀ 7.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# This program is free software; you can redistribute it and/or modify
2
 
# it under the terms of the GNU General Public License as published by
3
 
# the Free Software Foundation; version 2 of the License.
4
 
#
5
 
# This program is distributed in the hope that it will be useful, but
6
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
7
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8
 
# General Public License for more details.
9
 
#
10
 
# You should have received a copy of the GNU General Public License
11
 
# along with this program; if not, write to the Free Software
12
 
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
13
 
# USA
14
 
 
15
 
package GenTest::Transform::DisableChosenPlan;
16
 
 
17
 
require Exporter;
18
 
@ISA = qw(GenTest GenTest::Transform);
19
 
 
20
 
use strict;
21
 
use lib 'lib';
22
 
use GenTest;
23
 
use GenTest::Transform;
24
 
use GenTest::Constants;
25
 
use Data::Dumper;
26
 
 
27
 
#
28
 
# This Transform runs EXPLAIN on the query, determines which (subquery) optimizations were used
29
 
# and disables them so that the query can be rerun with a "second-best" plan. This way the best and
30
 
# the "second best" plans are checked against one another.
31
 
#
32
 
# This has the following benefits:
33
 
# 1. The query plan that is being validated is the one actually chosen by the optimizer, so that one can
34
 
# run a comprehensive subquery test without having to manually fiddle with @@optimizer_switch
35
 
# 2. The plan that is used for validation is hopefully also fast enough, as compared to using unindexed nested loop
36
 
# joins with re-execution of the enitre subquery for each loop.
37
 
#
38
 
 
39
 
my @explain2switch = (
40
 
        [ 'sort_intersect'      => "optimizer_switch='index_merge_sort_intersection=off'"],
41
 
        [ 'intersect'           => "optimizer_switch='index_merge_intersection=off'"],
42
 
        [ 'firstmatch'          => "optimizer_switch='firstmatch=off'" ],
43
 
        [ '<expr_cache>'        => "optimizer_switch='subquery_cache=off'" ],
44
 
        [ 'materializ'          => "optimizer_switch='materialization=off,in_to_exists=on'" ],
45
 
        [ 'semijoin'            => "optimizer_switch='semijoin=off'" ],
46
 
        [ 'Start temporary'     => "optimizer_switch='semijoin=off'" ],
47
 
        [ 'loosescan'           => "optimizer_switch='loosescan=off'" ],
48
 
        [ '<subquery'           => "optimizer_switch='materialization=off,in_to_exists=on'" ],
49
 
        [ '<exists>'            => "optimizer_switch='in_to_exists=off,materialization=on'" ],
50
 
        [ qr{hash|BNLH|BKAH}    => "optimizer_switch='join_cache_hashed=off'" ],        
51
 
        [ 'BKA'                 => "optimizer_switch='join_cache_bka=off'" ],
52
 
        [ 'incremental'         => "optimizer_switch='join_cache_incremental=off'" ],
53
 
        [ 'join buffer'         => "join_cache_level=0" ],
54
 
        [ 'join buffer'         => "optimizer_join_cache_level=0" ],
55
 
        [ 'mrr'                 => "optimizer_switch='mrr=off'" ],
56
 
        [ 'index condition'     => "optimizer_switch='index_condition_pushdown=off'" ],
57
 
        [ qr{DERIVED}s          => "optimizer_switch='derived_merge=on'" ],
58
 
        [ qr{(?!DERIVED)}s      => "optimizer_switch='derived_merge=off'" ],
59
 
        [ qr{key[0-9]}          => "optimizer_switch='derived_with_keys=off'" ],
60
 
        [ 'Key-ordered'         => "optimizer_switch='mrr_sort_keys=off'" ],
61
 
        [ 'Key-ordered'         => "optimizer_switch='mrr=off'" ],
62
 
        [ 'Rowid-ordered'       => "optimizer_switch='mrr=off'" ]
63
 
);
64
 
 
65
 
my %explain2count;
66
 
 
67
 
my $available_switches;
68
 
 
69
 
sub transform {
70
 
        my ($class, $original_query, $executor) = @_;
71
 
 
72
 
        if (not defined $available_switches) {
73
 
                my $dbh_probe = DBI->connect($executor->dsn(), undef, undef, { PrintError => 0 } );
74
 
                
75
 
                foreach my $explain2switch (@explain2switch) {
76
 
                        my ($explain_fragment, $optimizer_switch) = ($explain2switch->[0], $explain2switch->[1]);
77
 
                        my $sth_probe = $dbh_probe->prepare("SET SESSION $optimizer_switch");
78
 
                        $sth_probe->execute();
79
 
                        $available_switches->{$optimizer_switch}++ if not defined $sth_probe->err();
80
 
                }
81
 
        }
82
 
 
83
 
        return STATUS_WONT_HANDLE if $original_query !~ m{^\s*SELECT}sio;
84
 
 
85
 
        my $original_explain = $executor->execute("EXPLAIN EXTENDED $original_query");
86
 
 
87
 
        if ($original_explain->status() == STATUS_SERVER_CRASHED) {
88
 
                return STATUS_SERVER_CRASHED;
89
 
        } elsif ($original_explain->status() ne STATUS_OK) {
90
 
                say("Query: $original_query EXPLAIN failed: ".$original_explain->err()." ".$original_explain->errstr());
91
 
                return $original_explain->status();
92
 
        }
93
 
 
94
 
        my $original_explain_string = Dumper($original_explain->data())."\n".Dumper($original_explain->warnings());
95
 
 
96
 
        my @transformed_queries;
97
 
        foreach my $explain2switch (@explain2switch) {
98
 
                my ($explain_fragment, $optimizer_switch) = ($explain2switch->[0], $explain2switch->[1]);
99
 
                next if not exists $available_switches->{$optimizer_switch};
100
 
                if ($original_explain_string =~ m{$explain_fragment}si) {
101
 
                        $explain2count{"$explain_fragment => $optimizer_switch"}++;
102
 
                        my ($switch_name) = $optimizer_switch =~ m{^(.*?)=}sgio;
103
 
                        push @transformed_queries, [
104
 
                                'SET @switch_saved = @@'.$switch_name.';',
105
 
                                "SET SESSION $optimizer_switch;",
106
 
                                "$original_query /* TRANSFORM_OUTCOME_UNORDERED_MATCH */ ;",
107
 
                                'SET SESSION '.$switch_name.'=@switch_saved'
108
 
                        ];
109
 
                }
110
 
        }
111
 
 
112
 
        if ($#transformed_queries > -1) {
113
 
                return \@transformed_queries;
114
 
        } else {
115
 
                return STATUS_WONT_HANDLE;
116
 
        }
117
 
}
118
 
 
119
 
sub DESTROY {
120
 
        if (rqg_debug()) {
121
 
                say("DisableChosenPlan statistics:");
122
 
                print Dumper \%explain2count;
123
 
        }
124
 
}
125
 
 
126
 
1;