]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 474715: Add 'limit', 'offset' and 'changed_since' arguments to WebService::Bug...
authormkanat%bugzilla.org <>
Fri, 23 Jan 2009 03:19:32 +0000 (03:19 +0000)
committermkanat%bugzilla.org <>
Fri, 23 Jan 2009 03:19:32 +0000 (03:19 +0000)
Patch By Kip Hampton <khampton@totalcinema.com> r=mkanat, a=mkanat

Bugzilla/Object.pm
Bugzilla/WebService/Bug.pm

index 53720327b59be3e20abf69763456c48d470ddefd..75e04f2e796c3d7930726b046f7658ad6da9642e 100644 (file)
@@ -156,9 +156,29 @@ sub match {
 
     return [$class->get_all] if !$criteria;
 
-    my (@terms, @values);
+    my (@terms, @values, $postamble);
     foreach my $field (keys %$criteria) {
         my $value = $criteria->{$field};
+        
+        # allow for LIMIT and OFFSET expressions via the criteria.
+        next if $field eq 'OFFSET';
+        if ( $field eq 'LIMIT' ) {
+            next unless defined $value;
+            $postamble = $dbh->sql_limit( $value, $criteria->{OFFSET} );
+            next;
+        }
+        elsif ( $field eq 'WHERE' ) {
+            next unless $value;
+            # the WHERE value is a hashref where the keys are
+            # "column_name operator ?" and values are the placeholder's
+            # value.
+            foreach my $k (keys( %$value )) {
+                push( @terms, $k );
+                push( @values, $value->{$k} );
+            }            
+            next;
+        }
+                
         if (ref $value eq 'ARRAY') {
             # IN () is invalid SQL, and if we have an empty list
             # to match against, we're just returning an empty
@@ -181,12 +201,12 @@ sub match {
         }
     }
 
-    my $where = join(' AND ', @terms);
-    return $class->_do_list_select($where, \@values);
+    my $where = join(' AND ', @terms) if scalar @terms;
+    return $class->_do_list_select($where, \@values, $postamble);
 }
 
 sub _do_list_select {
-    my ($class, $where, $values) = @_;
+    my ($class, $where, $values, $postamble) = @_;
     my $table = $class->DB_TABLE;
     my $cols  = join(',', $class->DB_COLUMNS);
     my $order = $class->LIST_ORDER;
@@ -196,7 +216,9 @@ sub _do_list_select {
         $sql .= " WHERE $where ";
     }
     $sql .= " ORDER BY $order";
-
+    
+    $sql .= " $postamble" if $postamble;
+        
     my $dbh = Bugzilla->dbh;
     my $objects = $dbh->selectall_arrayref($sql, {Slice=>{}}, @$values);
     bless ($_, $class) foreach @$objects;
@@ -625,6 +647,26 @@ There are two special values, the constants C<NULL> and C<NOT_NULL>,
 which means "give me objects where this field is NULL or NOT NULL,
 respectively."
 
+In addition to the column keys, there are a few special keys that
+can be used to rig the underlying database queries. These are 
+C<LIMIT>, C<OFFSET>, and C<WHERE>.
+
+The value for the C<LIMIT> key is expected to be an integer defining 
+the number of objects to return, while the value for C<OFFSET> defines
+the position, relative to the number of objects the query would normally 
+return, at which to begin the result set. If C<OFFSET> is defined without 
+a corresponding C<LIMIT> it is silently ignored.
+
+The C<WHERE> key provides a mechanism for adding arbitrary WHERE
+clauses to the underlying query. Its value is expected to a hash 
+reference whose keys are the columns, operators and placeholders, and the 
+values are the placeholders' bind value. For example:
+
+ WHERE => {'some_column >= ?' => $some_value }
+    
+would constrain the query to only those objects in the table whose
+'some_column' column has a value greater than or equal to $some_value.
+
 If you don't specify any criteria, calling this function is the same
 as doing C<[$class-E<gt>get_all]>.
 
index 04b18fe7c6ed5a98159906195540c7177ea48c6b..31f87ba99abf1bad9f9a0e46816053bea85d7226 100755 (executable)
@@ -50,6 +50,8 @@ use constant FIELD_MAP => {
     summary          => 'short_desc',
     url              => 'bug_file_loc',
     whiteboard       => 'status_whiteboard',
+    limit            => 'LIMIT',
+    offset           => 'OFFSET',
 };
 
 use constant PRODUCT_SPECIFIC_FIELDS => qw(version target_milestone component);
@@ -218,7 +220,21 @@ sub get_history {
 
 sub search {
     my ($self, $params) = @_;
+    
+    if ( $params->{offset} and !$params->{limit} ) {
+        ThrowCodeError( 'param_required', { param => 'limit', function => 'Bug.search()'});
+    }
+    
     $params = _map_fields($params);
+    
+    # If the user set the 'last_change_time' param (translated into delta_ts
+    # by the field map), use a custom WHERE to constrain the query to only 
+    # those bugs that have a delta_ts greater than or equal to 
+    # the specified time.
+    if ( my $bug_when = delete $params->{delta_ts} ) {
+        $params->{WHERE} = {'delta_ts >= ?' => $bug_when};
+    }
+    
     my $bugs = Bugzilla::Bug->match($params);
     my $visible = Bugzilla->user->visible_bugs($bugs);
     my @hashes = map { $self->_bug_to_hash($_) } @$visible;
@@ -960,7 +976,21 @@ C<int> The numeric id of the bug.
 
 =item C<last_change_time>
 
-C<dateTime> The last time the bug was updated.
+C<dateTime> Limit the search to only those bugs which have changed 
+in some way since the specified time. It includes all bugs changed 
+between the specified time and the present. Note: only a single 
+C<dateTime> will accepted, not an array.
+
+=item C<limit>
+
+C<int> Limit the number of results returned to C<int> records.
+
+=item C<offset>
+
+C<int> Used in conjunction with the C<limit> argument, C<offset> defines 
+the starting position for the search. For example, given a search that 
+would return 100 bugs, setting C<limit> to 10 and C<offset> to 10 would return 
+bugs 11 through 20 from the set of 100.
 
 =item C<op_sys>