Skip to content

Commit a93a532

Browse files
added csv and json output for run query on instnace
1 parent 281f84a commit a93a532

3 files changed

Lines changed: 112 additions & 3 deletions

File tree

src/stackql.test.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { assertStringIncludes } from "https://deno.land/std@0.206.0/assert/mod.ts";
22
import { StackQL } from "./stackql.ts";
3-
import { startStackQLServer } from "../testing/utils.ts";
3+
import {
4+
isCsvString,
5+
isJsonString,
6+
startStackQLServer,
7+
} from "../testing/utils.ts";
48
import {
59
assertEquals,
610
assertExists,
@@ -117,6 +121,49 @@ Deno.test("Set proxy properties from configs", async () => {
117121
runCommandSpy.restore();
118122
});
119123

124+
Deno.test("run query Output: json", async () => {
125+
await setupStackQL();
126+
const stackQL = new StackQL();
127+
await stackQL.initialize({
128+
serverMode: false,
129+
outputFormat: "json",
130+
});
131+
const githubTestQuery =
132+
`SELECT id, name from github.repos.repos where org='stackql'`;
133+
134+
const result = await stackQL.runQuery(githubTestQuery);
135+
136+
const params = stackQL.getParams();
137+
138+
assertEquals(params, [
139+
"--output",
140+
"json",
141+
]);
142+
assert(isJsonString(result));
143+
assert(!(await isCsvString(result)));
144+
});
145+
146+
Deno.test("run query Output: csv", async () => {
147+
await setupStackQL();
148+
const stackQL = new StackQL();
149+
await stackQL.initialize({
150+
serverMode: false,
151+
outputFormat: "csv",
152+
});
153+
const githubTestQuery =
154+
`SELECT id, name from github.repos.repos where org='stackql'`;
155+
156+
const result = await stackQL.runQuery(githubTestQuery);
157+
const params = stackQL.getParams();
158+
159+
assertEquals(params, [
160+
"--output",
161+
"csv",
162+
]);
163+
assert(!isJsonString(result));
164+
assert(await isCsvString(result));
165+
});
166+
120167
Deno.test("StackQL runServerQuery", async () => {
121168
const { closeProcess } = await startStackQLServer();
122169
const stackQL = new StackQL();

src/stackql.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ export interface StackQLConfig {
1717
proxyUser?: string;
1818
proxyPassword?: string;
1919
proxyScheme?: "http" | "https";
20+
outputFormat?: "csv" | "json";
2021
}
2122

2223
export class StackQL {
2324
private binaryPath?: string; //The full path of the `stackql` executable (not supported in `server_mode`).
2425
private downloader: Downloader = new Downloader();
2526
private serverMode = false;
2627
private connection?: Client;
27-
private format: "object" = "object";
28+
private outputFormat: "csv" | "json" = "json";
2829
private params: string[] = [];
2930
private version: string | undefined; // The version number of the `stackql` executable (not supported in `server_mode`)
3031
private sha: string | undefined; // The commit (short) sha for the installed `stackql` binary build (not supported in `server_mode`).
@@ -47,6 +48,13 @@ export class StackQL {
4748
return { version: this.version, sha: this.sha };
4849
}
4950

51+
async execute(query: string) {
52+
if (this.serverMode) {
53+
const result = await this.runServerQuery(query);
54+
}
55+
return await this.runQuery(query);
56+
}
57+
5058
private async updateVersion() {
5159
if (!this.binaryPath) {
5260
throw new Error("Binary path not found");
@@ -61,12 +69,22 @@ export class StackQL {
6169
this.sha = sha;
6270
}
6371
}
72+
73+
/**
74+
* Upgrade the `stackql` executable to the latest version
75+
* @returns The version number of the `stackql` executable (not supported in `server_mode`)
76+
*/
6477
async upgrade() {
6578
this.binaryPath = await this.downloader.upgradeStackQL();
6679
await this.updateVersion();
6780
return this.getVersion();
6881
}
6982

83+
/**
84+
* Initialize the `stackql` executable
85+
* @param config The configuration object
86+
* @returns The binary path of the `stackql` executable if `server_mode` is `false`, otherwise `undefined`
87+
*/
7088
public async initialize(config: StackQLConfig) {
7189
this.binaryPath = config.binaryPath;
7290
this.serverMode = config.serverMode || false;
@@ -80,6 +98,7 @@ export class StackQL {
8098
this.binaryPath = await this.downloader.setupStackQL();
8199
this.setProperties(config);
82100
}
101+
83102
private binaryExist() {
84103
return !!this.binaryPath && osUtils.fileExists(this.binaryPath);
85104
}
@@ -139,8 +158,24 @@ export class StackQL {
139158
if (config.proxyHost !== undefined) {
140159
this.setProxyProperties(config);
141160
}
161+
162+
if (config.outputFormat !== undefined) {
163+
if (!["csv", "json"].includes(config.outputFormat)) {
164+
throw new Error(
165+
`Invalid outputFormat. Expected one of ['csv', 'json'], got ${config.outputFormat}.`,
166+
);
167+
}
168+
this.params.push("--output");
169+
this.params.push(config.outputFormat);
170+
this.outputFormat = config.outputFormat;
171+
}
142172
}
143173

174+
/**
175+
* Run a StackQL query
176+
* @param query The StackQL query
177+
* @returns The result of the query
178+
*/
144179
public async runQuery(query: string) {
145180
assertExists(this.binaryPath);
146181
const args = ["exec", query].concat(this.params);
@@ -165,15 +200,23 @@ export class StackQL {
165200
this.connection = await server.connect(connectionString);
166201
}
167202

203+
/**
204+
* Close the connection to the stackql server
205+
*/
168206
public async closeConnection() {
169207
if (this.connection) {
170208
await this.connection.end();
171209
}
172210
}
173211

212+
/**
213+
* Run a StackQL query on the server
214+
* @param query The StackQL query
215+
* @returns The result of the query
216+
*/
174217
public async runServerQuery(query: string) {
175218
try {
176-
if (this.format === "object") {
219+
if (this.outputFormat === "json") {
177220
const result = await this.queryObjectFormat(query);
178221
return result;
179222
}

testing/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { existsSync } from "https://deno.land/std/fs/mod.ts";
22
import { join } from "https://deno.land/std@0.133.0/path/mod.ts";
3+
import { parse } from "https://deno.land/std@0.134.0/encoding/csv.ts";
34

45
export const removeStackQLDownload = async () => {
56
const projectDir = Deno.cwd();
@@ -42,3 +43,21 @@ export const startStackQLServer = async (port = 5444) => {
4243
};
4344
return { closeProcess };
4445
};
46+
47+
export const isJsonString = (str: string) => {
48+
try {
49+
JSON.parse(str);
50+
} catch (_error) {
51+
return false;
52+
}
53+
return true;
54+
};
55+
56+
export const isCsvString = async (str: string) => {
57+
try {
58+
await parse(str);
59+
} catch (_error) {
60+
return false;
61+
}
62+
return true;
63+
};

0 commit comments

Comments
 (0)