in src/controllers/queryRunner.ts [394:502]
public async copyResults(selection: ISlickRange[], batchId: number, resultId: number, includeHeaders?: boolean): Promise<void> {
let copyString = '';
// add the column headers
if (this.shouldIncludeHeaders(includeHeaders)) {
let firstCol: number;
let lastCol: number;
for (let range of selection) {
if (firstCol === undefined || (range.fromCell < firstCol)) {
firstCol = range.fromCell;
}
if (lastCol === undefined || (range.toCell > lastCol)) {
lastCol = range.toCell;
}
}
let columnRange: ISlickRange = {
fromCell: firstCol,
toCell: lastCol,
fromRow: undefined,
toRow: undefined
};
let columnHeaders = this.getColumnHeaders(batchId, resultId, columnRange);
copyString += columnHeaders.join('\t');
copyString += os.EOL;
}
// sort the selections by row to maintain copy order
selection.sort((a, b) => a.fromRow - b.fromRow);
// create a mapping of rows to selections
let rowIdToSelectionMap = new Map<number, ISlickRange[]>();
let rowIdToRowMap = new Map<number, DbCellValue[]>();
// create a mapping of the ranges to get promises
let tasks = selection.map((range) => {
return async () => {
const result = await this.getRows(range.fromRow, range.toRow - range.fromRow + 1, batchId, resultId);
for (let row of result.resultSubset.rows) {
let rowNumber = row[0].rowId + range.fromRow;
if (rowIdToSelectionMap.has(rowNumber)) {
let rowSelection = rowIdToSelectionMap.get(rowNumber);
rowSelection.push(range);
} else {
rowIdToSelectionMap.set(rowNumber, [range]);
}
rowIdToRowMap.set(rowNumber, row);
}
};
});
// get all the rows
let p = tasks[0]();
for (let i = 1; i < tasks.length; i++) {
p = p.then(tasks[i]);
}
await p;
// Go through all rows and get selections for them
let allRowIds = rowIdToRowMap.keys();
const endColumns = this.getSelectionEndColumns(rowIdToRowMap, rowIdToSelectionMap);
const firstColumn = endColumns[0];
const lastColumn = endColumns[1];
for (let rowId of allRowIds) {
let row = rowIdToRowMap.get(rowId);
const rowSelections = rowIdToSelectionMap.get(rowId);
// sort selections by column to go from left to right
rowSelections.sort((a, b) => {
return ((a.fromCell < b.fromCell) ? -1 : (a.fromCell > b.fromCell) ? 1 : 0);
});
for (let i = 0; i < rowSelections.length; i++) {
let rowSelection = rowSelections[i];
// Add tabs starting from the first column of the selection
for (let j = firstColumn; j < rowSelection.fromCell; j++) {
copyString += '\t';
}
let cellObjects = row.slice(rowSelection.fromCell, (rowSelection.toCell + 1));
// Remove newlines if requested
let cells = this.shouldRemoveNewLines()
? cellObjects.map(x => this.removeNewLines(x.displayValue))
: cellObjects.map(x => x.displayValue);
copyString += cells.join('\t');
// Add tabs until the end column of the selection
for (let k = rowSelection.toCell; k < lastColumn; k++) {
copyString += '\t';
}
}
copyString += os.EOL;
}
// Remove the last extra new line
if (copyString.length > 1) {
copyString = copyString.substring(0, copyString.length - os.EOL.length);
}
let oldLang: string;
if (process.platform === 'darwin') {
oldLang = process.env['LANG'];
process.env['LANG'] = 'en_US.UTF-8';
}
await this._vscodeWrapper.clipboardWriteText(copyString);
if (process.platform === 'darwin') {
process.env['LANG'] = oldLang;
}
}