Revert "fix(postgres): three parity fixes — POS NULL ordering, traceability div-by-zero, LIKE on non-text"

This commit is contained in:
Mihir Kandoi
2026-06-23 22:01:17 +05:30
committed by GitHub
parent 934b1ff7dd
commit 332f5efbd1
3 changed files with 7 additions and 23 deletions

View File

@@ -12,9 +12,8 @@ from typing import Any, Union
import frappe import frappe
from frappe import _ from frappe import _
from frappe.database.operator_map import OPERATOR_MAP from frappe.database.operator_map import OPERATOR_MAP
from frappe.model import numeric_fieldtypes
from frappe.query_builder import Case from frappe.query_builder import Case
from frappe.query_builder.functions import Cast_, Sum from frappe.query_builder.functions import Sum
from frappe.utils import cstr, date_diff, flt, getdate from frappe.utils import cstr, date_diff, flt, getdate
from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder
from pypika.terms import Bracket, LiteralValue from pypika.terms import Bracket, LiteralValue
@@ -865,15 +864,8 @@ class FilterExpressionParser:
field = getattr(table, field_name, None) field = getattr(table, field_name, None)
operator_fn = OPERATOR_MAP.get(operator.casefold()) operator_fn = OPERATOR_MAP.get(operator.casefold())
if "like" in operator.casefold(): if "like" in operator.casefold() and "%" not in value:
if "%" not in value: value = f"%{value}%"
value = f"%{value}%"
# Postgres has no LIKE/ILIKE operator for non-text columns; MariaDB implicitly casts
# the numeric column to text. Cast a numeric/Check Account field to varchar so the
# match runs on both engines and reproduces MariaDB's result.
meta_field = frappe.get_meta("Account").get_field(field_name)
if meta_field and meta_field.fieldtype in numeric_fieldtypes:
field = Cast_(field, "varchar")
return operator_fn(field, value) return operator_fn(field, value)

View File

@@ -6,7 +6,6 @@ import json
import frappe import frappe
from frappe.query_builder import Criterion, DocType, Order from frappe.query_builder import Criterion, DocType, Order
from frappe.query_builder.functions import Coalesce
from frappe.utils import cint, get_datetime from frappe.utils import cint, get_datetime
from frappe.utils.nestedset import get_root_of from frappe.utils.nestedset import get_root_of
@@ -232,10 +231,7 @@ def get_items(
.where(ItemPrice.selling == 1) .where(ItemPrice.selling == 1)
.where((ItemPrice.valid_from <= current_date) | (ItemPrice.valid_from.isnull())) .where((ItemPrice.valid_from <= current_date) | (ItemPrice.valid_from.isnull()))
.where((ItemPrice.valid_upto >= current_date) | (ItemPrice.valid_upto.isnull())) .where((ItemPrice.valid_upto >= current_date) | (ItemPrice.valid_upto.isnull()))
# Coalesce so a NULL valid_from (open-ended base price) sorts last under DESC on both .orderby(ItemPrice.valid_from, order=Order.desc)
# engines: MariaDB already sorts NULL last for DESC, Postgres defaults to NULLS FIRST, which
# would otherwise make the base price win the positional pick over a dated override.
.orderby(Coalesce(ItemPrice.valid_from, "1900-01-01"), order=Order.desc)
).run(as_dict=True) ).run(as_dict=True)
stock_uom_price = next((d for d in item_prices if d.get("uom") == item.stock_uom), {}) stock_uom_price = next((d for d in item_prices if d.get("uom") == item.stock_uom), {})

View File

@@ -4,7 +4,6 @@
import frappe import frappe
from frappe import _ from frappe import _
from frappe.query_builder import Case from frappe.query_builder import Case
from frappe.query_builder.functions import NullIf
def execute(filters: dict | None = None): def execute(filters: dict | None = None):
@@ -301,12 +300,9 @@ class ReportData:
( (
( (
stock_entry_detail.qty stock_entry_detail.qty
/ NullIf( / Case()
Case() .when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty)
.when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty) .else_(sabb_data.qty)
.else_(sabb_data.qty),
0,
)
) )
* sabb_data.qty * sabb_data.qty
).as_("qty"), ).as_("qty"),