Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

245 righe
8.6 KiB

  1. import unittest
  2. from typing import Callable
  3. import frappe
  4. from frappe.query_builder.custom import ConstantColumn
  5. from frappe.query_builder.functions import Coalesce, GroupConcat, Match, CombineDatetime, Cast_
  6. from frappe.query_builder.utils import db_type_is
  7. from frappe.query_builder import Case
  8. def run_only_if(dbtype: db_type_is) -> Callable:
  9. return unittest.skipIf(
  10. db_type_is(frappe.conf.db_type) != dbtype, f"Only runs for {dbtype.value}"
  11. )
  12. @run_only_if(db_type_is.MARIADB)
  13. class TestCustomFunctionsMariaDB(unittest.TestCase):
  14. def test_concat(self):
  15. self.assertEqual("GROUP_CONCAT('Notes')", GroupConcat("Notes").get_sql())
  16. def test_match(self):
  17. query = Match("Notes").Against("text")
  18. self.assertEqual(
  19. " MATCH('Notes') AGAINST ('+text*' IN BOOLEAN MODE)", query.get_sql()
  20. )
  21. def test_constant_column(self):
  22. query = frappe.qb.from_("DocType").select(
  23. "name", ConstantColumn("John").as_("User")
  24. )
  25. self.assertEqual(
  26. query.get_sql(), "SELECT `name`,'John' `User` FROM `tabDocType`"
  27. )
  28. def test_timestamp(self):
  29. note = frappe.qb.DocType("Note")
  30. self.assertEqual("TIMESTAMP(posting_date,posting_time)", CombineDatetime(note.posting_date, note.posting_time).get_sql())
  31. self.assertEqual("TIMESTAMP('2021-01-01','00:00:21')", CombineDatetime("2021-01-01", "00:00:21").get_sql())
  32. todo = frappe.qb.DocType("ToDo")
  33. select_query = (frappe.qb
  34. .from_(note)
  35. .join(todo).on(todo.refernce_name == note.name)
  36. .select(CombineDatetime(note.posting_date, note.posting_time)))
  37. self.assertIn("select timestamp(`tabnote`.`posting_date`,`tabnote`.`posting_time`)", str(select_query).lower())
  38. select_query = select_query.orderby(CombineDatetime(note.posting_date, note.posting_time))
  39. self.assertIn("order by timestamp(`tabnote`.`posting_date`,`tabnote`.`posting_time`)", str(select_query).lower())
  40. select_query = select_query.where(CombineDatetime(note.posting_date, note.posting_time) >= CombineDatetime("2021-01-01", "00:00:01"))
  41. self.assertIn("timestamp(`tabnote`.`posting_date`,`tabnote`.`posting_time`)>=timestamp('2021-01-01','00:00:01')", str(select_query).lower())
  42. select_query = select_query.select(CombineDatetime(note.posting_date, note.posting_time, alias="timestamp"))
  43. self.assertIn("timestamp(`tabnote`.`posting_date`,`tabnote`.`posting_time`) `timestamp`", str(select_query).lower())
  44. def test_cast(self):
  45. note = frappe.qb.DocType("Note")
  46. self.assertEqual("CONCAT(`tabnote`.`name`, '')", Cast_(note.name, "varchar"))
  47. self.assertEqual("CAST(`tabnote`.`name` AS INTEGER)", Cast_(note.name, "integer"))
  48. @run_only_if(db_type_is.POSTGRES)
  49. class TestCustomFunctionsPostgres(unittest.TestCase):
  50. def test_concat(self):
  51. self.assertEqual("STRING_AGG('Notes',',')", GroupConcat("Notes").get_sql())
  52. def test_match(self):
  53. query = Match("Notes").Against("text")
  54. self.assertEqual(
  55. "TO_TSVECTOR('Notes') @@ PLAINTO_TSQUERY('text')", query.get_sql()
  56. )
  57. def test_constant_column(self):
  58. query = frappe.qb.from_("DocType").select(
  59. "name", ConstantColumn("John").as_("User")
  60. )
  61. self.assertEqual(
  62. query.get_sql(), 'SELECT "name",\'John\' "User" FROM "tabDocType"'
  63. )
  64. def test_timestamp(self):
  65. note = frappe.qb.DocType("Note")
  66. self.assertEqual("posting_date+posting_time", CombineDatetime(note.posting_date, note.posting_time).get_sql())
  67. self.assertEqual("CAST('2021-01-01' AS DATE)+CAST('00:00:21' AS TIME)", CombineDatetime("2021-01-01", "00:00:21").get_sql())
  68. todo = frappe.qb.DocType("ToDo")
  69. select_query = (frappe.qb
  70. .from_(note)
  71. .join(todo).on(todo.refernce_name == note.name)
  72. .select(CombineDatetime(note.posting_date, note.posting_time)))
  73. self.assertIn('select "tabnote"."posting_date"+"tabnote"."posting_time"', str(select_query).lower())
  74. select_query = select_query.orderby(CombineDatetime(note.posting_date, note.posting_time))
  75. self.assertIn('order by "tabnote"."posting_date"+"tabnote"."posting_time"', str(select_query).lower())
  76. select_query = select_query.where(
  77. CombineDatetime(note.posting_date, note.posting_time) >= CombineDatetime('2021-01-01', '00:00:01')
  78. )
  79. self.assertIn("""where "tabnote"."posting_date"+"tabnote"."posting_time">=cast('2021-01-01' as date)+cast('00:00:01' as time)""",
  80. str(select_query).lower())
  81. select_query = select_query.select(CombineDatetime(note.posting_date, note.posting_time, alias="timestamp"))
  82. self.assertIn('"tabnote"."posting_date"+"tabnote"."posting_time" "timestamp"', str(select_query).lower())
  83. def test_cast(self):
  84. note = frappe.qb.DocType("Note")
  85. self.assertEqual("CAST(`tabnote`.`name` AS VARCHAR)", Cast_(note.name, "varchar"))
  86. self.assertEqual("CAST(`tabnote`.`name` AS INTEGER)", Cast_(note.name, "integer"))
  87. class TestBuilderBase(object):
  88. def test_adding_tabs(self):
  89. self.assertEqual("tabNotes", frappe.qb.DocType("Notes").get_sql())
  90. self.assertEqual("__Auth", frappe.qb.DocType("__Auth").get_sql())
  91. self.assertEqual("Notes", frappe.qb.Table("Notes").get_sql())
  92. def test_run_patcher(self):
  93. query = frappe.qb.from_("ToDo").select("*").limit(1)
  94. data = query.run(as_dict=True)
  95. self.assertTrue("run" in dir(query))
  96. self.assertIsInstance(query.run, Callable)
  97. self.assertIsInstance(data, list)
  98. class TestParameterization(unittest.TestCase):
  99. def test_where_conditions(self):
  100. DocType = frappe.qb.DocType("DocType")
  101. query = (
  102. frappe.qb.from_(DocType)
  103. .select(DocType.name)
  104. .where((DocType.owner == "Administrator' --"))
  105. )
  106. self.assertTrue("walk" in dir(query))
  107. query, params = query.walk()
  108. self.assertIn("%(param1)s", query)
  109. self.assertIn("param1", params)
  110. self.assertEqual(params["param1"], "Administrator' --")
  111. def test_set_cnoditions(self):
  112. DocType = frappe.qb.DocType("DocType")
  113. query = frappe.qb.update(DocType).set(DocType.value, "some_value")
  114. self.assertTrue("walk" in dir(query))
  115. query, params = query.walk()
  116. self.assertIn("%(param1)s", query)
  117. self.assertIn("param1", params)
  118. self.assertEqual(params["param1"], "some_value")
  119. def test_where_conditions_functions(self):
  120. DocType = frappe.qb.DocType("DocType")
  121. query = (
  122. frappe.qb.from_(DocType)
  123. .select(DocType.name)
  124. .where(Coalesce(DocType.search_fields == "subject"))
  125. )
  126. self.assertTrue("walk" in dir(query))
  127. query, params = query.walk()
  128. self.assertIn("%(param1)s", query)
  129. self.assertIn("param1", params)
  130. self.assertEqual(params["param1"], "subject")
  131. def test_case(self):
  132. DocType = frappe.qb.DocType("DocType")
  133. query = (
  134. frappe.qb.from_(DocType)
  135. .select(
  136. Case()
  137. .when(DocType.search_fields == "value", "other_value")
  138. .when(Coalesce(DocType.search_fields == "subject_in_function"), "true_value")
  139. .else_("Overdue")
  140. )
  141. )
  142. self.assertTrue("walk" in dir(query))
  143. query, params = query.walk()
  144. self.assertIn("%(param1)s", query)
  145. self.assertIn("param1", params)
  146. self.assertEqual(params["param1"], "value")
  147. self.assertEqual(params["param2"], "other_value")
  148. self.assertEqual(params["param3"], "subject_in_function")
  149. self.assertEqual(params["param4"], "true_value")
  150. self.assertEqual(params["param5"], "Overdue")
  151. def test_case_in_update(self):
  152. DocType = frappe.qb.DocType("DocType")
  153. query = (
  154. frappe.qb.update(DocType)
  155. .set(
  156. "parent",
  157. Case()
  158. .when(DocType.search_fields == "value", "other_value")
  159. .when(Coalesce(DocType.search_fields == "subject_in_function"), "true_value")
  160. .else_("Overdue")
  161. )
  162. )
  163. self.assertTrue("walk" in dir(query))
  164. query, params = query.walk()
  165. self.assertIn("%(param1)s", query)
  166. self.assertIn("param1", params)
  167. self.assertEqual(params["param1"], "value")
  168. self.assertEqual(params["param2"], "other_value")
  169. self.assertEqual(params["param3"], "subject_in_function")
  170. self.assertEqual(params["param4"], "true_value")
  171. self.assertEqual(params["param5"], "Overdue")
  172. @run_only_if(db_type_is.MARIADB)
  173. class TestBuilderMaria(unittest.TestCase, TestBuilderBase):
  174. def test_adding_tabs_in_from(self):
  175. self.assertEqual(
  176. "SELECT * FROM `tabNotes`", frappe.qb.from_("Notes").select("*").get_sql()
  177. )
  178. self.assertEqual(
  179. "SELECT * FROM `__Auth`", frappe.qb.from_("__Auth").select("*").get_sql()
  180. )
  181. @run_only_if(db_type_is.POSTGRES)
  182. class TestBuilderPostgres(unittest.TestCase, TestBuilderBase):
  183. def test_adding_tabs_in_from(self):
  184. self.assertEqual(
  185. 'SELECT * FROM "tabNotes"', frappe.qb.from_("Notes").select("*").get_sql()
  186. )
  187. self.assertEqual(
  188. 'SELECT * FROM "__Auth"', frappe.qb.from_("__Auth").select("*").get_sql()
  189. )
  190. def test_replace_tables(self):
  191. info_schema = frappe.qb.Schema("information_schema")
  192. self.assertEqual(
  193. 'SELECT * FROM "pg_stat_all_tables"',
  194. frappe.qb.from_(info_schema.tables).select("*").get_sql(),
  195. )
  196. def test_replace_fields_post(self):
  197. self.assertEqual("relname", frappe.qb.Field("table_name").get_sql())