@@ -627,74 +627,84 @@ def dbTableValues(self, tableValues):
627627 elif conf .dumpFormat == DUMP_FORMAT .SQLITE :
628628 rtable .beginTransaction ()
629629
630+ # Precompute the per-column layout once. These values are invariant across
631+ # every row, so resolving them per cell (dict lookup, int() conversion and
632+ # identifier normalization) wasted count x ncols work on large dumps.
633+ dumpColumns = []
634+ for column in columns :
635+ if column != "__infos__" :
636+ info = tableValues [column ]
637+ dumpColumns .append ((unsafeSQLIdentificatorNaming (column ), info ["values" ], int (info ["length" ])))
638+
630639 for i in xrange (count ):
631640 console = (i >= count - TRIM_STDOUT_DUMP_SIZE )
632641 field = 1
633- values = []
634- record = OrderedDict ()
642+
643+ # Only the SQLITE and JSONL paths accumulate a per-row container; the
644+ # others left these unused, wasting an allocation on every single row
645+ if conf .dumpFormat == DUMP_FORMAT .SQLITE :
646+ values = []
647+ elif conf .dumpFormat == DUMP_FORMAT .JSONL :
648+ record = OrderedDict ()
635649
636650 if i == 0 and count > TRIM_STDOUT_DUMP_SIZE :
637651 self ._write (" ..." )
638652
639653 if conf .dumpFormat == DUMP_FORMAT .HTML :
640654 dataToDumpFile (dumpFP , "<tr>" )
641655
642- for column in columns :
643- if column != "__infos__" :
644- info = tableValues [column ]
645-
646- if len (info ["values" ]) <= i or info ["values" ][i ] is None :
647- value = u''
656+ for safeColumn , colValues , maxlength in dumpColumns :
657+ if len (colValues ) <= i or colValues [i ] is None :
658+ value = u''
659+ else :
660+ value = getUnicode (colValues [i ])
661+ value = DUMP_REPLACEMENTS .get (value , value )
662+
663+ if conf .dumpFormat == DUMP_FORMAT .SQLITE :
664+ # Note: store a real NULL for the NULL sentinel (and the raw value otherwise),
665+ # mirroring the JSONL path below; appending the display-replaced 'NULL'/'<blank>'
666+ # text would corrupt the INTEGER/REAL-typed columns inferred above
667+ if len (colValues ) <= i or colValues [i ] is None or colValues [i ] == " " : # NULL
668+ values .append (None )
648669 else :
649- value = getUnicode (info ["values" ][i ])
650- value = DUMP_REPLACEMENTS .get (value , value )
651-
652- if conf .dumpFormat == DUMP_FORMAT .SQLITE :
653- # Note: store a real NULL for the NULL sentinel (and the raw value otherwise),
654- # mirroring the JSONL path below; appending the display-replaced 'NULL'/'<blank>'
655- # text would corrupt the INTEGER/REAL-typed columns inferred above
656- if len (info ["values" ]) <= i or info ["values" ][i ] is None or info ["values" ][i ] == " " : # NULL
657- values .append (None )
658- else :
659- values .append (getUnicode (info ["values" ][i ]))
670+ values .append (getUnicode (colValues [i ]))
660671
661- maxlength = int (info ["length" ])
662- blank = " " * (maxlength - getConsoleLength (value ))
663- self ._write ("| %s%s" % (value , blank ), newline = False , console = console )
672+ blank = " " * (maxlength - getConsoleLength (value ))
673+ self ._write ("| %s%s" % (value , blank ), newline = False , console = console )
664674
665- if len (value ) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value :
666- try :
667- mimetype = getText (magic .from_buffer (getBytes (value ), mime = True ))
668- if any (mimetype .startswith (_ ) for _ in ("application" , "image" )):
669- if not os .path .isdir (dumpDbPath ):
670- os .makedirs (dumpDbPath )
675+ if len (value ) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value :
676+ try :
677+ mimetype = getText (magic .from_buffer (getBytes (value ), mime = True ))
678+ if any (mimetype .startswith (_ ) for _ in ("application" , "image" )):
679+ if not os .path .isdir (dumpDbPath ):
680+ os .makedirs (dumpDbPath )
671681
672- _ = re .sub (r"[^\w]" , UNSAFE_DUMP_FILEPATH_REPLACEMENT , normalizeUnicode (unsafeSQLIdentificatorNaming ( column ) ))
673- filepath = os .path .join (dumpDbPath , "%s-%d.bin" % (_ , randomInt (8 )))
674- warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype , filepath )
675- logger .warning (warnMsg )
682+ _ = re .sub (r"[^\w]" , UNSAFE_DUMP_FILEPATH_REPLACEMENT , normalizeUnicode (safeColumn ))
683+ filepath = os .path .join (dumpDbPath , "%s-%d.bin" % (_ , randomInt (8 )))
684+ warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype , filepath )
685+ logger .warning (warnMsg )
676686
677- with openFile (filepath , "w+b" , None ) as f :
678- _ = safechardecode (value , True )
679- f .write (_ )
687+ with openFile (filepath , "w+b" , None ) as f :
688+ _ = safechardecode (value , True )
689+ f .write (_ )
680690
681- except Exception as ex :
682- logger .debug (getSafeExString (ex ))
691+ except Exception as ex :
692+ logger .debug (getSafeExString (ex ))
683693
684- if conf .dumpFormat == DUMP_FORMAT .CSV :
685- if field == fields :
686- dataToDumpFile (dumpFP , "%s" % safeCSValue (value ))
687- else :
688- dataToDumpFile (dumpFP , "%s%s" % (safeCSValue (value ), conf .csvDel ))
689- elif conf .dumpFormat == DUMP_FORMAT .HTML :
690- dataToDumpFile (dumpFP , "<td>%s</td>" % getUnicode (htmlEscape (value ).encode ("ascii" , "xmlcharrefreplace" )))
691- elif conf .dumpFormat == DUMP_FORMAT .JSONL :
692- if len (info [ "values" ] ) <= i or info [ "values" ][ i ] is None or info [ "values" ] [i ] == " " : # NULL
693- record [unsafeSQLIdentificatorNaming ( column ) ] = None
694- else :
695- record [unsafeSQLIdentificatorNaming ( column ) ] = getUnicode (info [ "values" ] [i ])
694+ if conf .dumpFormat == DUMP_FORMAT .CSV :
695+ if field == fields :
696+ dataToDumpFile (dumpFP , "%s" % safeCSValue (value ))
697+ else :
698+ dataToDumpFile (dumpFP , "%s%s" % (safeCSValue (value ), conf .csvDel ))
699+ elif conf .dumpFormat == DUMP_FORMAT .HTML :
700+ dataToDumpFile (dumpFP , "<td>%s</td>" % getUnicode (htmlEscape (value ).encode ("ascii" , "xmlcharrefreplace" )))
701+ elif conf .dumpFormat == DUMP_FORMAT .JSONL :
702+ if len (colValues ) <= i or colValues [ i ] is None or colValues [i ] == " " : # NULL
703+ record [safeColumn ] = None
704+ else :
705+ record [safeColumn ] = getUnicode (colValues [i ])
696706
697- field += 1
707+ field += 1
698708
699709 if conf .dumpFormat == DUMP_FORMAT .SQLITE :
700710 try :
0 commit comments