diff --git a/app/db_sql.py b/app/db_sql.py index 0708e1b..57210a3 100644 --- a/app/db_sql.py +++ b/app/db_sql.py @@ -543,6 +543,7 @@ def sql_select( hidden: str|None = None, # hidden, not_hidden, all fulltext_qry_dict: dict|None = None, and_qry_dict: dict|None = None, + and_in_dict_li: dict|None = None, fulltext_qry_field_li: list|None = None, # ['field_name_1', 'field_name_2'] fulltext_qry_str: str|None = None, # 'search string' order_by_li: dict|None = None, # {"the_field_name": "DESC"} @@ -713,6 +714,13 @@ def sql_select( # NOTE: Merge the data_qry result with the data dict data = {**data, **data_qry} + sql_and_in_dict_li = '' + if and_in_dict_li: + sql_and_in_dict_li, data_qry = sql_and_in_dict_li_part(and_in_dict_li) + + # NOTE: Merge the data_qry result with the data dict + data = {**data, **data_qry} + # # NOTE: Version 3 of the fulltext search # sql_fulltext_match_against = '' # log.debug(fulltext_qry_dict) @@ -773,6 +781,7 @@ def sql_select( WHERE `{table_name}`.{field_name} = :{field_name} {sql_fulltext_match_against} {sql_and_qry} + {sql_and_in_dict_li} {sql_enabled} {sql_hidden} {sql_order_by} @@ -824,10 +833,10 @@ def sql_select( log.warning('Nothing matched the expected combination of parameters passed to this function') return False # Not successful - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(sql) log.debug(data) - log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + # log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL result = run_sql_select(sql=sql, data=data) # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL @@ -1676,6 +1685,38 @@ def sql_and_qry_part( return sql_and_qry, data +# ### BEGIN ### API DB SQL Methods ### sql_and_in_dict_li_part() ### +# This function takes a list of values and formats them to be used in a SQL IN statement. This may contain one or more fields to use with the IN statement. +# Example: sql_and_in_dict_li_part({'field1': [1, 2, 3], 'field2': ['hello', 'world', 'day']}) +# Updated 2024-03-15 +@logger_reset +def sql_and_in_dict_li_part( + and_in_dict_li_dict_obj: dict + ) -> bool|dict: + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + data = {} + sql_and_in_dict_li = '' + + log.debug(and_in_dict_li_dict_obj) + if and_in_dict_li_dict_obj and isinstance(and_in_dict_li_dict_obj, dict): + log.info('Creating partial SQL string for additional AND IN queries.') + and_in_dict_li_dict_obj_str = [] + + for key, value in and_in_dict_li_dict_obj.items(): + log.debug(f'Key = {key}; Value = {value}') + and_in_dict_li_dict_obj_str.append(f'{key} IN :and_in_{key}') + # and_in_dict_li_dict_obj_str.append(f'{key} IN ( :and_in_{key} )') + data[f'and_in_{key}'] = value + and_in_dict_li_field_string = ' AND '.join(and_in_dict_li_dict_obj_str) + + sql_and_in_dict_li = f'AND ({and_in_dict_li_field_string})' + log.debug(sql_and_in_dict_li) + log.debug(data) + + return sql_and_in_dict_li, data + # ### BEGIN ### API DB SQL Methods ### sql_enable_part() ### # Updated 2022-01-17 @logger_reset diff --git a/app/routers/api_crud.py b/app/routers/api_crud.py index da34488..b7feeb9 100644 --- a/app/routers/api_crud.py +++ b/app/routers/api_crud.py @@ -237,8 +237,15 @@ async def get_obj_li( import urllib + # This should be a dict list of fields with a list of values to search for using FULLTEXT. fulltext_qry_dict_obj = None + + # This should be a dict list of fields with a list of values to search for using AND. and_qry_dict_obj = None + + # This should be a dict list of fields with a list of values to search for using AND IN. + and_in_dict_li_obj = None + jp_obj = None if jp: log.debug( urllib.parse.unquote(jp) ) @@ -256,6 +263,9 @@ async def get_obj_li( if jp_obj.get('and_qry'): # NOTE: This is for the additional AND clauses in the WHERE statement and_qry_dict_obj = jp_obj['and_qry'] + if jp_obj.get('and_in_li'): # NOTE: This is for the additional AND IN clauses in the WHERE statement + and_in_dict_li_obj = jp_obj['and_in_li'] + if order_by_li: order_by_li = json.loads(order_by_li) @@ -340,6 +350,7 @@ async def get_obj_li( hidden = hidden, fulltext_qry_dict = fulltext_qry_dict_obj, and_qry_dict = and_qry_dict_obj, + and_in_dict_li = and_in_dict_li_obj, # fulltext_qry_field_li = fulltext_qry_field_li, # fulltext_qry_str = fulltext_qry_str, order_by_li = order_by_li, @@ -357,6 +368,7 @@ async def get_obj_li( hidden = hidden, fulltext_qry_dict = fulltext_qry_dict_obj, and_qry_dict = and_qry_dict_obj, + and_in_dict_li = and_in_dict_li_obj, # fulltext_qry_field_li = fulltext_qry_field_li, # fulltext_qry_str = fulltext_qry_str, order_by_li = order_by_li,