Module | Sequel::EmulateOffsetWithReverseAndCount |
In: |
lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb
|
Make empty? work with an offset with an order. By default it would break since the order would be based on a column that empty does not select.
# File lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb, line 6 6: def empty? 7: if o = @opts[:offset] 8: unlimited.count <= o 9: else 10: super 11: end 12: end
Emulate OFFSET support using reverse order in a subselect, requiring a count of the number of rows.
If offset is used, an order must be provided, since it needs to be reversed in the subselect. Note that the order needs to be unambiguous to work correctly, and you must select all columns that you are ordering on.
# File lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb, line 20 20: def select_sql 21: return super if @opts[:sql] 22: return super unless o = @opts[:offset] 23: 24: order = @opts[:order] || default_offset_order 25: if order.nil? || order.empty? 26: raise(Error, "#{db.database_type} requires an order be provided if using an offset") 27: end 28: 29: ds = unlimited 30: row_count = @opts[:offset_total_count] || ds.clone(:append_sql=>'', :placeholder_literal_null=>true).count 31: dsa1 = dataset_alias(1) 32: 33: if o.is_a?(Symbol) && @opts[:bind_vars] && (match = Sequel::Dataset::PreparedStatementMethods::PLACEHOLDER_RE.match(o.to_s)) 34: # Handle use of bound variable offsets. Unfortunately, prepared statement 35: # bound variable offsets cannot be handled, since the bound variable value 36: # isn't available until later. 37: s = match[1].to_sym 38: if prepared_arg?(s) 39: o = prepared_arg(s) 40: end 41: end 42: 43: reverse_offset = row_count - o 44: ds = if reverse_offset > 0 45: ds.limit(reverse_offset). 46: reverse_order(*order). 47: from_self(:alias=>dsa1). 48: limit(@opts[:limit]). 49: order(*order) 50: else 51: # Sequel doesn't allow a nonpositive limit. If the offset 52: # is greater than the number of rows, the empty result set 53: # shuld be returned, so use a condition that is always false. 54: ds.where(1=>0) 55: end 56: sql = @opts[:append_sql] || '' 57: subselect_sql_append(sql, ds) 58: sql 59: end
This does not support offsets in correlated subqueries, as it requires a query to get a count that will be invalid if a correlated subquery is used.
# File lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb, line 63 63: def supports_offsets_in_correlated_subqueries? 64: false 65: end