Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 50 additions & 7 deletions lib/features/workspace/sql_query_history_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,7 @@ class _SqlQueryHistoryDialogContentState
});
}

static final _whitespacePattern = RegExp(r'\s+');

static String _previewOneLine(String sql) {
final collapsed = sql.replaceAll(_whitespacePattern, ' ').trim();
if (collapsed.length <= 96) return collapsed;
return '${collapsed.substring(0, 93)}…';
}
static String _previewOneLine(String sql) => previewSqlOneLine(sql);

static String? _formatWhen(String iso) {
final t = DateTime.tryParse(iso)?.toLocal();
Expand Down Expand Up @@ -405,3 +399,52 @@ class _SqlQueryHistoryDialogContentState
);
}
}

/// Longest one-line preview kept whole; longer text is cut to
/// [_previewKeep] characters plus an ellipsis.
const int _previewMax = 96;
const int _previewKeep = 93;

/// Same set as the regex `\s` (what the old `replaceAll(RegExp(r'\s+'), ' ')`
/// collapsed).
bool _isPreviewWhitespace(int c) =>
(c >= 0x09 && c <= 0x0D) ||
c == 0x20 ||
c == 0xA0 ||
c == 0x1680 ||
(c >= 0x2000 && c <= 0x200A) ||
c == 0x2028 ||
c == 0x2029 ||
c == 0x202F ||
c == 0x205F ||
c == 0x3000 ||
c == 0xFEFF;

/// One-line, whitespace-collapsed, trimmed preview of [sql] for a list row.
///
/// Reads only as far as it needs: a 100 KB migration is cut after about a
/// hundred characters instead of being copied whole by a regex replace (#1545).
@visibleForTesting
String previewSqlOneLine(String sql) {
final out = StringBuffer();
var length = 0;
var pendingSpace = false;
for (var i = 0; i < sql.length; i++) {
if (_isPreviewWhitespace(sql.codeUnitAt(i))) {
pendingSpace = length > 0;
continue;
}
if (pendingSpace) {
out.writeCharCode(0x20);
length++;
pendingSpace = false;
if (length > _previewMax) break;
}
out.writeCharCode(sql.codeUnitAt(i));
length++;
if (length > _previewMax) break;
}
final text = out.toString();
if (length <= _previewMax) return text;
return '${text.substring(0, _previewKeep)}…';
}
44 changes: 44 additions & 0 deletions test/features/workspace/sql_query_history_preview_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:querya_desktop/features/workspace/sql_query_history_dialog.dart';

/// The implementation before #1545: collapse the whole text, then cut.
String _reference(String sql) {
final collapsed = sql.replaceAll(RegExp(r'\s+'), ' ').trim();
if (collapsed.length <= 96) return collapsed;
return '${collapsed.substring(0, 93)}…';
}

void main() {
group('previewSqlOneLine (#1545)', () {
test('matches the old collapse-then-cut result', () {
final inputs = <String>[
'',
' ',
' \n\t ',
'SELECT 1',
' SELECT 1 \n FROM\tt ',
'SELECT a, b FROM t',
'a' * 96,
'a' * 97,
'${'a' * 96} ',
'${'a' * 96} b',
'${'a' * 95} b',
'${'a' * 94} b c',
('select x from t\n' * 20),
'\n\n\n${'x ' * 200}',
'a' * 5000,
'word ' * 30000,
];
for (final sql in inputs) {
expect(previewSqlOneLine(sql), _reference(sql),
reason: 'input of length ${sql.length}');
}
});

test('long text is cut to 93 characters and an ellipsis', () {
final out = previewSqlOneLine('SELECT ${'column_name, ' * 100}FROM t');
expect(out.length, 94);
expect(out.endsWith('…'), isTrue);
});
});
}
Loading