Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions postgrest/base_request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,20 @@ def order(
.. versionchanged:: 0.10.3
Allow ordering results for foreign tables with the foreign_table parameter.
"""

new_order_parameter = (
f"{foreign_table + '(' if foreign_table else ''}{column}{')' if foreign_table else ''}"
f"{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}"
)

existing_order_parameter = self.params.get("order")
if existing_order_parameter:
self.params = self.params.remove("order")
new_order_parameter = f"{existing_order_parameter},{new_order_parameter}"

self.params = self.params.add(
f"{foreign_table}.order" if foreign_table else "order",
f"{column}{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}",
"order",
new_order_parameter,
)
return self

Expand Down
17 changes: 17 additions & 0 deletions tests/_async/test_filter_request_builder_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,20 @@ async def test_rpc_with_range():
{"nicename": "Albania", "iso": "AL"},
{"nicename": "Algeria", "iso": "DZ"},
]


async def test_order():
res = (
await rest_client()
.from_("countries")
.select("country_name, iso")
.limit(3)
.order("nicename", desc=True)
.execute()
)

assert res.data == [
{"country_name": "ZIMBABWE", "iso": "ZW"},
{"country_name": "UNITED STATES", "iso": "US"},
{"country_name": "UNITED KINGDOM", "iso": "GB"},
]
26 changes: 26 additions & 0 deletions tests/_async/test_request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,32 @@ def test_explain_options(self, request_builder: AsyncRequestBuilder):
assert "options=analyze|verbose|buffers|wal" in str(builder.headers.get("accept"))


class TestOrder:
def test_order(self, request_builder: AsyncRequestBuilder):
builder = request_builder.select().order("country_name", desc=True)
assert str(builder.params) == "order=country_name.desc"

def test_multiple_orders(self, request_builder: AsyncRequestBuilder):
builder = (
request_builder.select()
.order("country_name", desc=True)
.order("iso", desc=True)
)
assert str(builder.params) == "order=country_name.desc%2Ciso.desc"

def test_multiple_orders_on_foreign_table(self, request_builder: AsyncRequestBuilder):
foreign_table = "cities"
builder = (
request_builder.select()
.order("city_name", desc=True, foreign_table=foreign_table)
.order("id", desc=True, foreign_table=foreign_table)
)
assert (
str(builder.params)
== "order=cities%28city_name%29.desc%2Ccities%28id%29.desc"
)


class TestRange:
def test_range_on_own_table(self, request_builder: AsyncRequestBuilder):
builder = request_builder.select("*").range(0, 1)
Expand Down
17 changes: 17 additions & 0 deletions tests/_sync/test_filter_request_builder_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,3 +474,20 @@ def test_rpc_with_range():
{"nicename": "Albania", "iso": "AL"},
{"nicename": "Algeria", "iso": "DZ"},
]


def test_order():
res = (
rest_client()
.from_("countries")
.select("country_name, iso")
.limit(3)
.order("nicename", desc=True)
.execute()
)

assert res.data == [
{"country_name": "ZIMBABWE", "iso": "ZW"},
{"country_name": "UNITED STATES", "iso": "US"},
{"country_name": "UNITED KINGDOM", "iso": "GB"},
]
48 changes: 37 additions & 11 deletions tests/_sync/test_request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ def test_insert_with_upsert(self, request_builder: SyncRequestBuilder):
assert builder.http_method == "POST"
assert builder.json == {"key1": "val1"}

def test_upsert_with_default_single(self, request_builder: SyncRequestBuilder):
builder = request_builder.upsert([{"key1": "val1"}], default_to_null=False)
assert builder.headers.get_list("prefer", True) == [
"return=representation",
"resolution=merge-duplicates",
"missing=default",
]
assert builder.http_method == "POST"
assert builder.json == [{"key1": "val1"}]
assert builder.params.get("columns") == '"key1"'

def test_bulk_insert_using_default(self, request_builder: SyncRequestBuilder):
builder = request_builder.insert(
[{"key1": "val1", "key2": "val2"}, {"key3": "val3"}], default_to_null=False
Expand All @@ -95,17 +106,6 @@ def test_upsert(self, request_builder: SyncRequestBuilder):
assert builder.http_method == "POST"
assert builder.json == {"key1": "val1"}

def test_upsert_with_default_single(self, request_builder: SyncRequestBuilder):
builder = request_builder.upsert([{"key1": "val1"}], default_to_null=False)
assert builder.headers.get_list("prefer", True) == [
"return=representation",
"resolution=merge-duplicates",
"missing=default",
]
assert builder.http_method == "POST"
assert builder.json == [{"key1": "val1"}]
assert builder.params.get("columns") == '"key1"'

def test_bulk_upsert_with_default(self, request_builder: SyncRequestBuilder):
builder = request_builder.upsert(
[{"key1": "val1", "key2": "val2"}, {"key3": "val3"}], default_to_null=False
Expand Down Expand Up @@ -190,6 +190,32 @@ def test_explain_options(self, request_builder: SyncRequestBuilder):
assert "options=analyze|verbose|buffers|wal" in str(builder.headers.get("accept"))


class TestOrder:
def test_order(self, request_builder: SyncRequestBuilder):
builder = request_builder.select().order("country_name", desc=True)
assert str(builder.params) == "order=country_name.desc"

def test_multiple_orders(self, request_builder: SyncRequestBuilder):
builder = (
request_builder.select()
.order("country_name", desc=True)
.order("iso", desc=True)
)
assert str(builder.params) == "order=country_name.desc%2Ciso.desc"

def test_multiple_orders_on_foreign_table(self, request_builder: SyncRequestBuilder):
foreign_table = "cities"
builder = (
request_builder.select()
.order("city_name", desc=True, foreign_table=foreign_table)
.order("id", desc=True, foreign_table=foreign_table)
)
assert (
str(builder.params)
== "order=cities%28city_name%29.desc%2Ccities%28id%29.desc"
)


class TestRange:
def test_range_on_own_table(self, request_builder: SyncRequestBuilder):
builder = request_builder.select("*").range(0, 1)
Expand Down