Skip to content

Commit 36aa880

Browse files
CASSANDRA-21381: Fix control character corruption during CSV export in cqlsh
1 parent dc7935b commit 36aa880

2 files changed

Lines changed: 27 additions & 17 deletions

File tree

pylib/cqlshlib/copyutil.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1753,7 +1753,8 @@ def format_value(self, val, cqltype):
17531753
encoding=self.encoding, colormap=NO_COLOR_MAP, date_time_format=self.date_time_format,
17541754
float_precision=cqltype.precision, nullval=self.nullval, quote=False,
17551755
decimal_sep=self.decimal_sep, thousands_sep=self.thousands_sep,
1756-
boolean_styles=self.boolean_styles)
1756+
boolean_styles=self.boolean_styles,
1757+
escape_control_chars=False)
17571758
return formatted
17581759

17591760
def close(self):

pylib/cqlshlib/formatting.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ def _turn_bits_red(match):
6161

6262
def format_by_type(val, cqltype, encoding, colormap=None, addcolor=False,
6363
nullval=None, date_time_format=None, float_precision=None,
64-
decimal_sep=None, thousands_sep=None, boolean_styles=None):
64+
decimal_sep=None, thousands_sep=None, boolean_styles=None,
65+
escape_control_chars=True):
6566
if nullval is None:
6667
nullval = default_null_placeholder
6768
if val is None:
@@ -77,7 +78,7 @@ def format_by_type(val, cqltype, encoding, colormap=None, addcolor=False,
7778
return format_value(val, cqltype=cqltype, encoding=encoding, colormap=colormap,
7879
date_time_format=date_time_format, float_precision=float_precision,
7980
nullval=nullval, decimal_sep=decimal_sep, thousands_sep=thousands_sep,
80-
boolean_styles=boolean_styles)
81+
boolean_styles=boolean_styles, escape_control_chars=escape_control_chars)
8182

8283

8384
def color_text(bval, colormap, displaywidth=None):
@@ -477,11 +478,12 @@ def decode_zig_zag_64(n):
477478

478479

479480
@formatter_for('str')
480-
def format_value_text(val, encoding, colormap, quote=False, **_):
481+
def format_value_text(val, encoding, colormap, quote=False, escape_control_chars=True, **_):
481482
escapedval = val.replace('\\', '\\\\')
482483
if quote:
483484
escapedval = escapedval.replace("'", "''")
484-
escapedval = UNICODE_CONTROLCHARS_RE.sub(_show_control_chars, escapedval)
485+
if escape_control_chars:
486+
escapedval = UNICODE_CONTROLCHARS_RE.sub(_show_control_chars, escapedval)
485487
bval = escapedval
486488
if quote:
487489
bval = "'{}'".format(bval)
@@ -496,11 +498,13 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
496498

497499
def format_simple_collection(val, cqltype, lbracket, rbracket, encoding,
498500
colormap, date_time_format, float_precision, nullval,
499-
decimal_sep, thousands_sep, boolean_styles):
501+
decimal_sep, thousands_sep, boolean_styles,
502+
escape_control_chars=True):
500503
subs = [format_value(sval, cqltype=stype, encoding=encoding, colormap=colormap,
501504
date_time_format=date_time_format, float_precision=float_precision,
502505
nullval=nullval, quote=True, decimal_sep=decimal_sep,
503-
thousands_sep=thousands_sep, boolean_styles=boolean_styles)
506+
thousands_sep=thousands_sep, boolean_styles=boolean_styles,
507+
escape_control_chars=escape_control_chars)
504508
for sval, stype in zip(val, cqltype.get_n_sub_types(len(val)))]
505509
bval = lbracket + ', '.join(get_str(sval) for sval in subs) + rbracket
506510
if colormap is NO_COLOR_MAP:
@@ -515,26 +519,29 @@ def format_simple_collection(val, cqltype, lbracket, rbracket, encoding,
515519

516520
@formatter_for('list')
517521
def format_value_list(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
518-
decimal_sep, thousands_sep, boolean_styles, **_):
522+
decimal_sep, thousands_sep, boolean_styles, escape_control_chars=True, **_):
519523
return format_simple_collection(val, cqltype, '[', ']', encoding, colormap,
520524
date_time_format, float_precision, nullval,
521-
decimal_sep, thousands_sep, boolean_styles)
525+
decimal_sep, thousands_sep, boolean_styles,
526+
escape_control_chars=escape_control_chars)
522527

523528

524529
@formatter_for('tuple')
525530
def format_value_tuple(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
526-
decimal_sep, thousands_sep, boolean_styles, **_):
531+
decimal_sep, thousands_sep, boolean_styles, escape_control_chars=True, **_):
527532
return format_simple_collection(val, cqltype, '(', ')', encoding, colormap,
528533
date_time_format, float_precision, nullval,
529-
decimal_sep, thousands_sep, boolean_styles)
534+
decimal_sep, thousands_sep, boolean_styles,
535+
escape_control_chars=escape_control_chars)
530536

531537

532538
@formatter_for('set')
533539
def format_value_set(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
534-
decimal_sep, thousands_sep, boolean_styles, **_):
540+
decimal_sep, thousands_sep, boolean_styles, escape_control_chars=True, **_):
535541
return format_simple_collection(val, cqltype, '{', '}', encoding, colormap,
536542
date_time_format, float_precision, nullval,
537-
decimal_sep, thousands_sep, boolean_styles)
543+
decimal_sep, thousands_sep, boolean_styles,
544+
escape_control_chars=escape_control_chars)
538545

539546

540547
formatter_for('frozenset')(format_value_set)
@@ -544,12 +551,13 @@ def format_value_set(val, cqltype, encoding, colormap, date_time_format, float_p
544551

545552
@formatter_for('dict')
546553
def format_value_map(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
547-
decimal_sep, thousands_sep, boolean_styles, **_):
554+
decimal_sep, thousands_sep, boolean_styles, escape_control_chars=True, **_):
548555
def subformat(v, t):
549556
return format_value(v, cqltype=t, encoding=encoding, colormap=colormap,
550557
date_time_format=date_time_format, float_precision=float_precision,
551558
nullval=nullval, quote=True, decimal_sep=decimal_sep,
552-
thousands_sep=thousands_sep, boolean_styles=boolean_styles)
559+
thousands_sep=thousands_sep, boolean_styles=boolean_styles,
560+
escape_control_chars=escape_control_chars)
553561

554562
subs = [(subformat(k, cqltype.sub_types[0]), subformat(v, cqltype.sub_types[1])) for (k, v) in sorted(val.items())]
555563
bval = '{' + ', '.join(get_str(k) + ': ' + get_str(v) for (k, v) in subs) + '}'
@@ -572,14 +580,15 @@ def subformat(v, t):
572580

573581

574582
def format_value_utype(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
575-
decimal_sep, thousands_sep, boolean_styles, **_):
583+
decimal_sep, thousands_sep, boolean_styles, escape_control_chars=True, **_):
576584
def format_field_value(v, t):
577585
if v is None:
578586
return colorme(nullval, colormap, 'error')
579587
return format_value(v, cqltype=t, encoding=encoding, colormap=colormap,
580588
date_time_format=date_time_format, float_precision=float_precision,
581589
nullval=nullval, quote=True, decimal_sep=decimal_sep,
582-
thousands_sep=thousands_sep, boolean_styles=boolean_styles)
590+
thousands_sep=thousands_sep, boolean_styles=boolean_styles,
591+
escape_control_chars=escape_control_chars)
583592

584593
def format_field_name(name):
585594
return format_value_text(name, encoding=encoding, colormap=colormap, quote=False)

0 commit comments

Comments
 (0)