Skip to content

Commit 96f5e93

Browse files
committed
Support sort and reverse methods in pg_array_ops extension on PostgreSQL 18+
1 parent d7c42cb commit 96f5e93

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
=== master
22

3+
* Support sort and reverse methods in pg_array_ops extension on PostgreSQL 18+ (jeremyevans)
4+
35
* Support :in_arrays option for Postgres::JSON{,B}#strip_nulls in pg_json_ops extension on PostgreSQL 18+ (jeremyevans)
46

57
* Support VIRTUAL generated columns on PostgreSQL 18+ using :virtual option (jeremyevans)

lib/sequel/extensions/pg_array_ops.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656
# ia.join(':', ' ') # array_to_string(int_array_column, ':', ' ')
5757
# ia.unnest # unnest(int_array_column)
5858
# ia.unnest(:b) # unnest(int_array_column, b)
59+
#
60+
# On PostgreSQL 18+, the following are supported:
61+
#
62+
# ia.sort # array_sort(int_array_column)
63+
# ia.sort(desc: true) # array_sort(int_array_column, true)
64+
# ia.sort(nulls: :first) # array_sort(int_array_column, false, true)
65+
# ia.reverse # array_reverse(int_array_column)
5966
#
6067
# See the PostgreSQL array function and operator documentation for more
6168
# details on what these functions and operators do.
@@ -217,6 +224,40 @@ def replace(element, replacement)
217224
ArrayOp.new(function(:array_replace, element, replacement))
218225
end
219226

227+
# Call the array_reverse method:
228+
#
229+
# array_op.reverse # array_reverse(array)
230+
def reverse
231+
function(:array_reverse)
232+
end
233+
234+
# Call the array_sort method. Options:
235+
#
236+
# :desc :: Sort in descending order instead of ascending order.
237+
# :nulls :: If sorting in ascending order and value is :first, include NULL
238+
# values before non-NULL values. If sorting in descending order and
239+
# value is :last, include non-NULL values before NULL values.
240+
#
241+
# array_op.sort # array_sort(array)
242+
# array_op.sort(desc: true) # array_sort(array, true)
243+
# array_op.sort(nulls: :first) # array_sort(array, false, true)
244+
# array_op.sort(desc: true, nulls: :last) # array_sort(array, true, false)
245+
def sort(opts=OPTS)
246+
desc = opts[:desc]
247+
nulls = opts[:nulls]
248+
if desc
249+
if nulls == :last
250+
function(:array_sort, true, false)
251+
else
252+
function(:array_sort, true)
253+
end
254+
elsif nulls == :first
255+
function(:array_sort, false, true)
256+
else
257+
function(:array_sort)
258+
end
259+
end
260+
220261
# Call the array_to_string method:
221262
#
222263
# array_op.join # array_to_string(array, '')

spec/adapters/postgres_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,6 +3789,18 @@ def ==(other)
37893789

37903790
@ds.from{Sequel.pg_array([1,2,3]).op.unnest([4,5,6], [7,8]).as(:t1, [:a, :b, :c])}.select_order_map([:a, :b, :c]).must_equal [[1, 4, 7], [2, 5, 8], [3, 6, nil]]
37913791
end
3792+
if @db.server_version >= 180000
3793+
@ds.get(Sequel.pg_array(:i5).sort).must_equal [1, 5, nil]
3794+
@ds.get(Sequel.pg_array(:i5).sort(:desc => false)).must_equal [1, 5, nil]
3795+
@ds.get(Sequel.pg_array(:i5).sort(:desc => true)).must_equal [nil, 5, 1]
3796+
@ds.get(Sequel.pg_array(:i5).sort(:nulls => :first)).must_equal [nil, 1, 5]
3797+
@ds.get(Sequel.pg_array(:i5).sort(:nulls => :last)).must_equal [1, 5, nil]
3798+
@ds.get(Sequel.pg_array(:i5).sort(:desc => false, :nulls => :first)).must_equal [nil, 1, 5]
3799+
@ds.get(Sequel.pg_array(:i5).sort(:desc => false, :nulls => :last)).must_equal [1, 5, nil]
3800+
@ds.get(Sequel.pg_array(:i5).sort(:desc => true, :nulls => :first)).must_equal [nil, 5, 1]
3801+
@ds.get(Sequel.pg_array(:i5).sort(:desc => true, :nulls => :last)).must_equal [5, 1, nil]
3802+
@ds.get(Sequel.pg_array(:i5).reverse).must_equal [5, nil, 1]
3803+
end
37923804

37933805
@ds.get(Sequel.pg_array(:i).push(4)).must_equal [1, 2, 3, 4]
37943806
@ds.get(Sequel.pg_array(:i).unshift(4)).must_equal [4, 1, 2, 3]

spec/extensions/pg_array_ops_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,30 @@
6060
@db.literal(@a.replace(1, 2)[3]).must_equal "(array_replace(a, 1, 2))[3]"
6161
end
6262

63+
it "#reverse should call the array_reverse function" do
64+
@db.literal(@a.reverse).must_equal "array_reverse(a)"
65+
end
66+
67+
it "#sort should call the array_sort function" do
68+
@db.literal(@a.sort).must_equal "array_sort(a)"
69+
end
70+
71+
it "#sort should respect the :desc option" do
72+
@db.literal(@a.sort(desc: true)).must_equal "array_sort(a, true)"
73+
end
74+
75+
it "#sort should respect the nulls: :first option" do
76+
@db.literal(@a.sort(nulls: :first)).must_equal "array_sort(a, false, true)"
77+
end
78+
79+
it "#sort should respect the desc: true, nulls: :last options" do
80+
@db.literal(@a.sort(desc: true, nulls: :last)).must_equal "array_sort(a, true, false)"
81+
end
82+
83+
it "#sort should call the array_sort function" do
84+
@db.literal(@a.sort).must_equal "array_sort(a)"
85+
end
86+
6387
it "#unshift should use the || operator in prepend mode" do
6488
@db.literal(@a.unshift(:b)).must_equal "(b || a)"
6589
end

0 commit comments

Comments
 (0)