Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

results: remove duplicated columns #135

Merged
merged 3 commits into from
Nov 14, 2023
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
26 changes: 20 additions & 6 deletions src/clients/sql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Pool, PoolClient, PoolConfig, QueryResult } from "pg";
import { Pool, PoolClient, PoolConfig, QueryArrayResult, QueryResult } from "pg";
import AdminClient from "./admin";
import CloudClient from "./cloud";
import { Profile } from "../context/config";
Expand Down Expand Up @@ -116,11 +116,12 @@ export default class SqlClient {
* Internal queries are intended for exploring cases.
* Like quering the catalog, or information about Materialize.
* Queries goes to the pool, and no client is kept.
*
* @param statement
* @param values
* @returns query results
*/
async internalQuery(statement: string, values?: Array<any>): Promise<QueryResult<any>> {
async internalQuery(statement: string, values?: Array<any>): Promise<QueryArrayResult<any>> {
const pool = await this.pool;
const results = await pool.query(statement, values);

Expand All @@ -129,15 +130,28 @@ export default class SqlClient {


/**
* Private queries are intended for the user. A private query reuses always the same client.
* In this way, it functions like a shell, processing one statement after another.
* Private queries are intended for the user.
* A private query reuses always the same client.
* In this way, it functions like a shell,
* processing one statement after another.
*
* Another important difference is that
* it returns the values in Array mode.
*
* @param statement
* @param values
* @returns query results
*/
async privateQuery(statement: string, values?: Array<any>): Promise<QueryResult<any>> {
async privateQuery(statement: string, values?: Array<any>): Promise<QueryArrayResult<any>> {
const client = await this.privateClient;
const results = await client.query(statement, values);
// Row mode is a must.
// Otherwise when two columns have the same name, one is dropped
// Issue: https://github.com/brianc/node-postgres/issues/280
const results = await client.query({
rowMode: "array",
text: statement,
values
});

return results;
}
Expand Down
12 changes: 8 additions & 4 deletions src/context/asyncContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Errors, ExtensionError } from "../utilities/error";
import AppPassword from "./appPassword";
import { ActivityLogTreeProvider, AuthProvider, DatabaseTreeProvider, ResultsProvider } from "../providers";
import * as vscode from 'vscode';
import { QueryResult } from "pg";
import { QueryArrayResult, QueryResult } from "pg";
import { ExecuteCommandParseStatement } from "../clients/lsp";

/**
Expand Down Expand Up @@ -389,7 +389,7 @@ export default class AsyncContext extends Context {
* @param vals
* @returns query results
*/
async internalQuery(text: string, vals?: Array<any>) {
async internalQuery(text: string, vals?: Array<any>): Promise<QueryResult<any>> {
const client = await this.getSqlClient();

return await client.internalQuery(text, vals);
Expand All @@ -398,13 +398,17 @@ export default class AsyncContext extends Context {
/**
* Private queries are intended for the user.
* A private query reuses always the same client.
* In this way, it functions like a shell, processing one statement after another.
* In this way, it functions like a shell,
* processing one statement after another.
*
* Another important difference is that
* it returns the values in Array mode.
*
* @param text
* @param vals
* @returns query results
*/
async privateQuery(text: string, vals?: Array<any>) {
async privateQuery(text: string, vals?: Array<any>): Promise<QueryArrayResult<any>> {
const client = await this.getSqlClient();

return await client.privateQuery(text, vals);
Expand Down
89 changes: 0 additions & 89 deletions src/providers/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,6 @@ import * as vscode from 'vscode';
import { randomUUID } from 'crypto';
import AsyncContext from "../context/asyncContext";

// vscode.commands.executeCommand('queryResults.focus').then(async () => {
// const document = activeEditor.document;
// const selection = activeEditor.selection;
// const textSelected = activeEditor.document.getText(selection).trim();
// const query = textSelected ? textSelected : document.getText();
// const fileName = document.fileName;

// // Identify the query to not overlap results.
// // When a user press many times the run query button
// // the results from one query can overlap the results
// // from another. We only want to display the last results.
// const id = randomUUID();

// try {
// // Clean the results by emitting a newQuery event.
// context.emit("event", { type: EventType.newQuery, data: { id } });

// try {
// const statements = await context.parseSql(query);

// console.log("[RunSQLCommand]", "Running statements: ", statements);

// const lastStatement = statements[statements.length - 1];
// for (const statement of statements) {
// console.log("[RunSQLCommand]", "Running statement: ", statement);

// // Benchmark
// const startTime = Date.now();
// try {
// const results = await context.privateQuery(statement.sql);
// const endTime = Date.now();
// const elapsedTime = endTime - startTime;

// console.log("[RunSQLCommand]", "Results: ", results);
// console.log("[RunSQLCommand]", "Emitting results.");

// // Only display the results from the last statement.
// if (lastStatement === statement) {
// if (Array.isArray(results)) {
// context.emit("event", { type: EventType.queryResults, data: { ...results[0], elapsedTime, id } });
// } else {
// context.emit("event", { type: EventType.queryResults, data: { ...results, elapsedTime, id } });
// }
// }
// activityLogProvider.addLog({
// status: "success",
// latency: elapsedTime, // assuming elapsedTime holds the time taken for the query to execute
// sql: statement.sql
// });
// } catch (error: any) {
// console.log("[RunSQLCommand]", error.toString());
// console.log("[RunSQLCommand]", JSON.stringify(error));
// const endTime = Date.now();
// const elapsedTime = endTime - startTime;

// activityLogProvider.addLog({
// status: "failure",
// latency: elapsedTime, // assuming elapsedTime holds the time taken before the error was caught
// sql: statement.sql
// });

// context.emit("event", { type: EventType.queryResults, data: { id, rows: [], fields: [], error: {
// message: error.toString(),
// position: error.position,
// query,
// }, elapsedTime }});
// break;
// } finally {
// resultsProvider._view?.show();
// }
// }
// } catch (err) {
// context.emit("event", { type: EventType.queryResults, data: { id, rows: [], fields: [], error: {
// message: "Syntax errors are present. For more information, please refer to the \"Problems\" tab.",
// position: undefined,
// query,
// }, elapsedTime: undefined }});

// console.error("[RunSQLCommand]", "Error running statement: ", err);
// }
// } catch (err) {
// context.emit("event", { type: EventType.queryResults, data: { id, rows: [], fields: [], error: {
// message: "Error connecting to Materialize.",
// position: undefined,
// query,
// }, elapsedTime: undefined }});
// }
// });

export const buildRunSQLCommand = (context: AsyncContext) => {
const sqlCommand = async () => {
const {
Expand Down
6 changes: 2 additions & 4 deletions src/providers/scripts/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,11 @@
// Create data rows
// Loop through the data and create rows and cells
if (rows && rows.length > 0) {
rows.forEach((row: any, i: number) => {
rows.forEach((row: any) => {
const dataRow = document.createElement("vscode-data-grid-row");

fields.forEach(({ name: field }: { name: string }, index: number) => {
row.forEach((value: any, index: number) => {
const dataCell = document.createElement("vscode-data-grid-cell");
dataCell.setAttribute("grid-column", String(index + 1));
const value = row[field];
dataCell.innerText = typeof value === "object" ? JSON.stringify(value) : value;

dataRow.appendChild(dataCell);
Expand Down