@@ -83,10 +83,11 @@ def query(
8383 try :
8484 cur = db_connection .client .cursor ()
8585 logger .info (f"Executing : Query | { selectStatement } " )
86- self .__execute_sql (cur , selectStatement , parameters = parameters )
86+ self ._execute_sql (cur , selectStatement , parameters = parameters )
8787 all_rows = cur .fetchall ()
88+ col_names = [c [0 ] for c in cur .description ]
89+ self ._log_query_result (col_names , all_rows )
8890 if returnAsDict :
89- col_names = [c [0 ] for c in cur .description ]
9091 return [dict (zip (col_names , row )) for row in all_rows ]
9192 return all_rows
9293 finally :
@@ -123,13 +124,15 @@ def row_count(
123124 try :
124125 cur = db_connection .client .cursor ()
125126 logger .info (f"Executing : Row Count | { selectStatement } " )
126- self .__execute_sql (cur , selectStatement , parameters = parameters )
127+ self ._execute_sql (cur , selectStatement , parameters = parameters )
127128 data = cur .fetchall ()
129+ col_names = [c [0 ] for c in cur .description ]
128130 if db_connection .module_name in ["sqlite3" , "ibm_db" , "ibm_db_dbi" , "pyodbc" ]:
129131 current_row_count = len (data )
130132 else :
131133 current_row_count = cur .rowcount
132134 logger .info (f"Retrieved { current_row_count } rows" )
135+ self ._log_query_result (col_names , data )
133136 return current_row_count
134137 finally :
135138 if cur and not sansTran :
@@ -175,7 +178,7 @@ def description(
175178 try :
176179 cur = db_connection .client .cursor ()
177180 logger .info ("Executing : Description | {selectStatement}" )
178- self .__execute_sql (cur , selectStatement , parameters = parameters )
181+ self ._execute_sql (cur , selectStatement , parameters = parameters )
179182 description = list (cur .description )
180183 if sys .version_info [0 ] < 3 :
181184 for row in range (0 , len (description )):
@@ -205,7 +208,7 @@ def delete_all_rows_from_table(self, tableName: str, sansTran: bool = False, ali
205208 try :
206209 cur = db_connection .client .cursor ()
207210 logger .info (f"Executing : Delete All Rows From Table | { query } " )
208- result = self .__execute_sql (cur , query )
211+ result = self ._execute_sql (cur , query )
209212 if result is not None :
210213 if not sansTran :
211214 db_connection .client .commit ()
@@ -289,7 +292,7 @@ def execute_sql_script(
289292 logger .info (f"Executing : Execute SQL Script | { sqlScriptFileName } " )
290293 if not split :
291294 logger .info ("Statements splitting disabled - pass entire script content to the database module" )
292- self .__execute_sql (cur , sql_file .read ())
295+ self ._execute_sql (cur , sql_file .read ())
293296 else :
294297 logger .info ("Splitting script file into statements..." )
295298 statements_to_execute = []
@@ -355,7 +358,7 @@ def execute_sql_script(
355358 logger .info (f"Executing statement from script file: { statement } " )
356359 line_ends_with_proc_end = re .compile (r"(\s|;)" + proc_end_pattern .pattern + "$" )
357360 omit_semicolon = not line_ends_with_proc_end .search (statement .lower ())
358- self .__execute_sql (cur , statement , omit_semicolon )
361+ self ._execute_sql (cur , statement , omit_semicolon )
359362 if not sansTran :
360363 db_connection .client .commit ()
361364 finally :
@@ -400,7 +403,7 @@ def execute_sql_string(
400403 try :
401404 cur = db_connection .client .cursor ()
402405 logger .info (f"Executing : Execute SQL String | { sqlString } " )
403- self .__execute_sql (cur , sqlString , omit_trailing_semicolon = omitTrailingSemicolon , parameters = parameters )
406+ self ._execute_sql (cur , sqlString , omit_trailing_semicolon = omitTrailingSemicolon , parameters = parameters )
404407 if not sansTran :
405408 db_connection .client .commit ()
406409 finally :
@@ -549,7 +552,7 @@ def call_stored_procedure(
549552 if cur and not sansTran :
550553 db_connection .client .rollback ()
551554
552- def __execute_sql (
555+ def _execute_sql (
553556 self ,
554557 cur ,
555558 sql_statement : str ,
@@ -573,3 +576,41 @@ def __execute_sql(
573576 else :
574577 logger .debug (f"Executing sql '{ sql_statement } ' with parameters: { parameters } " )
575578 return cur .execute (sql_statement , parameters )
579+
580+ def _log_query_result (self , col_names , result_rows , log_head = 50 ):
581+ """
582+ Logs the `result_rows` of a query in RF log as a HTML table.
583+ The `col_names` are needed for the table header.
584+ Max. `log_head` rows are logged (`0` disables the limit).
585+ """
586+ cell_border_and_align = "border: 1px solid rgb(160 160 160);padding: 8px 10px;text-align: center;"
587+ table_border = "2px solid rgb(140 140 140)"
588+ row_index_color = "#d6ecd4"
589+ msg = f'<div style="max-width: 100%; overflow-x: auto;">'
590+ msg += f'<table style="width: auto; border-collapse: collapse; border: { table_border } ">'
591+ msg += f'<caption style="text-align: left; font-weight: bold; padding: 5px;">Query returned { len (result_rows )} rows</caption>'
592+ msg += "<tr>"
593+ msg += f'<th scope="col" style="background-color: { row_index_color } ; { cell_border_and_align } ">Row</th>'
594+ for col in col_names :
595+ msg += f'<th scope="col" style="background-color: #505050; color: #fff;{ cell_border_and_align } ">{ col } </th>'
596+ msg += "</tr>"
597+ table_truncated = False
598+ for i , row in enumerate (result_rows ):
599+ if log_head and i >= log_head :
600+ table_truncated = True
601+ break
602+ row_style = ""
603+ if i % 2 == 0 :
604+ row_style = ' style="background-color: #eee;"'
605+ msg += f"<tr{ row_style } >"
606+ msg += f'<th scope="row" style="background-color: { row_index_color } ;{ cell_border_and_align } ">{ i } </th>'
607+ for cell in row :
608+ msg += f'<td style="{ cell_border_and_align } ">{ cell } </td>'
609+ msg += "</tr>"
610+ msg += "</table>"
611+ if table_truncated :
612+ msg += (
613+ f'<p style="font-weight: bold;">Log limit of { log_head } rows was reached, the table was truncated</p>'
614+ )
615+ msg += "</div>"
616+ logger .info (msg , html = True )
0 commit comments