mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-24 04:26:38 +00:00
fix(controllers): cast idx to varchar in child-row picker for Postgres
get_filtered_child_rows searched child rows by row number with table.idx.like(...). idx is an integer column; frappe maps .like() to ILIKE on Postgres, which has no bigint ILIKE operator ('operator does not exist: bigint ~~* unknown'). Cast idx to string via frappe's Cast_ with 'varchar': a bare CAST(idx AS CHAR) is character(1) on Postgres and silently truncates a two-digit idx (11 -> '1'), dropping the row; CAST(idx AS VARCHAR) keeps the full value, and on MariaDB Cast_ rewrites to CONCAT(idx, '') matching the previous implicit coercion. MariaDB output unchanged. The test builds an order with >10 rows and searches row 11 (fails on Postgres with a char(1) cast).
This commit is contained in:
@@ -10,6 +10,7 @@ from frappe import qb, scrub
|
||||
from frappe.permissions import has_permission
|
||||
from frappe.query_builder import Case, Criterion, DocType
|
||||
from frappe.query_builder.functions import (
|
||||
Cast_,
|
||||
Concat,
|
||||
IfNull,
|
||||
Length,
|
||||
@@ -1135,7 +1136,8 @@ def get_filtered_child_rows(
|
||||
if txt:
|
||||
txt += "%"
|
||||
query = query.where(
|
||||
((table.idx.like(txt.replace("#", ""))) | (table.item_code.like(txt))) | (table.name.like(txt))
|
||||
((Cast_(table.idx, "varchar").like(txt.replace("#", ""))) | (table.item_code.like(txt)))
|
||||
| (table.name.like(txt))
|
||||
)
|
||||
|
||||
return query.run(as_dict=False)
|
||||
|
||||
@@ -93,6 +93,34 @@ class TestQueries(ERPNextTestSuite):
|
||||
query = add_default_params(queries.get_purchase_invoices, "Purchase Invoice")
|
||||
self.assertIsInstance(query(txt="", filters={}), list | tuple)
|
||||
|
||||
def test_get_filtered_child_rows_query(self):
|
||||
# idx is an integer column. Searching child rows by it must run on Postgres
|
||||
# (a bare LIKE rejects "bigint ILIKE text") AND cast to a full-length string:
|
||||
# CAST(idx AS CHAR) is character(1) on Postgres, so a two-digit idx like 11
|
||||
# would render as "1" and be missed. Build a Sales Order with >10 rows and
|
||||
# search for row 11 to lock both behaviours.
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
|
||||
frappe.db.set_single_value("Selling Settings", "allow_multiple_items", 1)
|
||||
so = make_sales_order(
|
||||
item_list=[
|
||||
{"item_code": "_Test Item", "qty": 1, "rate": 100, "warehouse": "_Test Warehouse - _TC"}
|
||||
for _ in range(11)
|
||||
],
|
||||
do_not_submit=True,
|
||||
)
|
||||
|
||||
rows = queries.get_filtered_child_rows(
|
||||
"Sales Order Item",
|
||||
txt="#11",
|
||||
searchfield="name",
|
||||
start=0,
|
||||
page_len=20,
|
||||
filters={"parent": so.name},
|
||||
)
|
||||
# row label is "#<idx>, <item_code>"; row 11 must be present
|
||||
self.assertTrue(any(str(label).startswith("#11,") for _name, label in rows))
|
||||
|
||||
def test_default_uoms(self):
|
||||
self.assertGreaterEqual(frappe.db.count("UOM", {"enabled": 1}), 10)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user