diff --git a/frappe/database/query.py b/frappe/database/query.py index c8e1ddabc6..6295c4ec3e 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -462,7 +462,8 @@ class Query: fields = updated_fields - if not is_list: + # Need to check instance again since fields modified. + if not isinstance(fields, (list, tuple, set)): fields = [fields] if fields else [] fields.extend(function_objects) diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 077b39101e..915d2819ee 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -25,7 +25,7 @@ def run_webhooks(doc, method): # query webhooks webhooks_list = frappe.get_all( "Webhook", - fields=["name", "condition", "webhook_docevent", "webhook_doctype"], + fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], filters={"enabled": True}, ) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index b9c757bfa6..fe52818235 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -89,9 +89,6 @@ class DatabaseQuery(object): ignore_ddl=False, parent_doctype=None, ) -> List: - from frappe.database.query import Query - - self.query = Query() if ( not ignore_permissions @@ -115,8 +112,6 @@ class DatabaseQuery(object): # if `filters` is a list of strings, its probably fields filters, fields = fields, filters - self.temp_filters, self.temp_fields = filters, fields - if fields: self.fields = fields else: @@ -202,6 +197,7 @@ class DatabaseQuery(object): %(limit)s""" % args ) + return frappe.db.sql( query, as_dict=not self.as_list, diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index 7b260098d1..b55eff4298 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -95,6 +95,8 @@ class SqlFunctions(Enum): Count = "count" Sum = "sum" Avg = "avg" + Max = "max" + Min = "min" def _max(dt, fieldname, filters=None, **kwargs): diff --git a/frappe/share.py b/frappe/share.py index 2933017048..3edcb1be38 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -104,12 +104,12 @@ def get_users(doctype, name): return frappe.db.get_all( "DocShare", fields=[ - "name", - "user", - "read", - "write", - "submit", - "share", + "`name`", + "`user`", + "`read`", + "`write`", + "`submit`", + "`share`", "everyone", "owner", "creation", diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index 949c3e9433..d7190fe7ae 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -1,11 +1,12 @@ import unittest import frappe +from frappe.query_builder import Field from frappe.tests.test_query_builder import db_type_is, run_only_if -@run_only_if(db_type_is.MARIADB) class TestQuery(unittest.TestCase): + @run_only_if(db_type_is.MARIADB) def test_multiple_tables_in_filters(self): self.assertEqual( frappe.db.query.get_sql( @@ -18,3 +19,55 @@ class TestQuery(unittest.TestCase): ).get_sql(), "SELECT * FROM `tabDocType` LEFT JOIN `tabBOM Update Log` ON `tabBOM Update Log`.`parent`=`tabDocType`.`name` WHERE `tabBOM Update Log`.`name` LIKE 'f%' AND `tabDocType`.`parent`='something'", ) + + def test_string_fields(self): + self.assertEqual( + frappe.db.query.get_sql("User", fields="name, email", filters={"name": "Administrator"}), + frappe.qb.from_("User") + .select(Field("name"), Field("email")) + .where(Field("name") == "Administrator"), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=["name, email"], filters={"name": "Administrator"}), + frappe.qb.from_("User") + .select(Field("name"), Field("email")) + .where(Field("name") == "Administrator"), + ) + + def test_functions_fields(self): + from frappe.query_builder.functions import Count + + self.assertEqual( + frappe.db.query.get_sql("User", fields="Count(name)", filters={}), + frappe.qb.from_("User").select(Count(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields="Count(name), Max(name)", filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=["Count(name)", "Max(name)"], filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=[Count("*")], filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + def test_qb_fields(self): + user_doctype = frappe.qb.DocType("User") + self.assertEqual( + frappe.db.query.get_sql( + user_doctype, fields=[user_doctype.name, user_doctype.email], filters={} + ), + frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email), + ) + + self.assertEqual( + frappe.db.query.get_sql(user_doctype, fields=user_doctype.email, filters={}), + frappe.qb.from_(user_doctype).select(user_doctype.email), + ) diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 545ad6ec77..038a3021d2 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -290,7 +290,7 @@ def update_completed_workflow_actions_using_user(doc, user=None): def get_next_possible_transitions(workflow_name, state, doc=None): transitions = frappe.get_all( "Workflow Transition", - fields=["allowed", "action", "state", "allow_self_approval", "next_state", "condition"], + fields=["allowed", "action", "state", "allow_self_approval", "next_state", "`condition`"], filters=[["parent", "=", workflow_name], ["state", "=", state]], )