Francois Gouget : testbot/orm: Add support for multi-column Itemrefs.

Alexandre Julliard julliard at winehq.org
Tue Jun 7 15:37:01 CDT 2022


Module: tools
Branch: master
Commit: 763995636b6b2fb1e703fbb405b651d057a22ed0
URL:    https://source.winehq.org/git/tools.git/?a=commit;h=763995636b6b2fb1e703fbb405b651d057a22ed0

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Tue Jun  7 18:49:35 2022 +0200

testbot/orm: Add support for multi-column Itemrefs.

Also document why they are not supported in filters.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45023
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 testbot/lib/ObjectModel/CGI/ValueFormatter.pm |  6 ++--
 testbot/lib/ObjectModel/DBIBackEnd.pm         |  7 ++++-
 testbot/lib/ObjectModel/Item.pm               | 41 ++++++++++++++++++++-------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/testbot/lib/ObjectModel/CGI/ValueFormatter.pm b/testbot/lib/ObjectModel/CGI/ValueFormatter.pm
index 41d1e14..49bf856 100644
--- a/testbot/lib/ObjectModel/CGI/ValueFormatter.pm
+++ b/testbot/lib/ObjectModel/CGI/ValueFormatter.pm
@@ -306,16 +306,18 @@ sub GenerateValueHTML($$$;$)
   }
   elsif ($PropertyDescriptor->GetClass() eq "Itemref" and defined $Value)
   {
-    # Note: This only supports single-key Itemrefs
+    my $First = 1;
     foreach my $ValuePD (@{$Value->GetPropertyDescriptors()})
     {
       if ($ValuePD->GetIsKey())
       {
+        print "/" if (!$First);
+        $First = 0;
         my $PropertyName = $ValuePD->GetName();
         GenerateValueHTML($Parent, $ValuePD, $Value->$PropertyName);
-        return;
       }
     }
+    return;
   }
   print defined $Value ? $Parent->escapeHTML($Value) : " ";
 }
diff --git a/testbot/lib/ObjectModel/DBIBackEnd.pm b/testbot/lib/ObjectModel/DBIBackEnd.pm
index 62332c1..f4d1683 100644
--- a/testbot/lib/ObjectModel/DBIBackEnd.pm
+++ b/testbot/lib/ObjectModel/DBIBackEnd.pm
@@ -222,7 +222,12 @@ sub ColNameToDb($)
   my $ColNames = $PropertyDescriptor->GetColNames();
   if (@$ColNames != 1)
   {
-    die "cannot filter on Itemref with more than one column name: @$ColNames";
+    # This would require building a more complex where clause, something like
+    #   ((col1 = item1.val1 AND col2 = item1.val2...) OR
+    #    (col1 = item2.val1 AND col2 = item2.val2...) OR ...)
+    # So it is not supported. Instead one should build the where clause by
+    # hand from the underlying columns.
+    die "cannot filter on the ". $PropertyDescriptor->GetName() ." Itemref because it has a multi-column key: @$ColNames";
   }
   return $ColNames->[0];
 }
diff --git a/testbot/lib/ObjectModel/Item.pm b/testbot/lib/ObjectModel/Item.pm
index 39c80cc..593b039 100644
--- a/testbot/lib/ObjectModel/Item.pm
+++ b/testbot/lib/ObjectModel/Item.pm
@@ -281,26 +281,45 @@ sub AUTOLOAD
       }
       elsif($PropertyDescriptor->GetClass() eq "Itemref")
       {
-        my $ColNames = $PropertyDescriptor->GetColNames();
-        if (@{$ColNames} != 1)
-        {
-          die "Multiple key components not supported";
-        }
         if (@_)
         {
-          $self->{Itemrefs}{$PropertyName} = shift;
-          if ($self->ValuesDiffer($self->{ColValues}{@{$ColNames}[0]},
-                                  $self->{Itemrefs}{$PropertyName}->GetKey()))
+          my $Item = shift;
+          if (!$Item and !$self->{Itemrefs}{$PropertyName})
+          {
+            # No change -> nothing to do
+          }
+          elsif (!$Item)
+          {
+            $self->{IsModified} = 1;
+            $self->{Itemrefs}{$PropertyName} = undef;
+            foreach my $ColName (@{$PropertyDescriptor->GetColNames()})
+            {
+              $self->{ColValues}{$ColName} = undef;
+            }
+          }
+          elsif (!$self->{Itemrefs}{$PropertyName} or
+                 $self->{Itemrefs}{$PropertyName} ne $Item)
           {
             $self->{IsModified} = 1;
-            $self->{ColValues}{@{$ColNames}[0]} = $self->{Itemrefs}{$PropertyName}->GetKey();
+            $self->{Itemrefs}{$PropertyName} = $Item;
+            # Note that the foreign key names ($RefColNames) typically don't
+            # match the Item's primary key column names. But their order and
+            # count must match the primary key values.
+            my $RefColNames = $PropertyDescriptor->GetColNames();
+            my ($_ColNames, $ColValues) = $Item->GetMasterKey();
+            foreach my $ColIndex (0..$#{$RefColNames})
+            {
+              $self->{ColValues}{$RefColNames->[$ColIndex]} = $ColValues->[$ColIndex];
+            }
           }
         }
         elsif (! defined($self->{Itemrefs}{$PropertyName}))
         {
+          my $ColNames = $PropertyDescriptor->GetColNames();
+          my @KeyComponents = map { $self->{ColValues}{$_} || "" } @$ColNames;
           my $Collection = &{$PropertyDescriptor->GetCreator()}($self);
-          my $Item = $Collection->GetItem($self->{ColValues}{@{$ColNames}[0]});
-          $self->{Itemrefs}{$PropertyName} = $Item;
+          my $Key = $Collection->CombineKey(@KeyComponents);
+          $self->{Itemrefs}{$PropertyName} = $Collection->GetItem($Key);
         }
         return $self->{Itemrefs}{$PropertyName};
       }




More information about the wine-cvs mailing list