@@ -701,6 +701,32 @@ def _safeCmd(self, command):
701701 """Just replaces password, if visible, with *********"""
702702 return command .replace (self .__passwd , "**********" )
703703
704+ def _logCmd (self , cmd , args = None ):
705+ """Return a copy of the SQL command with %s placeholders
706+ replaced by their actual values including basic string quoting.
707+ The formatting may not be perfect SQL in every case, but it should be
708+ good enough to see what's going to the database in the log.
709+ If formatting is not possibe, the unformatted cmd will be returned.
710+ """
711+ safe = self ._safeCmd (cmd )
712+ if args is None or not isinstance (args , (list , tuple )) or not args :
713+ return safe
714+
715+ subs = []
716+ for v in args :
717+ if v is None :
718+ subs .append ("NULL" )
719+ elif isinstance (v , (int , float )):
720+ subs .append (str (v ))
721+ else :
722+ escaped = str (v ).replace ('"' , '""' )
723+ subs .append (f'"{ escaped } "' )
724+
725+ try :
726+ return safe % tuple (subs )
727+ except TypeError :
728+ return safe
729+
704730 def _connect (self ):
705731 """
706732 open connection to MySQL DB and put Connection into Queue
@@ -724,18 +750,23 @@ def _connect(self):
724750 return S_OK ()
725751
726752 @captureOptimizerTraces
727- def _query (self , cmd , * , args = None , conn = None , debug = True ):
753+ def _query (self , cmd , * , args = None , logArgs = None , conn = None , debug = True ):
728754 """
729755 execute MySQL query command
730756
731757 :param debug: print or not the errors
758+ :param logArgs: alternative args list for logging only; when set it is
759+ used by ``_logCmd`` so that secrets present in *args*
760+ can be omitted from the log.
732761
733762 return S_OK structure with fetchall result as tuple
734763 it returns an empty tuple if no matching rows are found
735764 return S_ERROR upon error
736765 """
737766
738- self .log .debug (f"_query: { self ._safeCmd (cmd )} " )
767+ if logArgs is None :
768+ logArgs = args
769+ self .log .debug (f"_query: { self ._logCmd (cmd , logArgs )} " )
739770
740771 if conn :
741772 connection = conn
@@ -772,10 +803,13 @@ def _query(self, cmd, *, args=None, conn=None, debug=True):
772803 return retDict
773804
774805 @captureOptimizerTraces
775- def _update (self , cmd , * , args = None , conn = None , debug = True ):
806+ def _update (self , cmd , * , args = None , logArgs = None , conn = None , debug = True ):
776807 """execute MySQL update command
777808
778809 :param args: parameters passed to cursor.execute(..., args=args) method.
810+ :param logArgs: alternative args list for logging only; when set it is
811+ used by ``_logCmd`` so that secrets present in *args*
812+ can be omitted from the log.
779813 :param conn: connection object.
780814 :param debug: print or not the errors
781815
@@ -784,7 +818,9 @@ def _update(self, cmd, *, args=None, conn=None, debug=True):
784818 lastRowId: if set, added to the returned dictionary
785819 """
786820
787- self .log .debug (f"_update: { self ._safeCmd (cmd )} " )
821+ if logArgs is None :
822+ logArgs = args
823+ self .log .debug (f"_update: { self ._logCmd (cmd , logArgs )} " )
788824 if conn :
789825 connection = conn
790826 else :
@@ -812,16 +848,28 @@ def _update(self, cmd, *, args=None, conn=None, debug=True):
812848 return retDict
813849
814850 @captureOptimizerTraces
815- def _updatemany (self , cmd , data , * , conn = None , debug = True ):
851+ def _updatemany (self , cmd , data , * , logData = None , conn = None , debug = True ):
816852 """execute MySQL updatemany command
817853
854+ :param cmd: SQL command template.
855+ :param data: iterable of parameter tuples for ``executemany``.
856+ :param logData: alternative data for logging only; when set it is
857+ used by ``_logCmd`` so that secrets present in *data*
858+ can be omitted from the log.
859+ logData may have fewer entries than data if logging
860+ a sub-set of example entries is required.
861+ :param conn: connection object.
818862 :param debug: print or not the errors
819863
820864 :return: S_OK with number of updated registers upon success.
821865 S_ERROR upon error.
822866 """
823867
824- self .log .debug (f"_updatemany: { self ._safeCmd (cmd )} " )
868+ if logData is None :
869+ logData = data
870+ for idx , row in enumerate (logData , 1 ):
871+ self .log .debug (f"_updatemany [{ idx } ]: { self ._logCmd (cmd , row )} " )
872+
825873 if conn :
826874 connection = conn
827875 else :
0 commit comments