diff --git a/src/commands/dataSourceCommand.ts b/src/commands/dataSourceCommand.ts index 7c31e504..c2c50458 100644 --- a/src/commands/dataSourceCommand.ts +++ b/src/commands/dataSourceCommand.ts @@ -31,7 +31,6 @@ import { getConnectedInsightsNode, } from "../utils/dataSource"; import { - arrayToTable, handleScratchpadTableRes, handleWSError, handleWSResults, @@ -65,13 +64,13 @@ export async function addDataSource(): Promise { fs.writeFileSync(filePath, JSON.stringify(defaultDataSourceContent)); window.showInformationMessage( - `Created ${fileName} in ${kdbDataSourcesFolderPath}.` + `Created ${fileName} in ${kdbDataSourcesFolderPath}.`, ); } export async function renameDataSource( oldName: string, - newName: string + newName: string, ): Promise { const kdbDataSourcesFolderPath = createKdbDataSourcesFolder(); if (!kdbDataSourcesFolderPath) { @@ -80,11 +79,11 @@ export async function renameDataSource( const oldFilePath = path.join( kdbDataSourcesFolderPath, - `${oldName}${ext.kdbDataSourceFileExtension}` + `${oldName}${ext.kdbDataSourceFileExtension}`, ); const newFilePath = path.join( kdbDataSourcesFolderPath, - `${newName}${ext.kdbDataSourceFileExtension}` + `${newName}${ext.kdbDataSourceFileExtension}`, ); const dataSourceContent = fs.readFileSync(oldFilePath, "utf8"); @@ -102,7 +101,7 @@ export async function renameDataSource( } export async function deleteDataSource( - dataSource: KdbDataSourceTreeItem + dataSource: KdbDataSourceTreeItem, ): Promise { const kdbDataSourcesFolderPath = createKdbDataSourcesFolder(); if (!kdbDataSourcesFolderPath) { @@ -111,28 +110,28 @@ export async function deleteDataSource( const dataSourceFilePath = path.join( kdbDataSourcesFolderPath, - `${dataSource.label}${ext.kdbDataSourceFileExtension}` + `${dataSource.label}${ext.kdbDataSourceFileExtension}`, ); if (fs.existsSync(dataSourceFilePath)) { fs.unlinkSync(dataSourceFilePath); window.showInformationMessage( - `Deleted ${dataSource.label} from ${kdbDataSourcesFolderPath}.` + `Deleted ${dataSource.label} from ${kdbDataSourcesFolderPath}.`, ); } } export async function openDataSource( dataSource: KdbDataSourceTreeItem, - uri: Uri + uri: Uri, ): Promise { const kdbDataSourcesFolderPath = createKdbDataSourcesFolder(); Object.assign(ext.insightsMeta, await getMeta()); if (!ext.insightsMeta.assembly) { ext.outputChannel.appendLine( - `To edit or run a datasource you need to be connected to an Insights server` + `To edit or run a datasource you need to be connected to an Insights server`, ); window.showErrorMessage( - "To edit or run a datasource you need to be connected to an Insights server" + "To edit or run a datasource you need to be connected to an Insights server", ); } if (!kdbDataSourcesFolderPath) { @@ -141,12 +140,12 @@ export async function openDataSource( fs.readFile( path.join( kdbDataSourcesFolderPath, - `${dataSource.label}${ext.kdbDataSourceFileExtension}` + `${dataSource.label}${ext.kdbDataSourceFileExtension}`, ), (err, data) => { if (err) { ext.outputChannel.appendLine( - `Error reading the file ${dataSource.label}${ext.kdbDataSourceFileExtension}, this file maybe doesn't exist` + `Error reading the file ${dataSource.label}${ext.kdbDataSourceFileExtension}, this file maybe doesn't exist`, ); window.showErrorMessage("Error reading file"); return; @@ -155,12 +154,12 @@ export async function openDataSource( const datasourceContent: DataSourceFiles = JSON.parse(data.toString()); DataSourcesPanel.render(uri, datasourceContent); } - } + }, ); } export async function saveDataSource( - dataSourceForm: DataSourceFiles + dataSourceForm: DataSourceFiles, ): Promise { const kdbDataSourcesFolderPath = createKdbDataSourcesFolder(); if (!kdbDataSourcesFolderPath) { @@ -181,7 +180,7 @@ export async function saveDataSource( const dataSourceFilePath = path.join( kdbDataSourcesFolderPath, - `${dataSourceForm.name}${ext.kdbDataSourceFileExtension}` + `${dataSourceForm.name}${ext.kdbDataSourceFileExtension}`, ); if (fs.existsSync(dataSourceFilePath)) { @@ -191,7 +190,7 @@ export async function saveDataSource( } export async function populateScratchpad( - dataSourceForm: DataSourceFiles + dataSourceForm: DataSourceFiles, ): Promise { const scratchpadVariable: InputBoxOptions = { prompt: scratchpadVariableInput.prompt, @@ -205,14 +204,14 @@ export async function populateScratchpad( await importScratchpad(outputVariable!, dataSourceForm!); } else { ext.outputChannel.appendLine( - `Invalid scratchpad output variable name: ${outputVariable}` + `Invalid scratchpad output variable name: ${outputVariable}`, ); } }); } export async function runDataSource( - dataSourceForm: DataSourceFiles + dataSourceForm: DataSourceFiles, ): Promise { if (DataSourcesPanel.running) { return; @@ -223,10 +222,10 @@ export async function runDataSource( Object.assign(ext.insightsMeta, await getMeta()); if (!ext.insightsMeta.assembly) { ext.outputChannel.appendLine( - `To run a datasource you need to be connected to an Insights server` + `To run a datasource you need to be connected to an Insights server`, ); window.showErrorMessage( - "To run a datasource you need to be connected to an Insights server" + "To run a datasource you need to be connected to an Insights server", ); return; } @@ -257,14 +256,13 @@ export async function runDataSource( writeQueryResultsToView( res, getQuery(fileContent, selectedType), - selectedType + selectedType, ); } else { - const resString = arrayToTable(res); writeQueryResultsToConsole( - resString, + res, getQuery(fileContent, selectedType), - selectedType + selectedType, ); } } finally { @@ -287,22 +285,22 @@ export function getSelectedType(fileContent: DataSourceFiles): string { } export async function runApiDataSource( - fileContent: DataSourceFiles + fileContent: DataSourceFiles, ): Promise { const isTimeCorrect = checkIfTimeParamIsCorrect( fileContent.dataSource.api.startTS, - fileContent.dataSource.api.endTS + fileContent.dataSource.api.endTS, ); if (!isTimeCorrect) { window.showErrorMessage( - "The time parameters(startTS and endTS) are not correct, please check the format or if the startTS is before the endTS" + "The time parameters(startTS and endTS) are not correct, please check the format or if the startTS is before the endTS", ); return; } const apiBody = getApiBody(fileContent); const apiCall = await getDataInsights( ext.insightsServiceGatewayUrls.data, - JSON.stringify(apiBody) + JSON.stringify(apiBody), ); if (apiCall?.error) { @@ -316,7 +314,7 @@ export async function runApiDataSource( } export function getApiBody( - fileContent: DataSourceFiles + fileContent: DataSourceFiles, ): Partial { const api = fileContent.dataSource.api; @@ -353,7 +351,7 @@ export function getApiBody( if (labels.length > 0) { apiBody.labels = Object.assign( {}, - ...labels.map((label) => ({ [label.key]: label.value })) + ...labels.map((label) => ({ [label.key]: label.value })), ); } @@ -404,7 +402,7 @@ export function getApiBody( } export async function runQsqlDataSource( - fileContent: DataSourceFiles + fileContent: DataSourceFiles, ): Promise { const assembly = fileContent.dataSource.qsql.selectedTarget.slice(0, -4); const target = fileContent.dataSource.qsql.selectedTarget.slice(-3); @@ -415,7 +413,7 @@ export async function runQsqlDataSource( }; const qsqlCall = await getDataInsights( ext.insightsServiceGatewayUrls.qsql, - JSON.stringify(qsqlBody) + JSON.stringify(qsqlBody), ); if (qsqlCall?.error) { @@ -429,14 +427,14 @@ export async function runQsqlDataSource( } export async function runSqlDataSource( - fileContent: DataSourceFiles + fileContent: DataSourceFiles, ): Promise { const sqlBody = { query: fileContent.dataSource.sql.query, }; const sqlCall = await getDataInsights( ext.insightsServiceGatewayUrls.sql, - JSON.stringify(sqlBody) + JSON.stringify(sqlBody), ); if (sqlCall?.error) { @@ -451,7 +449,7 @@ export async function runSqlDataSource( export function getQuery( fileContent: DataSourceFiles, - selectedType: string + selectedType: string, ): string { switch (selectedType) { case "API": diff --git a/src/utils/queryUtils.ts b/src/utils/queryUtils.ts index 34d2f2c0..6eaef2c4 100644 --- a/src/utils/queryUtils.ts +++ b/src/utils/queryUtils.ts @@ -92,10 +92,10 @@ export function handleWSResults(ab: ArrayBuffer): any { if (res.rows.length === 0 && res.columns.length === 0) { return "No results found."; } - if (ext.resultsViewProvider.isVisible() || ext.isDatasourceExecution) { + if (ext.resultsViewProvider.isVisible()) { return getValueFromArray(res); } - return convertRows(res); + return convertRows(res.rows); } catch (error) { console.log(error); throw error; @@ -201,12 +201,14 @@ export function checkIfIsQDateTypes(obj: any): any { return obj; } -export function convertRows(rows: any[]): any[] { +export function convertRows(rows: any[]): any { if (rows.length === 0) { return []; } const keys = Object.keys(rows[0]); - const result = [keys.join("#$#;#$#")]; + const isObj = typeof rows[0] === "object"; + const isPropVal = isObj ? checkIfIsPropVal(keys) : false; + const result = isPropVal ? [] : [keys.join("#$#;header;#$#")]; for (const row of rows) { const values = keys.map((key) => { if (Array.isArray(row[key])) { @@ -216,15 +218,23 @@ export function convertRows(rows: any[]): any[] { }); result.push(values.join("#$#;#$#")); } - return result; + return convertRowsToConsole(result).join("\n") + "\n\n"; } export function convertRowsToConsole(rows: string[]): string[] { if (rows.length === 0) { return []; } - + const haveHeader = rows[0].includes("#$#;header;#$#"); + let header; + if (haveHeader) { + header = rows[0].split("#$#;header;#$#"); + rows.shift(); + } const vector = rows.map((row) => row.split("#$#;#$#")); + if (header) { + vector.unshift(header); + } const columnCounters = vector[0].reduce((counters: number[], _, j) => { const maxLength = vector.reduce( @@ -240,7 +250,11 @@ export function convertRowsToConsole(rows: string[]): string[] { const counter = columnCounters[j]; const diff = counter - value.length; if (diff > 0) { - row[j] = value + " ".repeat(diff); + if (!haveHeader && j !== columnCounters.length - 1) { + row[j] = value + "|" + " ".repeat(diff > 1 ? diff - 1 : diff); + } else { + row[j] = value + " ".repeat(diff); + } } }); }); @@ -249,41 +263,19 @@ export function convertRowsToConsole(rows: string[]): string[] { const totalCount = columnCounters.reduce((sum, count) => sum + count, 0); const totalCounter = "-".repeat(totalCount); - result.splice(1, 0, totalCounter); + if (haveHeader) { + result.splice(1, 0, totalCounter); + } return result; } -export function arrayToTable(data: any[]): any { - // Obter as chaves do primeiro objeto para usar como cabeçalho da tabela - if (!Array.isArray(data) || data.length === 0) { - return data; - } - - const header = Object.keys(data[0]); - - // Calcular o tamanho máximo de cada coluna - const columnLengths = header.map((key) => { - return Math.max(key.length, ...data.map((obj) => String(obj[key]).length)); - }); - - // Converter o cabeçalho em uma string, alinhando os valores - const headerString = header - .map((key, i) => key.padEnd(columnLengths[i])) - .join(" "); - - const separator = header - .map((_, i) => "-".repeat(columnLengths[i])) - .join("---"); - // Converter cada objeto em uma string, alinhando os valores - const rows = data.map((obj) => { - return header - .map((key, i) => String(obj[key]).padEnd(columnLengths[i])) - .join(" "); - }); - - // Juntar o cabeçalho e as linhas para formar a tabela - return [headerString, separator, ...rows].join("\n"); +export function checkIfIsPropVal(columns: string[]): boolean { + return ( + columns.length === 2 && + columns.includes("Property") && + columns.includes("Value") + ); } export function getConnectionType(type: ServerType): string { diff --git a/test/suite/utils.test.ts b/test/suite/utils.test.ts index 2911f6da..f2485fd2 100644 --- a/test/suite/utils.test.ts +++ b/test/suite/utils.test.ts @@ -836,16 +836,31 @@ describe("Utils", () => { b: 4, }, ]; - const expectedRes = ["a#$#;#$#b", "1#$#;#$#2", "3#$#;#$#4"].toString(); + const expectedRes = ["a b \n------\n1 2 \n3 4 \n\n"].toString(); const result = queryUtils.convertRows(rows); assert.equal(result, expectedRes); }); - it("convertRowsToConsole", () => { - const rows = ["a,b", "1,2", "3,4"]; - const expectedRes = ["a,b ", "-----", "1,2 ", "3,4 "].toString(); - const result = queryUtils.convertRowsToConsole(rows); - assert.equal(result, expectedRes); + describe("convertRowsToConsole", () => { + it("should work with headers", () => { + const rows = ["a#$#;header;#$#b", "1#$#;#$#2", "3#$#;#$#4"]; + const expectedRes = ["a b ", "------", "1 2 ", "3 4 "]; + const result = queryUtils.convertRowsToConsole(rows); + assert.deepEqual(result, expectedRes); + }); + it("should work without headers", () => { + const rows = ["a#$#;#$#1", "b#$#;#$#2", "c#$#;#$#3"]; + const expectedRes = ["a| 1 ", "b| 2 ", "c| 3 "]; + const result = queryUtils.convertRowsToConsole(rows); + assert.deepEqual(result, expectedRes); + }); + + it("should work with empty rows", () => { + const rows = []; + const expectedRes = []; + const result = queryUtils.convertRowsToConsole(rows); + assert.deepEqual(result, expectedRes); + }); }); it("getConnectionType", () => { @@ -894,30 +909,6 @@ describe("Utils", () => { assert.deepStrictEqual(result, { error: "Query error" }); }); }); - - describe("arrayToTable", () => { - it("should format an array of objects as a table", () => { - const data = [ - { a: "0", b: "1.4198733294891718e+38" }, - { a: "1", b: "-1.2894694634258276e+29" }, - ]; - - const expected = - "a b \n" + - "---------------------------\n" + - "0 1.4198733294891718e+38 \n" + - "1 -1.2894694634258276e+29"; - - const result = queryUtils.arrayToTable(data); - assert.strictEqual(result, expected); - }); - - it("should return the input if it is not a non-empty array", () => { - const data = []; - const result = queryUtils.arrayToTable(data); - assert.strictEqual(result, data); - }); - }); }); describe("Registration", () => {