11from logging import getLogger
22from json import dumps
3- from typing import Any , Dict , List , Optional
3+ from typing import Any , Dict , List , Optional , Union
44
5- from ..const .error import WrongParamsError
5+ from tortoise .expressions import Q
6+ from tortoise .models import Model
7+ from tortoise .query_utils import QueryModifier
8+
9+ from ..const .error import QsParsingError , WrongParamsError
610
711logger = getLogger (__name__ )
812# ensure the functionality of the RawSQL
@@ -19,11 +23,35 @@ def __init__(self, sql: str):
1923class SQLizer :
2024
2125 @classmethod
22- def resolve_condition (cls , conditions : List [str ]) -> str :
23- return " AND " .join (conditions )
26+ def resolve_wheres (
27+ cls ,
28+ wheres : Union [str , Q , Dict [str , Any ], List [Q ]],
29+ model : Optional [Model ] = None ,
30+ ) -> str :
31+ if not model and not isinstance (wheres , str ):
32+ raise WrongParamsError ("Parameter `wheres` only support str type if no model passed" )
33+
34+ if isinstance (wheres , str ):
35+ return wheres
36+ elif isinstance (wheres , Q ):
37+ qs = [wheres ]
38+ elif isinstance (wheres , dict ):
39+ qs = [Q (** {key : value }) for (key , value ) in wheres .items ()]
40+ elif isinstance (wheres , list ):
41+ qs = [q for q in wheres if isinstance (q , Q )]
42+ else :
43+ raise WrongParamsError ("Parameter `wheres` only supports str, dict and list type" )
44+
45+ if not qs :
46+ raise QsParsingError ("Parsing `wheres` for qs failed!" )
47+
48+ modifier = QueryModifier ()
49+ for q in qs :
50+ modifier &= q .resolve (model , model ._meta .basetable )
51+ return modifier .where_criterion .get_sql (quote_char = "`" )
2452
2553 @classmethod
26- def resolve_ordering (cls , orderings : List [str ]) -> str :
54+ def resolve_orders (cls , orderings : List [str ]) -> str :
2755 orders = []
2856 for o in orderings :
2957 if o .startswith ("-" ):
@@ -59,23 +87,24 @@ def select_custom_fields(
5987 cls ,
6088 table : str ,
6189 fields : List [str ],
62- wheres : List [str ],
90+ wheres : Union [str , Q , Dict [ str , Any ], List [ Q ] ],
6391 groups : Optional [List [str ]] = None ,
64- havings : Optional [List [ str ] ] = None ,
92+ having : Optional [str ] = None ,
6593 orders : Optional [List [str ]] = None ,
6694 limit : int = 0 ,
95+ model : Optional [Model ] = None ,
6796 ) -> Optional [str ]:
6897 if not all ([table , fields , wheres ]):
6998 raise WrongParamsError ("Please check your params" )
70- if havings and not groups :
71- raise WrongParamsError ("Please check your params " )
99+ if having and not groups :
100+ raise WrongParamsError ("Parameter `groups` shoud be no empty when `having` isn't " )
72101
73102 group_by = f" GROUP BY { ', ' .join (groups )} " if groups else ""
74- having = f" HAVING { cls . resolve_condition ( havings ) } " if havings else ""
75- order_by = f" ORDER BY { cls .resolve_ordering (orders )} " if orders else ""
103+ having_ = f" HAVING { having } " if having else ""
104+ order_by = f" ORDER BY { cls .resolve_orders (orders )} " if orders else ""
76105 limit_ = f" LIMIT { limit } " if limit else ""
77106 # NOTE Doesn't support `offset` parameter due to it's bad performance
78- extras = [group_by , having , order_by , limit_ ]
107+ extras = [group_by , having_ , order_by , limit_ ]
79108
80109 sql = """
81110 SELECT
@@ -85,8 +114,8 @@ def select_custom_fields(
85114{}""" .format (
86115 ", " .join (fields ),
87116 table ,
88- cls .resolve_condition (wheres ),
89- "\n " .join (extras ) if extras else "" ,
117+ cls .resolve_wheres (wheres , model ),
118+ "\n " .join (i for i in extras if i ) ,
90119 )
91120 logger .debug (sql )
92121 return sql
@@ -97,7 +126,8 @@ def upsert_json_field(
97126 table : str ,
98127 json_field : str ,
99128 path_value_dict : Dict [str , Any ],
100- wheres : List [str ],
129+ wheres : Union [str , Q , Dict [str , Any ], List [Q ]],
130+ model : Optional [Model ] = None ,
101131 ) -> Optional [str ]:
102132 if not all ([table , json_field , path_value_dict , wheres ]):
103133 raise WrongParamsError ("Please check your params" )
@@ -110,7 +140,7 @@ def upsert_json_field(
110140 sql = f"""
111141 UPDATE { table }
112142 SET { json_field } = JSON_SET(COALESCE({ json_field } , '{{}}'), { ", " .join (params )} )
113- WHERE { cls .resolve_condition (wheres )} """
143+ WHERE { cls .resolve_wheres (wheres , model )} """
114144 logger .debug (sql )
115145 return sql
116146
@@ -147,9 +177,10 @@ def upsert_on_duplicated(
147177 def insert_into_select (
148178 cls ,
149179 table : str ,
150- wheres : List [str ],
180+ wheres : Union [str , Q , Dict [ str , Any ], List [ Q ] ],
151181 remain_fields : List [str ],
152182 assign_field_dict : Dict [str , Any ],
183+ model : Optional [Model ] = None ,
153184 ) -> Optional [str ]:
154185 if not all ([table , wheres ] or not any ([remain_fields , assign_field_dict ])):
155186 raise WrongParamsError ("Please check your params" )
@@ -166,7 +197,7 @@ def insert_into_select(
166197 ({ ", " .join (fields )} )
167198 SELECT { ", " .join (remain_fields + assign_fields )}
168199 FROM { table }
169- WHERE { cls .resolve_condition (wheres )} """
200+ WHERE { cls .resolve_wheres (wheres , model )} """
170201 logger .debug (sql )
171202 return sql
172203
0 commit comments