From 18293764fd2619960bbeab7883db0668241a2b9f Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 14 Aug 2024 14:36:07 -0400 Subject: [PATCH] Work on CRUD v2 and better SQL WHERE part building... I hope. --- app/ae_obj_types_def.py | 38 ++++++++++++++++--- app/db_sql.py | 76 +++++++++++++++++++++++++++++++++++++- app/routers/api_crud.py | 4 +- app/routers/api_crud_v2.py | 31 ++++++++++++++++ 4 files changed, 140 insertions(+), 9 deletions(-) diff --git a/app/ae_obj_types_def.py b/app/ae_obj_types_def.py index 5bbd457..1cadc86 100644 --- a/app/ae_obj_types_def.py +++ b/app/ae_obj_types_def.py @@ -95,15 +95,32 @@ obj_type_kv_li = { ], }, 'sponsorship_cfg': { - 'tbl': 'sponsorship_cfg', 'tbl_default': 'v_sponsorship_cfg', 'tbl_update': 'sponsorship_cfg', - 'mdl': Sponsorship_Cfg_Base, 'mdl_default': Sponsorship_Cfg_Base, 'mdl_in': None, 'mdl_out': None + 'tbl': 'sponsorship_cfg', + 'tbl_default': 'v_sponsorship_cfg', + 'tbl_update': 'sponsorship_cfg', + 'mdl': Sponsorship_Cfg_Base, + 'mdl_default': Sponsorship_Cfg_Base, + 'mdl_in': None, + 'mdl_out': None }, 'event_badge': { - 'tbl': 'event_badge', 'tbl_default': 'v_event_badge', 'tbl_alt': 'v_event_badge_only', 'tbl_update': 'event_badge', - 'mdl': Event_Badge_Base, 'mdl_default': Event_Badge_Basic_Base, 'mdl_alt': Event_Badge_Basic_Base + 'tbl': 'event_badge', + 'tbl_default': 'v_event_badge', + 'tbl_alt': 'v_event_badge_only', + 'tbl_update': 'event_badge', + 'mdl': Event_Badge_Base, + 'mdl_default': Event_Badge_Basic_Base, + 'mdl_alt': Event_Badge_Basic_Base }, 'event_presenter': { - 'tbl': 'event_presenter', 'tbl_default': 'v_event_presenter', 'tbl_update': 'event_presenter', 'mdl': Event_Presenter_Base, 'mdl_default': Event_Presenter_Base, 'mdl_in': Event_Presenter_Base, 'mdl_out': Event_Presenter_Out_Base, + 'tbl': 'event_presenter', + 'tbl_default': 'v_event_presenter', + 'tbl_alt': 'v_event_presenter_w_file_count', + 'tbl_update': 'event_presenter', + 'mdl': Event_Presenter_Base, + 'mdl_default': Event_Presenter_Base, + 'mdl_in': Event_Presenter_Base, + 'mdl_out': Event_Presenter_Out_Base, 'exp_default': [ 'event_presenter_id_random', # 'account_id_random', @@ -123,6 +140,15 @@ obj_type_kv_li = { 'base_name': Event_Presenter_Base # WARNING: These must be updated soon! }, + 'event_session': { + 'table_name': 'v_event_session', + 'tbl_default': 'v_event_session', + 'tbl_alt': 'v_event_session_w_file_count', + 'tbl_name_update': 'event_session', + 'mdl_default': Event_Session_Base, + 'base_name': Event_Session_Base, + 'exclude_for_db': {'poc_person_id', 'file_count', 'internal_use_count', 'enable_from', 'enable_to', 'event_name', 'event_start_datetime', 'event_end_datetime', 'event_location_name', 'event_track_name', 'event_abstract_list', 'event_badge_list', 'event_device_list', 'event_file_list', 'event_file_internal_use_list', 'event_location', 'event_location_list', 'event_person_list', 'event_presenter_cat', 'event_presentation_list', 'event_presenter_list', 'event_track', 'poc_event_person'} + }, } # WARNING: These must be updated soon! @@ -220,7 +246,7 @@ obj_type_kv_li['event_person_tracking'] = {'table_name': 'v_event_person_trackin obj_type_kv_li['event_presentation'] = {'table_name': 'v_event_presentation', 'table_name_alt': 'v_event_presentation_w_file_count', 'tbl_name_update': 'event_presentation', 'base_name': Event_Presentation_Base} # obj_type_kv_li['event_presenter'] = {'table_name': 'v_event_presenter', 'table_name_alt': 'v_event_presenter_w_file_count', 'tbl_name_update': 'event_presenter', 'base_name': Event_Presenter_Base} obj_type_kv_li['event_registration'] = {'table_name': 'v_event_registration', 'tbl_name_update': 'event_registration', 'base_name': Event_Registration_Base} -obj_type_kv_li['event_session'] = {'table_name': 'v_event_session', 'table_name_alt': 'v_event_session_w_file_count', 'tbl_name_update': 'event_session', 'base_name': Event_Session_Base, 'exclude_for_db': {'poc_person_id', 'file_count', 'internal_use_count', 'enable_from', 'enable_to', 'event_name', 'event_start_datetime', 'event_end_datetime', 'event_location_name', 'event_track_name', 'event_abstract_list', 'event_badge_list', 'event_device_list', 'event_file_list', 'event_file_internal_use_list', 'event_location', 'event_location_list', 'event_person_list', 'event_presenter_cat', 'event_presentation_list', 'event_presenter_list', 'event_track', 'poc_event_person'}} + obj_type_kv_li['event_track'] = {'table_name': 'v_event_track', 'tbl_name_update': 'event_track', 'base_name': Event_Track_Base} obj_type_kv_li['grant'] = {'table_name': 'v_grant', 'tbl_name_update': 'grant', 'base_name': Grant_Base} diff --git a/app/db_sql.py b/app/db_sql.py index d847ad4..688c63e 100644 --- a/app/db_sql.py +++ b/app/db_sql.py @@ -548,6 +548,7 @@ def sql_select( field_value = None, enabled: str|None = None, # enabled, disabled, all hidden: str|None = None, # hidden, not_hidden, all + qry_dict_li: dict|None = None, # NEW 2024-08-14 fulltext_qry_dict: dict|None = None, and_qry_dict: dict|None = None, and_like_dict: dict|None = None, @@ -703,12 +704,21 @@ def sql_select( elif table_name and field_name and field_value and not (record_id or record_id_random or sql or data): # Select all records from a table with a specific field and field value # Updated 2023-11-30 - # log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.info('Select all records from a table with a specific field and field value') if not data: data = {} + # This is the new catch all version for building the WHERE clause for the SQL SELECT statement. -2024-08-14 + sql_where_qry = '' + if qry_dict_li: + log.info('Creating partial SQL string for search.') + sql_where_qry, data_qry = sql_where_qry_part(qry_dict_li) + + # NOTE: Merge the data_qry result with the data dict + data = {**data, **data_qry} + sql_fulltext_match_against = '' if fulltext_qry_dict: log.info('Creating partial SQL string for fulltext search.') @@ -807,6 +817,7 @@ def sql_select( SELECT * FROM `{table_name}` WHERE `{table_name}`.{field_name} = :{field_name} + {sql_where_qry} {sql_fulltext_match_against} {sql_and_qry} {sql_and_like} @@ -1692,6 +1703,69 @@ def get_account_id_w_for_type_id( # ### END ### API DB SQL Methods ### get_account_id_w_for_type_id() ### +# ### BEGIN ### API DB SQL Methods ### sql_where_qry_part() ### +# Example JSON data +# jp: { +# qry: [ +# { +# type: "AND", +# field: "enable", +# operator: "=", +# value: TRUE +# }, +# { +# type: "AND", +# field: "example", +# operator: ">=", +# value: 2 +# }, +# { +# type: "OR", +# field: "test", +# operator: "LIKE", +# value: "%xyz%" +# }, +# ] +# } +# Updated 2024-08-14 +def sql_where_qry_part( + qry_dict_li: list, # JSON data + ) -> bool|str: + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + data = {} + sql_where_qry = '' + + if qry_dict_li and isinstance(qry_dict_li, list): + log.info('Creating partial SQL string for WHERE queries.') + sql_where_qry_str = [] + + for qry in qry_dict_li: + log.debug(qry) + if qry.get('type') == '': + sql_where_qry_str.append(f'{qry.get("field")} {qry.get("operator")} :{qry.get("field")}') + data[qry.get('field')] = qry.get('value') + elif qry.get('type') == 'AND': + sql_where_qry_str.append(f'AND {qry.get("field")} {qry.get("operator")} :{qry.get("field")}') + data[qry.get('field')] = qry.get('value') + elif qry.get('type') == 'OR': + sql_where_qry_str.append(f'OR {qry.get("field")} {qry.get("operator")} :{qry.get("field")}') + data[qry.get('field')] = qry.get('value') + else: + log.error(f'Unknown query type: {qry.get("type")}') + return False + + # Should this WHERE part also be surrounded by parentheses??? + # sql_where_qry = 'AND ('+' '.join(sql_where_qry_str)+')' + # sql_where_qry = sql_where_qry_str + sql_where_qry = ' '.join(sql_where_qry_str) + log.debug(sql_where_qry) + + return sql_where_qry, data +# ### END ### API DB SQL Methods ### sql_where_qry_part() ### + + # ### BEGIN ### API DB SQL Methods ### sql_fulltext_qry_part() ### # Updated 2023-11-30 @logger_reset diff --git a/app/routers/api_crud.py b/app/routers/api_crud.py index aafb24e..5ac3260 100644 --- a/app/routers/api_crud.py +++ b/app/routers/api_crud.py @@ -366,7 +366,7 @@ def handle_get_obj_li( commons: Common_Route_Params = None, ): - log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) import urllib @@ -538,7 +538,7 @@ def handle_get_obj_li( if sql_result: if isinstance(sql_result, list): - log.setLevel(logging.DEBUG) + log.setLevel(logging.INFO) resp_data_li = [] for record in sql_result: if base_name: diff --git a/app/routers/api_crud_v2.py b/app/routers/api_crud_v2.py index c0f9405..bf0be1c 100644 --- a/app/routers/api_crud_v2.py +++ b/app/routers/api_crud_v2.py @@ -298,6 +298,9 @@ def handle_get_obj_li( import urllib + # This should be a list of SQL WHERE parts defined in JSON. + qry_dict_li = None + # This should be a dict list of fields with a list of values to search for using FULLTEXT. fulltext_qry_dict_obj = None @@ -325,6 +328,32 @@ def handle_get_obj_li( log.info(jp_obj) + if jp_obj.get('qry'): # NOTE: This is for specific additional WHERE clauses in the SQL statement + # Example JSON: + # jp: { + # qry: [ + # { + # type: "AND", + # field: "enable", + # operator: "=", + # value: TRUE + # }, + # { + # type: "AND", + # field: "example", + # operator: ">=", + # value: 2 + # }, + # { + # type: "OR", + # field: "test", + # operator: "LIKE", + # value: "%xyz%" + # }, + # ] + # } + qry_dict_li = jp_obj['qry'] + if jp_obj.get('ft_qry'): # NOTE: This is for the fulltext query fulltext_qry_dict_obj = jp_obj['ft_qry'] @@ -445,6 +474,7 @@ def handle_get_obj_li( field_value = for_obj_id, enabled = commons.enabled, hidden = hidden, + qry_dict_li = qry_dict_li, fulltext_qry_dict = fulltext_qry_dict_obj, and_qry_dict = and_qry_dict_obj, and_like_dict = and_like_dict_obj, @@ -465,6 +495,7 @@ def handle_get_obj_li( table_name = table_name, enabled = commons.enabled, hidden = hidden, + qry_dict_li = qry_dict_li, fulltext_qry_dict = fulltext_qry_dict_obj, and_qry_dict = and_qry_dict_obj, and_like_dict = and_like_dict_obj,