3235: Fix SQL query.
[arvados.git] / services / api / app / controllers / arvados / v1 / groups_controller.rb
1 class Arvados::V1::GroupsController < ApplicationController
2
3   def self._contents_requires_parameters
4     _index_requires_parameters.
5       merge({
6               include_linked: {
7                 type: 'boolean', required: false, default: false
8               },
9             })
10   end
11
12   def render_404_if_no_object
13     if params[:action] == 'contents' and !params[:uuid]
14       # OK!
15       @object = nil
16     else
17       super
18     end
19   end
20
21   def contents
22     # Set @objects:
23     load_searchable_objects(owner_uuid: @object.andand.uuid, include_linked: params[:include_linked])
24
25     @links = Link.where('link_class=? and tail_uuid=?'\
26                         ' and head_uuid in (?)',
27                         'name',
28                         @object.uuid,
29                         @objects.collect(&:uuid))
30     @object_list = {
31       :kind  => "arvados#objectList",
32       :etag => "",
33       :self_link => "",
34       :links => @links.as_api_response(nil),
35       :offset => @offset,
36       :limit => @limit,
37       :items_available => @items_available,
38       :items => @objects.as_api_response(nil)
39     }
40     render json: @object_list
41   end
42
43   protected
44
45   def load_searchable_objects opts
46     all_objects = []
47     @items_available = 0
48
49     # Trick apply_where_limit_order_params into applying suitable
50     # per-table values. *_all are the real ones we'll apply to the
51     # aggregate set.
52     limit_all = @limit
53     offset_all = @offset
54     @orders = []
55
56     [Group,
57      Job, PipelineInstance, PipelineTemplate,
58      Collection,
59      Human, Specimen, Trait].each do |klass|
60       @objects = klass.readable_by(*@read_users)
61       conds = []
62       cond_params = []
63       if opts[:owner_uuid]
64         conds << "#{klass.table_name}.owner_uuid = ?"
65         cond_params << opts[:owner_uuid]
66       end
67       if opts[:include_linked]
68         conds << "#{klass.table_name}.uuid IN (SELECT head_uuid FROM links WHERE link_class=#{klass.sanitize 'name'} AND links.tail_uuid=#{klass.sanitize @object.uuid})"
69       end
70       if conds.any?
71         cond_sql = '(' + conds.join(') OR (') + ')'
72         @objects = @objects.where(cond_sql, *cond_params)
73       end
74       @objects = @objects.order("#{klass.table_name}.uuid")
75       @limit = limit_all - all_objects.count
76       apply_where_limit_order_params
77       klass_items_available = @objects.
78         except(:limit).except(:offset).
79         count(:id, distinct: true)
80       @items_available += klass_items_available
81       @offset = [@offset - klass_items_available, 0].max
82
83       all_objects += @objects.to_a
84     end
85
86     @objects = all_objects
87     @limit = limit_all
88     @offset = offset_all
89   end
90
91 end