fix: pypika does not parse datetime.time (backport #18184) (#18205)

* fix: pypika does not parse datetime.time

(cherry picked from commit b8f5a4304cccda954822cfe69d4805a18d9f07a7)

* fix: style - imports sort order fixed

(cherry picked from commit c3562c643ab9bff38d230202675d8ce1ae190912)

* test: add test for query builder parsing datetime.time

(cherry picked from commit 99889c270199da4b26b0d3858ae0f0a416d49d90)

* fix: format_time instead of format_datetime, test was failing!

(cherry picked from commit 5d697a22ac8cb98c8f8f44b3f99c57b932c5223c)

* fix(style): linter issues

(cherry picked from commit e231e1b0eadf63e84c9f81cfed9e2926e086fc44)

* test: add test for postgres

(cherry picked from commit 695591c43af9672cb83ce856a46c97e0bddfa9c3)

* fix: converting datepart and timepart to strings for Combinedatetime

(cherry picked from commit 1ebda943a607688bfb3db9fb42c80723a9050973)

* fix: style, linter issues

(cherry picked from commit c01262ad02b8831fdb0c5332b6973499e8adf6ad)

Co-authored-by: Anoop Kurungadam <anoop@earthianslive.com>
Co-authored-by: Aradhya <aradhyatripathi51@gmail.com>
This commit is contained in:
mergify[bot] 2022-09-23 15:46:31 +05:30 committed by GitHub
parent 4263aace27
commit 002b27dbdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 3 deletions

View file

@ -1,3 +1,4 @@
from datetime import time
from enum import Enum
from pypika.functions import *
@ -47,6 +48,9 @@ Match = ImportMapper({db_type_is.MARIADB: MATCH, db_type_is.POSTGRES: TO_TSVECTO
class _PostgresTimestamp(ArithmeticExpression):
def __init__(self, datepart, timepart, alias=None):
"""Postgres would need both datepart and timepart to be a string for concatenation"""
if isinstance(timepart, time) or isinstance(datepart, time):
timepart, datepart = str(timepart), str(datepart)
if isinstance(datepart, str):
datepart = Cast(datepart, "date")
if isinstance(timepart, str):

View file

@ -1,11 +1,11 @@
from datetime import timedelta
from datetime import time, timedelta
from typing import Any
from pypika.queries import QueryBuilder
from pypika.terms import Criterion, Function, ValueWrapper
from pypika.utils import format_alias_sql
from frappe.utils.data import format_timedelta
from frappe.utils.data import format_time, format_timedelta
class NamedParameterWrapper:
@ -55,9 +55,12 @@ class ParameterizedValueWrapper(ValueWrapper):
value_sql = self.get_value_sql(quote_char=quote_char, **kwargs)
sql = param_wrapper.get_sql(param_value=value_sql, **kwargs)
else:
# * BUG: pypika doesen't parse timedeltas
# * BUG: pypika doesen't parse timedeltas and datetime.time
if isinstance(self.value, timedelta):
self.value = format_timedelta(self.value)
elif isinstance(self.value, time):
self.value = format_time(self.value)
sql = self.get_value_sql(
quote_char=quote_char,
secondary_quote_char=secondary_quote_char,

View file

@ -1,5 +1,6 @@
import unittest
from collections.abc import Callable
from datetime import time
import frappe
from frappe.query_builder import Case
@ -74,6 +75,26 @@ class TestCustomFunctionsMariaDB(FrappeTestCase):
str(select_query).lower(),
)
def test_time(self):
note = frappe.qb.DocType("Note")
self.assertEqual(
"TIMESTAMP('2021-01-01','00:00:21')", CombineDatetime("2021-01-01", time(0, 0, 21)).get_sql()
)
select_query = frappe.qb.from_(note).select(
CombineDatetime(note.posting_date, note.posting_time)
)
self.assertIn("select timestamp(`posting_date`,`posting_time`)", str(select_query).lower())
select_query = select_query.where(
CombineDatetime(note.posting_date, note.posting_time)
>= CombineDatetime("2021-01-01", time(0, 0, 1))
)
self.assertIn(
"timestamp(`posting_date`,`posting_time`)>=timestamp('2021-01-01','00:00:01')",
str(select_query).lower(),
)
def test_cast(self):
note = frappe.qb.DocType("Note")
self.assertEqual("CONCAT(name,'')", Cast_(note.name, "varchar").get_sql())
@ -141,6 +162,28 @@ class TestCustomFunctionsPostgres(FrappeTestCase):
'"tabnote"."posting_date"+"tabnote"."posting_time" "timestamp"', str(select_query).lower()
)
def test_time(self):
note = frappe.qb.DocType("Note")
self.assertEqual(
"CAST('2021-01-01' AS DATE)+CAST('00:00:21' AS TIME)",
CombineDatetime("2021-01-01", time(0, 0, 21)).get_sql(),
)
select_query = frappe.qb.from_(note).select(
CombineDatetime(note.posting_date, note.posting_time)
)
self.assertIn('select "posting_date"+"posting_time"', str(select_query).lower())
select_query = select_query.where(
CombineDatetime(note.posting_date, note.posting_time)
>= CombineDatetime("2021-01-01", time(0, 0, 1))
)
self.assertIn(
"""where "posting_date"+"posting_time">=cast('2021-01-01' as date)+cast('00:00:01' as time)""",
str(select_query).lower(),
)
def test_cast(self):
note = frappe.qb.DocType("Note")
self.assertEqual("CAST(name AS VARCHAR)", Cast_(note.name, "varchar").get_sql())