8099: 7263: Merge branch 'hgi/7263-even-better-busy-behavior' of github.com:wtsi...
[arvados.git] / services / api / lib / load_param.rb
index 35f1d0b640cbf9f8b7aa907b1336b5a61e1b5fa4..d7b9bb7513899d477906738d09a5a23bc8e6095f 100644 (file)
@@ -9,9 +9,6 @@ module LoadParam
   # Default number of rows to return in a single query.
   DEFAULT_LIMIT = 100
 
-  # Maximum number of rows to return in a single query, even if the client asks for more.
-  MAX_LIMIT = 1000
-
   # Load params[:where] into @where
   def load_where_param
     if params[:where].nil? or params[:where] == ""
@@ -54,7 +51,8 @@ module LoadParam
       unless params[:limit].to_s.match(/^\d+$/)
         raise ArgumentError.new("Invalid value for limit parameter")
       end
-      @limit = [params[:limit].to_i, MAX_LIMIT].min
+      @limit = [params[:limit].to_i,
+                Rails.configuration.max_items_per_response].min
     else
       @limit = DEFAULT_LIMIT
     end
@@ -113,7 +111,31 @@ module LoadParam
     # (e.g., [] or ['owner_uuid desc']), fall back on the default
     # orders to ensure repeating the same request (possibly with
     # different limit/offset) will return records in the same order.
-    @orders += model_class.default_orders
+    #
+    # Clean up the resulting list of orders such that no column
+    # uselessly appears twice (Postgres might not optimize this out
+    # for us) and no columns uselessly appear after a unique column
+    # (Postgres does not optimize this out for us; as of 9.2, "order
+    # by id, modified_at desc, uuid" is slow but "order by id" is
+    # fast).
+    orders_given_and_default = @orders + model_class.default_orders
+    order_cols_used = {}
+    @orders = []
+    orders_given_and_default.each do |order|
+      otablecol = order.split(' ')[0]
+
+      next if order_cols_used[otablecol]
+      order_cols_used[otablecol] = true
+
+      @orders << order
+
+      otable, ocol = otablecol.split('.')
+      if otable == table_name and model_class.unique_columns.include?(ocol)
+        # we already have a full ordering; subsequent entries would be
+        # superfluous
+        break
+      end
+    end
 
     case params[:select]
     when Array