[FIX] Fix database compatibility issue in search query builder for payments filter (#3090)
Co-authored-by: dni ⚡ <office@dnilabs.com>
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
This commit is contained in:
parent
32cbf16d91
commit
51bf344d65
2 changed files with 79 additions and 6 deletions
10
lnbits/db.py
10
lnbits/db.py
|
|
@ -554,9 +554,13 @@ class Filters(BaseModel, Generic[TFilterModel]):
|
||||||
for page_filter in self.filters:
|
for page_filter in self.filters:
|
||||||
where_stmts.append(page_filter.statement)
|
where_stmts.append(page_filter.statement)
|
||||||
if self.search and self.model and self.model.__search_fields__:
|
if self.search and self.model and self.model.__search_fields__:
|
||||||
where_stmts.append(
|
# Use `COALESCE` to handle `NULL` values and `||`
|
||||||
f"lower(concat({', '.join(self.model.__search_fields__)})) LIKE :search"
|
# for cross-database compatible string concatenation
|
||||||
|
_fields = self.model.__search_fields__
|
||||||
|
search_expr = " || ".join(
|
||||||
|
f"COALESCE(CAST({field} AS TEXT), '')" for field in _fields
|
||||||
)
|
)
|
||||||
|
where_stmts.append(f"lower({search_expr}) LIKE :search")
|
||||||
|
|
||||||
if where_stmts:
|
if where_stmts:
|
||||||
return "WHERE " + " AND ".join(where_stmts)
|
return "WHERE " + " AND ".join(where_stmts)
|
||||||
|
|
@ -576,7 +580,7 @@ class Filters(BaseModel, Generic[TFilterModel]):
|
||||||
for key, value in page_filter.values.items():
|
for key, value in page_filter.values.items():
|
||||||
values[key] = value
|
values[key] = value
|
||||||
if self.search and self.model:
|
if self.search and self.model:
|
||||||
values["search"] = f"%{self.search}%"
|
values["search"] = f"%{self.search.lower()}%"
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from lnbits.core.crud import create_wallet, get_payments, update_payment
|
from lnbits.core.crud import (
|
||||||
from lnbits.core.models import PaymentState
|
create_wallet,
|
||||||
from lnbits.core.services import create_user_account, update_wallet_balance
|
get_payments,
|
||||||
|
get_payments_paginated,
|
||||||
|
update_payment,
|
||||||
|
)
|
||||||
|
from lnbits.core.models import PaymentFilters, PaymentState
|
||||||
|
from lnbits.core.services import (
|
||||||
|
create_invoice,
|
||||||
|
create_user_account,
|
||||||
|
update_wallet_balance,
|
||||||
|
)
|
||||||
|
from lnbits.db import Filters
|
||||||
|
|
||||||
|
|
||||||
async def update_payments(payments):
|
async def update_payments(payments):
|
||||||
|
|
@ -64,3 +74,62 @@ async def test_crud_get_payments(app):
|
||||||
# both false should return failed payments
|
# both false should return failed payments
|
||||||
# payments = await get_payments(wallet_id=wallet.id, complete=False, pending=False)
|
# payments = await get_payments(wallet_id=wallet.id, complete=False, pending=False)
|
||||||
# assert len(payments) == 2, "should return 2 failed payment"
|
# assert len(payments) == 2, "should return 2 failed payment"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
async def test_crud_search_payments():
|
||||||
|
|
||||||
|
user = await create_user_account()
|
||||||
|
wallet = await create_wallet(user_id=user.id)
|
||||||
|
filters: Filters = Filters(
|
||||||
|
search="",
|
||||||
|
model=PaymentFilters,
|
||||||
|
)
|
||||||
|
# no memo
|
||||||
|
await create_invoice(wallet_id=wallet.id, amount=30, memo="")
|
||||||
|
await create_invoice(wallet_id=wallet.id, amount=30, memo="Invoice A")
|
||||||
|
filters.search = "Invoice A"
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 1, "should return only Invoice A"
|
||||||
|
|
||||||
|
filters.search = "Invoice B"
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 0, "no Invoice B yet"
|
||||||
|
|
||||||
|
for i in range(15):
|
||||||
|
await create_invoice(wallet_id=wallet.id, amount=30 + i, memo="Invoice A")
|
||||||
|
await create_invoice(wallet_id=wallet.id, amount=30 + i, memo="Invoice B")
|
||||||
|
|
||||||
|
filters.search = None
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 32, "should return all payments"
|
||||||
|
|
||||||
|
filters.search = "Invoice A"
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 16
|
||||||
|
|
||||||
|
filters.search = "Invoice B"
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 15
|
||||||
|
|
||||||
|
filters.search = "Invoice"
|
||||||
|
page = await get_payments_paginated(
|
||||||
|
wallet_id=wallet.id,
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
assert page.total == 31
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue