diff --git a/frappe/database/query.py b/frappe/database/query.py index b873844ff6..f1a6d3141e 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -1,8 +1,9 @@ import operator import re -from ast import literal_eval -from functools import cached_property import sys +from ast import literal_eval +from fileinput import filename +from functools import cached_property from types import BuiltinFunctionType from typing import Any, Callable @@ -121,6 +122,7 @@ def func_timespan(key: Field, value: str) -> frappe.qb: return func_between(key, get_timespan_date_range(value)) + def change_orderby(order: str): """Convert orderby to standart Order object @@ -483,28 +485,26 @@ class Engine: def get_fieldnames_from_child_table(self, doctype, fields): # convert child_table.fieldname to `tabChild DocType`.`fieldname` - linked_doctype, fieldname = None, None for field in fields: if "." in field and "tab" not in field: original_field = field alias = None if " as " in field: field, alias = field.split(" as ") - linked_fieldname, fieldname = field.split(".") - linked_field = frappe.get_meta(doctype).get_field(linked_fieldname) - linked_doctype = linked_field.options - field = f"`tab{linked_doctype}`.`{fieldname}`" + self.fieldname, linked_fieldname = field.split(".") + linked_field = frappe.get_meta(doctype).get_field(self.fieldname) + self.linked_doctype = linked_field.options + field = f"`tab{self.linked_doctype}`.`{linked_fieldname}`" if alias: field = f"{field} as {alias}" fields[fields.index(original_field)] = field - return fields, linked_doctype, fieldname + return fields def set_fields(self, table, fields, **kwargs): fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" if isinstance(fields, list) and None in fields and Field not in fields: return None - linked_doctype, linked_field = None, None function_objects = [] is_list = isinstance(fields, (list, tuple, set)) if is_list and len(fields) == 1: @@ -543,7 +543,9 @@ class Engine: updated_fields = [] if "*" in fields: return fields - fields, linked_doctype, linked_field = self.get_fieldnames_from_child_table(doctype=table, fields=fields) + fields = self.get_fieldnames_from_child_table( + doctype=table, fields=fields + ) for field in fields: if not isinstance(field, Criterion) and field: if " as " in field: @@ -564,7 +566,7 @@ class Engine: fields = [fields] if fields else [] fields.extend(function_objects) - return fields, linked_doctype, linked_field + return fields def get_query( self, @@ -575,13 +577,21 @@ class Engine: ): # Clean up state before each query self.tables = {} - criterion = self.build_conditions(table, filters, **kwargs) - fields, linked_doctype, linked_field = self.set_fields(table, kwargs.get("field_objects") or fields, **kwargs) + self.linked_doctype = None + self.fieldname = None - if linked_doctype: - linked_doctype = frappe.qb.DocType(linked_doctype) - criterion = criterion.left_join(linked_doctype).on( - linked_doctype.name == frappe.qb.DocType(table).linked_field + criterion = self.build_conditions(table, filters, **kwargs) + fields = self.set_fields( + table, kwargs.get("field_objects") or fields, **kwargs + ) + if self.linked_doctype and self.fieldname: + for field in fields: + if "tab" not in str(field): + fields[fields.index(field)] = PseudoColumn(f"`tab{table}`.`{field.get_sql()}`") + + self.linked_doctype = frappe.qb.DocType(self.linked_doctype) + criterion = criterion.left_join(self.linked_doctype).on( + self.linked_doctype.name == getattr(frappe.qb.DocType(table), self.fieldname) ) join = kwargs.get("join").replace(" ", "_") if kwargs.get("join") else "left_join"