Author: spadkins
Date: Thu Jan  8 21:42:01 2009
New Revision: 12314

Modified:
   p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm
   p5ee/trunk/App-Repository/lib/App/Repository/Oracle.pm
   p5ee/trunk/App-Repository/t/DBI-select-join.t
   p5ee/trunk/App-Repository/t/RepositoryTestUtils.pm

Log:
fixed bug which caused joins to be out of order based on the dependencies

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 Thu Jan  8 21:42:01 2009
@@ -3089,6 +3089,49 @@
         }
     }
 
+    {   # ORDER THE TABLE ALIASES BASED ON DEPENDENCIES
+        my $tablealiases = $table_def->{tablealiases};
+        my $tablealias   = $table_def->{tablealias};
+        # print STDERR "ALIASES [$table] BEFORE : [...@$tablealiases]\n";
+        my @orig_tablealiases = @$tablealiases;
+        my (@ordered_tablealiases, $alias, %alias_seen, $dep, $dependencies, 
%alias_tries);
+        my $max_tries = $#$tablealiases + 1;
+        while ($#orig_tablealiases > -1) {
+            $alias = shift(@orig_tablealiases);
+            if ($alias_seen{$alias}) {
+                # do nothing (throw this duplicate copy away)
+            }
+            else {
+                $dependencies = $tablealias->{$alias}{dependencies};
+                if (!$dependencies || ref($dependencies) ne "ARRAY") {
+                    push(@ordered_tablealiases, $alias);
+                    $alias_seen{$alias} = 1;
+                }
+                else {
+                    my $dependencies_satisfied = 1;
+                    $alias_tries{$alias} = 0 if (! defined 
$alias_tries{$alias});
+                    if ($alias_tries{$alias} <= $max_tries) {
+                        foreach my $dep (@$dependencies) {
+                            if (!$alias_seen{$dep}) {    # $alias depends on 
another alias which has never been seen
+                                push(@orig_tablealiases, $alias); # so put it 
back on the end
+                                $dependencies_satisfied = 0;
+                                last;
+                            }
+                        }
+                    }
+                    $alias_tries{$alias}++;
+                    if ($dependencies_satisfied) {
+                        push(@ordered_tablealiases, $alias);
+                        $alias_seen{$alias} = 1;
+                    }
+                }
+            }
+        }
+        $tablealiases = \...@ordered_tablealiases;
+        $table_def->{tablealiases} = $tablealiases;
+        # print STDERR "ALIASES [$table] AFTER : [...@$tablealiases]\n";
+    }
+
     #if ($App::DEBUG >= 2 && $self->{context}->dbg(2)) {
     #    print $App::DEBUG_FILE "Table Metadata: $table\n";
     #    my $d = Data::Dumper->new([ $table_def ], [ "table_def" ]);

Modified: p5ee/trunk/App-Repository/lib/App/Repository/Oracle.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository/Oracle.pm      (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository/Oracle.pm      Thu Jan  8 
21:42:01 2009
@@ -605,52 +605,52 @@
     &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 TBDexplain_sql {
+#SQL> explain plan for select * from hotel_brand_grp where brand_grp_cd like 
'H%';
+#
+#Explained.
+#
+#SQL> SELECT * from table (dbms_xplan.display);
+#
+#PLAN_TABLE_OUTPUT
+#--------------------------------------------------------------------------------------------------------------------------------------------
+#Plan hash value: 980249155
+#
+#---------------------------------------------------------------------------------------------------
+#| Id  | Operation                   | Name                | Rows  | Bytes | 
Cost (%CPU)| Time     |
+#---------------------------------------------------------------------------------------------------
+#|   0 | SELECT STATEMENT            |                     |     2 |    84 |   
  1   (0)| 00:00:01 |
+#|   1 |  TABLE ACCESS BY INDEX ROWID| HOTEL_BRAND_GRP     |     2 |    84 |   
  1   (0)| 00:00:01 |
+#|*  2 |   INDEX RANGE SCAN          | HOTEL_BRAND_GRP_AK1 |     2 |       |   
  1   (0)| 00:00:01 |
+#---------------------------------------------------------------------------------------------------
+#
+#Predicate Information (identified by operation id):
+#
+#PLAN_TABLE_OUTPUT
+#--------------------------------------------------------------------------------------------------------------------------------------------
+#---------------------------------------------------
+#
+#   2 - access("BRAND_GRP_CD" LIKE 'H%')
+#       filter("BRAND_GRP_CD" LIKE 'H%')
+#
+#15 rows selected.
+
+sub explain_sql {
     my ($self, $sql) = @_;
     my $dbh = $self->{dbh};
-    # NOTE: Oracle "explain" only works for "select".
-    # We convert "update" and "delete" to "select" to explain them.
+    # NOTE: Oracle "explain" only works for "select", "update", and "delete".
     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) {
+        if ($sql =~ /^\s*(select|update|delete)/i) {
             my ($rows, $posskeys, $key, $keylen);
             eval {
-                $rows = $dbh->selectall_arrayref("explain $sql");
+                $dbh->do("explain plan for $sql");
+                $rows = $dbh->selectall_arrayref("select * from table 
(dbms_xplan.display)");
             };
             print $App::DEBUG_FILE "EXPLAIN_SQL: $DBI::errstr\n";
-            if ($rows) {
-                print $App::DEBUG_FILE 
"+----+-------------+----------------------+-------+----------------------+---------+----------+\n";
-                print $App::DEBUG_FILE "| id | select_type | table             
   | type  | key                  | key_len |     rows |\n";
-                print $App::DEBUG_FILE 
"+----+-------------+----------------------+-------+----------------------+---------+----------+\n";
-                foreach my $row (@$rows) {
-                    $key = $row->[5];
-                    $keylen = length($key);
-                    if ($keylen > 21) {
-                       $key = substr($key,0,12) . ".." . 
substr($key,$keylen-7,7);
-                    }
-                    printf($App::DEBUG_FILE "|%3s | %-12s| %-21s| %-6s| 
%-21s|%8d |%9d | %s\n", @{$row}[0,1,2,3], $key, @{$row}[6,8]);
-                }
-                print $App::DEBUG_FILE 
"+----+----------------------------------------------------------------------------------------+\n";
-                print $App::DEBUG_FILE "| id | possible_keys/ref/extra\n";
-                print $App::DEBUG_FILE 
"+----+----------------------------------------------------------------------------------------+\n";
-                foreach my $row (@$rows) {
-                    $key = $row->[5];
-                    $posskeys = $row->[4];
-                    $posskeys =~ s/\b($key)\b/[$key]/;
-                    printf($App::DEBUG_FILE "|%3s | posskeys: %s\n", 
$row->[0], $posskeys);
-                    printf($App::DEBUG_FILE "|%3s | ref:      %s; extra: 
%s\n", @{$row}[0,7,9]);
-                }
-                print $App::DEBUG_FILE 
"+---------------------------------------------------------------------------------------------+\n";
+            if ($rows && $#$rows == 0) {
+                print $App::DEBUG_FILE $rows->[0][0];
+            }
+            else {
+                print $App::DEBUG_FILE "EXPLAIN_SQL: Got unexpected result.\n";
             }
         }
         else {

Modified: p5ee/trunk/App-Repository/t/DBI-select-join.t
==============================================================================
--- p5ee/trunk/App-Repository/t/DBI-select-join.t       (original)
+++ p5ee/trunk/App-Repository/t/DBI-select-join.t       Thu Jan  8 21:42:01 2009
@@ -64,7 +64,8 @@
                     },
                     test_person => {
                       alias => "p",
-                      tablealiases => [ "p", "c", "ctry" ],
+                      #tablealiases => [ "p", "c", "ctry", "ctyctry" ],
+                      tablealiases => [ "ctyctry", "ctry", "c", "p", ],
                       tablealias => {
                         c => {
                           table => "test_city",
@@ -76,9 +77,15 @@
                           dependencies => [ "p" ],
                           joincriteria => "ctry.country = p.country",
                         },
+                        ctyctry => {
+                          table => "test_country",
+                          dependencies => [ "c", "p", ],
+                          joincriteria => "ctyctry.country = c.country",
+                        },
                       },
                       column => {
                         country_nm => { dbexpr => "ctry.country_nm", },
+                        city_country_nm => { dbexpr => "ctyctry.country_nm", },
                         gender     => { alias => "gnd", },
                       },
                     },
@@ -914,6 +921,28 @@
 is($sql, $expect_sql, "_mk_select_joined_sql(): city->country. where 
country_nm=JAPAN");
 &check_select($sql,2);
 
+$expect_sql = <<EOF;
+select
+   p.first_name,
+   p.last_name,
+   p.city,
+   p.state,
+   p.age
+from test_person p
+     inner join test_city c on c.city_cd = p.city_cd
+     inner join test_country ctyctry on ctyctry.country = c.country
+where ctyctry.country_nm = 'United States'
+EOF
+&test_get_rows($expect_sql, 0, "_mk_select_joined_sql(): ensure that joins are 
in order",
+    "test_person",
+    { city_country_nm => 'United States' },
+    ["first_name","last_name","city","state","age"]);
+$sql = $rep->_mk_select_joined_sql("test_person",
+    { city_country_nm => 'United States' },
+    ["first_name","last_name","city","state","age"]);
+is($sql, $expect_sql, "_mk_select_joined_sql(): ensure that joins are in 
order");
+&check_select($sql,0);
+
 exit(0);   # XXX REMOVE EXIT HERE XXX
 
 ###########################################################################

Modified: p5ee/trunk/App-Repository/t/RepositoryTestUtils.pm
==============================================================================
--- p5ee/trunk/App-Repository/t/RepositoryTestUtils.pm  (original)
+++ p5ee/trunk/App-Repository/t/RepositoryTestUtils.pm  Thu Jan  8 21:42:01 2009
@@ -57,6 +57,7 @@
     state          varchar(99)     null,
     zip            varchar(10)     null,
     country        char(2)         null,
+    city_cd        varchar(5)      null,
     home_phone     varchar(99)     null,
     work_phone     varchar(99)     null,
     email_address  varchar(99)     null,
@@ -202,6 +203,7 @@
     state          varchar(99)     null,
     zip            varchar(10)     null,
     country     char(2)         null,
+    city_cd        varchar(5)      null,
     home_phone     varchar(99)     null,
     work_phone     varchar(99)     null,
     email_address  varchar(99)     null,

Reply via email to